@classytic/mongokit 3.36.0 → 3.39.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-CBS1XGzp.d.mts → PaginationEngine-D-P19Y9m.d.mts} +34 -9
- package/dist/PaginationEngine-DQ7beTCR.mjs +1182 -0
- package/dist/{Repository-BArvU32x.mjs → Repository-D7fDpyFx.mjs} +405 -37
- package/dist/{Repository-BdSkQ8vc.d.mts → Repository-IxI983_m.d.mts} +55 -8
- package/dist/actions/index.d.mts +1 -1
- package/dist/actions/index.mjs +1 -1
- package/dist/adapter/index.d.mts +21 -0
- package/dist/adapter/index.mjs +1 -1
- package/dist/{adapter-Bfqz8yHE.mjs → adapter-BrVfPFSW.mjs} +45 -1
- package/dist/ai/index.d.mts +1 -1
- package/dist/better-auth/index.d.mts +78 -1
- package/dist/better-auth/index.mjs +233 -3
- package/dist/{create-repository-BU4x9Kb0.d.mts → create-repository-CRXjDa3N.d.mts} +5 -5
- package/dist/{create-repository-CPNbktFG.mjs → create-repository-DOe9E_5F.mjs} +3 -3
- package/dist/{index-DKEql4cL.d.mts → index-CmjNyulu.d.mts} +67 -8
- package/dist/index.d.mts +77 -13
- package/dist/index.mjs +31 -8
- package/dist/indexes/verify-indexes.d.mts +69 -0
- package/dist/indexes/verify-indexes.mjs +76 -0
- package/dist/{method-registry.plugin-DblM7V6j.mjs → method-registry.plugin-C63pGn1d.mjs} +54 -4
- package/dist/{multi-tenant.plugin-BwSvTirB.d.mts → multi-tenant.plugin-B-tzNeYL.d.mts} +60 -4
- package/dist/{operations-DZodvjC-.d.mts → operations-CrRIoc8Z.d.mts} +22 -7
- package/dist/outbox/index.d.mts +1 -1
- package/dist/outbox/index.mjs +2 -2
- package/dist/pagination/PaginationEngine.d.mts +1 -1
- package/dist/pagination/PaginationEngine.mjs +1 -1
- package/dist/pagination/utils/limits.d.mts +47 -0
- package/dist/pagination/utils/limits.mjs +85 -0
- package/dist/pagination-BpIv2bdS.d.mts +364 -0
- package/dist/{plugin-options-DXnlKM3B.d.mts → plugin-options-BuvtOSZf.d.mts} +2 -2
- package/dist/plugins/index.d.mts +3 -3
- package/dist/plugins/index.mjs +3 -3
- package/dist/{repository-H_ffGgpE.d.mts → repository-ZbLtL7Nk.d.mts} +30 -4
- package/dist/tenant/index.d.mts +89 -0
- package/dist/tenant/index.mjs +94 -0
- package/dist/testkit/index.d.mts +2 -2
- package/dist/testkit/index.mjs +1 -1
- package/dist/{timestamp.plugin-BEc6TANm.mjs → timestamp.plugin-B5eiaItQ.mjs} +75 -8
- package/dist/{to-plain-Dyz_qvuo.d.mts → to-plain-B8ufk3Qz.d.mts} +2 -2
- package/dist/{update-jSXp3nu3.mjs → update-c_01A0if.mjs} +126 -73
- package/dist/utils/index.d.mts +1 -1
- package/dist/{validation-chain.plugin-CyK1s9Ze.mjs → validation-chain.plugin-Bju1D1Sn.mjs} +2 -2
- package/dist/{validation-chain.plugin-yQRob3Av.d.mts → validation-chain.plugin-DvrLJIbJ.d.mts} +3 -19
- package/package.json +15 -3
- package/dist/PaginationEngine-GdyX29tE.mjs +0 -797
- package/dist/core-62oo3N1C.d.mts +0 -50
- package/dist/pagination-jSUdrACK.d.mts +0 -158
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { _ as UpdateOptions, a as CreateOptions, b as LookupOptions, c as FindOneAndUpdateOptions, f as MinMaxResult, g as UpdateManyResult, l as GroupResult, p as OperationOptions, s as DeleteResult } from "./operations-
|
|
2
|
-
import {
|
|
1
|
+
import { _ as UpdateOptions, a as CreateOptions, b as LookupOptions, c as FindOneAndUpdateOptions, f as MinMaxResult, g as UpdateManyResult, l as GroupResult, p as OperationOptions, s as DeleteResult } from "./operations-CrRIoc8Z.mjs";
|
|
2
|
+
import { _ as PopulateSpec, g as ObjectId, p as AnyDocument, v as ReadPreferenceType, x as SortSpec, y as SelectSpec } from "./pagination-BpIv2bdS.mjs";
|
|
3
3
|
import { p as UpdateWithValidationResult } from "./type-utils-CLzRFtIA.mjs";
|
|
4
4
|
import { Model, PipelineStage } from "mongoose";
|
|
5
5
|
declare namespace aggregate_d_exports {
|
|
@@ -12,9 +12,18 @@ declare function aggregate<TResult = unknown>(Model: Model<any>, pipeline: Pipel
|
|
|
12
12
|
session?: unknown;
|
|
13
13
|
}): Promise<TResult[]>;
|
|
14
14
|
/**
|
|
15
|
-
* Aggregate with pagination
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Aggregate with pagination.
|
|
16
|
+
*
|
|
17
|
+
* Page and count run as TWO concurrent pipelines rather than one `$facet`.
|
|
18
|
+
* `$facet` bundles every returned document plus the count into a SINGLE output
|
|
19
|
+
* document, and no stage may exceed 16MB — so a page of large documents failed
|
|
20
|
+
* with `BSONObjectTooLarge` instead of paginating, and the only defence was a
|
|
21
|
+
* warning above an arbitrary limit of 1000 that told the caller to go
|
|
22
|
+
* elsewhere. `$facet` also cannot use an index for the stages inside it.
|
|
23
|
+
*
|
|
24
|
+
* The trade: two reads, so a concurrent write between them can leave `total`
|
|
25
|
+
* a document out of step with `data` — the same trade `PaginationEngine`
|
|
26
|
+
* already makes on both its offset and aggregate paths.
|
|
18
27
|
*/
|
|
19
28
|
declare function aggregatePaginate<TDoc = AnyDocument>(Model: Model<TDoc>, pipeline: PipelineStage[], options?: {
|
|
20
29
|
page?: number;
|
|
@@ -91,14 +100,64 @@ declare function minMax(Model: Model<any>, field: string, query?: Record<string,
|
|
|
91
100
|
session?: unknown;
|
|
92
101
|
}): Promise<MinMaxResult>;
|
|
93
102
|
declare namespace create_d_exports {
|
|
94
|
-
export { create, createDefault, createMany, upsert };
|
|
103
|
+
export { CreateManyFailure, CreateManyPartial, CreateManyPartialError, create, createDefault, createMany, isCreateManyPartialError, upsert };
|
|
95
104
|
}
|
|
96
105
|
/**
|
|
97
106
|
* Create single document
|
|
98
107
|
*/
|
|
99
108
|
declare function create<TDoc = AnyDocument>(Model: Model<TDoc>, data: Record<string, unknown>, options?: CreateOptions): Promise<TDoc>;
|
|
100
109
|
/**
|
|
101
|
-
*
|
|
110
|
+
* One rejected input, keyed by its position in the array that was passed in.
|
|
111
|
+
*
|
|
112
|
+
* The index is the load-bearing part: it is the only way to tie a failure back
|
|
113
|
+
* to the caller's own record — the driver reports failures positionally, and a
|
|
114
|
+
* rejected document never comes back with an `_id` to match on.
|
|
115
|
+
*/
|
|
116
|
+
interface CreateManyFailure {
|
|
117
|
+
/** Position in the ORIGINAL `dataArray`. */
|
|
118
|
+
index: number;
|
|
119
|
+
/** The input that was rejected, as supplied. */
|
|
120
|
+
doc: Record<string, unknown>;
|
|
121
|
+
/** MongoDB error code, e.g. 11000 for a duplicate key. */
|
|
122
|
+
code?: number;
|
|
123
|
+
message: string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* What a partially-successful `createMany` actually did.
|
|
127
|
+
*
|
|
128
|
+
* Attached to the thrown error as `partial`. `createMany` still REJECTS — that
|
|
129
|
+
* is unchanged and deliberate — but the rejection now says which documents
|
|
130
|
+
* landed and which did not, instead of leaving the caller to dig through a
|
|
131
|
+
* driver error to find out.
|
|
132
|
+
*/
|
|
133
|
+
interface CreateManyPartial<TDoc = AnyDocument> {
|
|
134
|
+
/** Documents the server accepted. */
|
|
135
|
+
inserted: TDoc[];
|
|
136
|
+
/** Every rejected input, in input order. */
|
|
137
|
+
failed: CreateManyFailure[];
|
|
138
|
+
}
|
|
139
|
+
/** The error `createMany` throws when some documents landed and some did not. */
|
|
140
|
+
type CreateManyPartialError<TDoc = AnyDocument> = Error & {
|
|
141
|
+
partial?: CreateManyPartial<TDoc>;
|
|
142
|
+
};
|
|
143
|
+
/** Narrow a caught error to one carrying a partial-write report. */
|
|
144
|
+
declare function isCreateManyPartialError<TDoc = AnyDocument>(err: unknown): err is CreateManyPartialError<TDoc> & {
|
|
145
|
+
partial: CreateManyPartial<TDoc>;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Create multiple documents.
|
|
149
|
+
*
|
|
150
|
+
* **A rejection does NOT mean nothing was written.** Neither ordering does:
|
|
151
|
+
* `ordered: true` stops at the first failure and keeps everything before it,
|
|
152
|
+
* `ordered: false` keeps everything valid. Measured on a six-document batch
|
|
153
|
+
* with a conflict in the middle — ordered wrote 3, unordered wrote 5. Only a
|
|
154
|
+
* transaction gives all-or-nothing.
|
|
155
|
+
*
|
|
156
|
+
* So the rejection carries a `partial` report naming what landed and what did
|
|
157
|
+
* not, because the alternative is a caller retrying the whole batch and
|
|
158
|
+
* double-writing everything that had already succeeded. Use it to retry only
|
|
159
|
+
* `failed`, or to reconcile — and prefer a unique index or an idempotency key
|
|
160
|
+
* for anything that will be retried automatically.
|
|
102
161
|
*/
|
|
103
162
|
declare function createMany<TDoc = AnyDocument>(Model: Model<TDoc>, dataArray: Record<string, unknown>[], options?: CreateOptions): Promise<TDoc[]>;
|
|
104
163
|
/**
|
|
@@ -301,4 +360,4 @@ declare namespace index_d_exports {
|
|
|
301
360
|
export { aggregate_d_exports as aggregate, create_d_exports as create, delete_d_exports as deleteActions, read_d_exports as read, update_d_exports as update };
|
|
302
361
|
}
|
|
303
362
|
//#endregion
|
|
304
|
-
export {
|
|
363
|
+
export { CreateManyFailure as a, create_d_exports as c, delete_d_exports as i, isCreateManyPartialError as l, update_d_exports as n, CreateManyPartial as o, read_d_exports as r, CreateManyPartialError as s, index_d_exports as t, aggregate_d_exports as u };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import { _ as UpdateOptions, a as CreateOptions, b as LookupOptions, c as FindOneAndUpdateOptions, d as LookupPopulateResult, f as MinMaxResult, g as UpdateManyResult, h as SessionOptions, i as ConvenientTransactionOptions, l as GroupResult, m as ReadOptions, n as CacheOperationOptions, p as OperationOptions, r as CacheableOptions, s as DeleteResult, t as AggregateOptions, u as LookupPopulateOptions, v as WithTransactionOptions, y as LookupBuilder } from "./operations-
|
|
2
|
-
import {
|
|
3
|
-
import { a as
|
|
4
|
-
import { t as index_d_exports } from "./index-DKEql4cL.mjs";
|
|
1
|
+
import { _ as UpdateOptions, a as CreateOptions, b as LookupOptions, c as FindOneAndUpdateOptions, d as LookupPopulateResult, f as MinMaxResult, g as UpdateManyResult, h as SessionOptions, i as ConvenientTransactionOptions, l as GroupResult, m as ReadOptions, n as CacheOperationOptions, p as OperationOptions, r as CacheableOptions, s as DeleteResult, t as AggregateOptions, u as LookupPopulateOptions, v as WithTransactionOptions, y as LookupBuilder } from "./operations-CrRIoc8Z.mjs";
|
|
2
|
+
import { _ as PopulateSpec, a as CursorPayload, b as SortDirection, c as MongokitPageExtras, d as ValueType, f as CursorSecret, g as ObjectId, i as CountStrategy, l as OffsetPaginationOptions, m as AnyModel, n as BasePaginationOptions, o as DecodedCursor, p as AnyDocument, r as CollationOptions, s as KeysetPaginationOptions, t as AggregatePaginationOptions, u as PaginationConfig, v as ReadPreferenceType, x as SortSpec$1, y as SelectSpec } from "./pagination-BpIv2bdS.mjs";
|
|
3
|
+
import { a as CreateManyFailure, l as isCreateManyPartialError, o as CreateManyPartial, s as CreateManyPartialError, t as index_d_exports } from "./index-CmjNyulu.mjs";
|
|
5
4
|
import { a as InferRawDoc, c as NonNullableFields, d as Strict, f as UpdatePatch, i as InferDocument, l as PartialBy, n as DeepPartial, o as KeysOfType, p as UpdateWithValidationResult, r as DocField, s as MongoOperatorUpdate, t as CreateInput, u as RequiredBy } from "./type-utils-CLzRFtIA.mjs";
|
|
6
|
-
import { S as RepositoryPluginName, _ as RepositoryOptions, a as HookMode, b as MONGOKIT_PLUGIN_NAMES, c as MinimalRepoView, d as PluginType, f as PrioritizedHook, g as RepositoryOperation, h as RepositoryInstance, i as EventPhase, l as Plugin, m as RepositoryEvent, n as EventHandlers, o as Middleware, p as RepositoryContext, r as EventPayload, s as MiddlewareContext, t as AllPluginMethods, u as PluginFunction, v as UserContext, x as MongoKitPluginName, y as WithPlugins } from "./repository-
|
|
7
|
-
import { A as ensureAuditTrailReady, C as AuditTrailMethods, D as AuditTrailQueryOptions, E as AuditTrailQuery, O as EnsureAuditTrailReadyOptions, S as AuditQueryResult, T as AuditTrailOptions, _ as RepositoryCachePluginOptions, a as DateSequentialIdOptions, b as AuditOperation, c as SequentialIdOptions, d as getNextSequence, f as prefixedId, g as RepositoryCacheHandle, h as CacheOptions, i as CustomIdOptions, k as auditTrailPlugin, l as customIdPlugin, m as CacheAdapter, n as adminBypass, o as IdGenerator, p as sequentialId, r as multiTenantPlugin, s as PrefixedIdOptions, t as MultiTenantOptions, u as dateSequentialId, v as cachePlugin, w as AuditTrailMode, x as AuditQueryOptions, y as AuditEntry } from "./multi-tenant.plugin-
|
|
8
|
-
import { t as PaginationEngine } from "./PaginationEngine-
|
|
9
|
-
import { a as AggregationPlan, c as SortOrder, i as AggregationBuilder, l as SortSpec, n as Repository, o as GroupSpec, r as TransitionMachine, s as ProjectionSpec, t as HOOK_PRIORITY, u as VectorSearchOptions } from "./Repository-
|
|
10
|
-
import { a as SoftDeleteFilterMode, c as ValidationChainOptions, i as Logger, l as ValidatorDefinition, n as CascadeRelation, o as SoftDeleteOptions, r as FieldPreset, s as SoftDeleteRepository, t as CascadeOptions } from "./plugin-options-
|
|
11
|
-
import { n as CreateRepositoryConfig, r as createRepository, t as AuditConfig } from "./create-repository-
|
|
12
|
-
import { A as IdempotencyStoreMethods, B as auditLogPlugin, C as LeaseMethods, D as ImmutableStatesPluginOptions, E as ImmutableClaimView, F as elasticSearchPlugin, H as appendOnlyPlugin, I as cascadePlugin, L as BatchOperationsMethods, M as idempotencyStorePlugin, N as fieldFilterPlugin, O as immutableStatesPlugin, P as ElasticSearchOptions, R as BulkWriteResult, S as methodRegistryPlugin, T as leasePlugin, U as AggregateHelpersMethods, V as AppendOnlyPluginOptions, W as aggregateHelpersPlugin, _ as OperationMetric, a as requireField, b as mongoOperationsPlugin, c as timestampPlugin, d as createTenantContext, f as SubdocumentMethods, g as ObservabilityOptions, h as softDeletePlugin, i as immutableField, j as IdempotencyStorePluginOptions, k as IdempotencyClaim, l as TenantContext, m as SoftDeleteMethods, n as autoInject, o as uniqueField, p as subdocumentPlugin, r as blockIf, s as validationChainPlugin, t as OperationType, u as TenantStore, v as observabilityPlugin, w as LeasePluginOptions, y as MongoOperationsMethods, z as batchOperationsPlugin } from "./validation-chain.plugin-
|
|
5
|
+
import { S as RepositoryPluginName, _ as RepositoryOptions, a as HookMode, b as MONGOKIT_PLUGIN_NAMES, c as MinimalRepoView, d as PluginType, f as PrioritizedHook, g as RepositoryOperation, h as RepositoryInstance, i as EventPhase, l as Plugin, m as RepositoryEvent, n as EventHandlers, o as Middleware, p as RepositoryContext, r as EventPayload, s as MiddlewareContext, t as AllPluginMethods, u as PluginFunction, v as UserContext, x as MongoKitPluginName, y as WithPlugins } from "./repository-ZbLtL7Nk.mjs";
|
|
6
|
+
import { A as ensureAuditTrailReady, C as AuditTrailMethods, D as AuditTrailQueryOptions, E as AuditTrailQuery, O as EnsureAuditTrailReadyOptions, S as AuditQueryResult, T as AuditTrailOptions, _ as RepositoryCachePluginOptions, a as DateSequentialIdOptions, b as AuditOperation, c as SequentialIdOptions, d as getNextSequence, f as prefixedId, g as RepositoryCacheHandle, h as CacheOptions, i as CustomIdOptions, k as auditTrailPlugin, l as customIdPlugin, m as CacheAdapter, n as adminBypass, o as IdGenerator, p as sequentialId, r as multiTenantPlugin, s as PrefixedIdOptions, t as MultiTenantOptions, u as dateSequentialId, v as cachePlugin, w as AuditTrailMode, x as AuditQueryOptions, y as AuditEntry } from "./multi-tenant.plugin-B-tzNeYL.mjs";
|
|
7
|
+
import { t as PaginationEngine } from "./PaginationEngine-D-P19Y9m.mjs";
|
|
8
|
+
import { a as AggregationPlan, c as SortOrder, i as AggregationBuilder, l as SortSpec, n as Repository, o as GroupSpec, r as TransitionMachine, s as ProjectionSpec, t as HOOK_PRIORITY, u as VectorSearchOptions } from "./Repository-IxI983_m.mjs";
|
|
9
|
+
import { a as SoftDeleteFilterMode, c as ValidationChainOptions, i as Logger, l as ValidatorDefinition, n as CascadeRelation, o as SoftDeleteOptions, r as FieldPreset, s as SoftDeleteRepository, t as CascadeOptions } from "./plugin-options-BuvtOSZf.mjs";
|
|
10
|
+
import { n as CreateRepositoryConfig, r as createRepository, t as AuditConfig } from "./create-repository-CRXjDa3N.mjs";
|
|
11
|
+
import { A as IdempotencyStoreMethods, B as auditLogPlugin, C as LeaseMethods, D as ImmutableStatesPluginOptions, E as ImmutableClaimView, F as elasticSearchPlugin, H as appendOnlyPlugin, I as cascadePlugin, L as BatchOperationsMethods, M as idempotencyStorePlugin, N as fieldFilterPlugin, O as immutableStatesPlugin, P as ElasticSearchOptions, R as BulkWriteResult, S as methodRegistryPlugin, T as leasePlugin, U as AggregateHelpersMethods, V as AppendOnlyPluginOptions, W as aggregateHelpersPlugin, _ as OperationMetric, a as requireField, b as mongoOperationsPlugin, c as timestampPlugin, d as createTenantContext, f as SubdocumentMethods, g as ObservabilityOptions, h as softDeletePlugin, i as immutableField, j as IdempotencyStorePluginOptions, k as IdempotencyClaim, l as TenantContext, m as SoftDeleteMethods, n as autoInject, o as uniqueField, p as subdocumentPlugin, r as blockIf, s as validationChainPlugin, t as OperationType, u as TenantStore, v as observabilityPlugin, w as LeasePluginOptions, y as MongoOperationsMethods, z as batchOperationsPlugin } from "./validation-chain.plugin-DvrLJIbJ.mjs";
|
|
13
12
|
import { n as SchemaPathsLike, t as FieldType$1 } from "./coercion-BjdPX3YF.mjs";
|
|
14
13
|
import { n as SchemaIndexes } from "./indexes-DIjMpYES.mjs";
|
|
15
|
-
import { S as parseDuplicateKeyError, _ as getMongooseProjection, a as createMemoryCache, b as createError, g as getFieldsForUser, h as filterResponseData, i as buildCrudSchemasFromMongooseSchema, m as createFieldPreset, n as CrudSchemasFramework, o as LoggerConfig, r as buildCrudSchemasFromModel, s as configureLogger, t as toPlain, u as idVariants, v as CreateErrorOptions, x as isDuplicateKeyError, y as ParseDuplicateKeyOptions } from "./to-plain-
|
|
14
|
+
import { S as parseDuplicateKeyError, _ as getMongooseProjection, a as createMemoryCache, b as createError, g as getFieldsForUser, h as filterResponseData, i as buildCrudSchemasFromMongooseSchema, m as createFieldPreset, n as CrudSchemasFramework, o as LoggerConfig, r as buildCrudSchemasFromModel, s as configureLogger, t as toPlain, u as idVariants, v as CreateErrorOptions, x as isDuplicateKeyError, y as ParseDuplicateKeyOptions } from "./to-plain-B8ufk3Qz.mjs";
|
|
16
15
|
import { RepoCapabilities } from "@classytic/repo-core/repository";
|
|
17
16
|
import { ClientSession, Connection, Model, PipelineStage, Schema } from "mongoose";
|
|
18
17
|
//#region src/actions/cascade-references.d.ts
|
|
@@ -396,6 +395,71 @@ declare const READ_OPERATIONS: readonly RepositoryOperation[];
|
|
|
396
395
|
/** Filter ops by their policy injection key. */
|
|
397
396
|
declare function operationsByPolicyKey(key: PolicyKey): RepositoryOperation[];
|
|
398
397
|
//#endregion
|
|
398
|
+
//#region src/pagination/defaults.d.ts
|
|
399
|
+
/**
|
|
400
|
+
* The subset of {@link PaginationConfig} that describes a deployment rather
|
|
401
|
+
* than one collection's shape.
|
|
402
|
+
*
|
|
403
|
+
* Deliberately NOT `defaultLimit` / `maxLimit` / `cursorVersion`: those are
|
|
404
|
+
* per-collection judgements (a line-item list and an audit log want different
|
|
405
|
+
* page sizes), and a process-wide override of them would be a surprise rather
|
|
406
|
+
* than a policy. What is here is the scale policy — how a page is walked, and
|
|
407
|
+
* whether the rows behind it are counted — plus the one SECURITY setting that
|
|
408
|
+
* is deployment-wide by nature: a signing key is one key for the process, and a
|
|
409
|
+
* repository that quietly declined to use it would be the hole.
|
|
410
|
+
*/
|
|
411
|
+
interface PaginationDefaults {
|
|
412
|
+
/** See {@link PaginationConfig.defaultCountStrategy}. */
|
|
413
|
+
defaultCountStrategy?: CountStrategy;
|
|
414
|
+
/**
|
|
415
|
+
* See {@link PaginationConfig.defaultCountLimit}.
|
|
416
|
+
*
|
|
417
|
+
* Belongs to the deployment for the same reason the strategy does: it is the
|
|
418
|
+
* point past which this business stops caring about an exact row count, which
|
|
419
|
+
* is one answer for the whole process, not per collection.
|
|
420
|
+
*/
|
|
421
|
+
defaultCountLimit?: number;
|
|
422
|
+
/**
|
|
423
|
+
* See {@link PaginationConfig.cursorSecret}.
|
|
424
|
+
*
|
|
425
|
+
* The reason this one MUST be reachable here: a kernel builds its own
|
|
426
|
+
* repositories, so without the policy seam a host could sign the cursors it
|
|
427
|
+
* mints itself while every engine-owned list kept issuing unsigned ones — a
|
|
428
|
+
* half-signed deployment, which is an unsigned deployment.
|
|
429
|
+
*/
|
|
430
|
+
cursorSecret?: CursorSecret;
|
|
431
|
+
/** See {@link PaginationConfig.defaultMode}. */
|
|
432
|
+
defaultMode?: 'offset' | 'keyset';
|
|
433
|
+
/**
|
|
434
|
+
* See {@link PaginationConfig.maxPage}.
|
|
435
|
+
*
|
|
436
|
+
* The other half of the offset cost: `skip(n)` walks n index entries before
|
|
437
|
+
* returning anything, so an unbounded page number is an unbounded read. A
|
|
438
|
+
* fleet that has moved to keyset can lower this to make the offset path's
|
|
439
|
+
* remaining callers fail loudly instead of quietly costing a scan.
|
|
440
|
+
*/
|
|
441
|
+
maxPage?: number;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Set the deployment's pagination policy. Merges into whatever is already set,
|
|
445
|
+
* so two call sites configuring different keys do not clobber each other.
|
|
446
|
+
*
|
|
447
|
+
* Call it at boot, before composing modules. Ordering is not load-bearing —
|
|
448
|
+
* repositories read this at query time, not construction time — but a call
|
|
449
|
+
* made after traffic starts changes behaviour mid-flight, which is rarely what
|
|
450
|
+
* anyone means.
|
|
451
|
+
*/
|
|
452
|
+
declare function configurePaginationDefaults(defaults: PaginationDefaults): void;
|
|
453
|
+
/**
|
|
454
|
+
* The current deployment policy. Empty until something configures it.
|
|
455
|
+
*
|
|
456
|
+
* A COPY — `Readonly<T>` is erased at runtime, and handing out the live object
|
|
457
|
+
* would let a caller mutate the policy through a getter that promised not to.
|
|
458
|
+
*/
|
|
459
|
+
declare function getPaginationDefaults(): Readonly<PaginationDefaults>;
|
|
460
|
+
/** Back to library defaults. For tests — a global that cannot be reset is a leak between them. */
|
|
461
|
+
declare function resetPaginationDefaults(): void;
|
|
462
|
+
//#endregion
|
|
399
463
|
//#region src/query/parser/types.d.ts
|
|
400
464
|
type SortSpec$2 = Record<string, 1 | -1>;
|
|
401
465
|
type FilterQuery = Record<string, unknown>;
|
|
@@ -972,4 +1036,4 @@ declare function createOptionsExtractor<TCtx extends Record<string, unknown>>(fi
|
|
|
972
1036
|
*/
|
|
973
1037
|
declare function systemContext(extra?: SessionOptions): SessionOptions;
|
|
974
1038
|
//#endregion
|
|
975
|
-
export { ALL_OPERATIONS, 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 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 ConvenientTransactionOptions, type CreateErrorOptions, type CreateInput, type CreateOptions, type CreateRepositoryConfig, type CrudSchemasFramework, type CursorPayload, 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 GroupResult, type GroupSpec, HOOK_PRIORITY, type HookMode, type IdGenerator, type IdempotencyClaim, type IdempotencyStoreMethods, type IdempotencyStorePluginOptions, type ImmutableClaimView, type ImmutableStatesPluginOptions, type InferDocument, type InferRawDoc, type KeysOfType, type KeysetPaginationOptions, 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 MultiTenantOptions, type NonNullableFields, OP_REGISTRY, type ObjectId, type ObservabilityOptions, type OffsetPaginationOptions, type OperationDescriptor, type OperationMetric, type OperationOptions, type OperationType, type PaginationConfig, PaginationEngine, type ParseDuplicateKeyOptions, type ParsedQuery, type PartialBy, type Plugin, type PluginFunction, type PluginType, type PolicyKey, type PopulateOption, type PopulateSpec, type PrefixedIdOptions, type PrioritizedHook, type ProjectionSpec, type PurgeMode, type PurgeableRepoLike, QueryParser, type QueryParserOptions, type QuerySchema, READ_OPERATIONS, type ReadOptions, type ReadPreferenceType, type ReferencePurgeResult, type ReferenceRelation, Repository, Repository as default, type RepositoryCacheHandle, type RepositoryCachePluginOptions, type RepositoryContext, type RepositoryEvent, type RepositoryInstance, type RepositoryOperation, type RepositoryOptions, type RepositoryPluginName, type RequiredBy, 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, index_d_exports as actions, adminBypass, aggregateHelpersPlugin, appendOnlyPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, capabilitiesForSupport, cascadePlugin, cascadePurgeReferences, classifyHelloReply, compileFilterToMongo, configureLogger, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, defineModel, defineModels, elasticSearchPlugin, ensureAuditTrailReady, fieldFilterPlugin, filterResponseData, getFieldsForUser, getMongooseProjection, getNextSequence, idVariants, idempotencyStorePlugin, immutableField, immutableStatesPlugin, isDuplicateKeyError, isModelRegistered, isTransactionUnsupported, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, probeMongoCapabilities, repoOptionsFromCtx, requireField, resetCapabilityProbeCache, resolveMongoCapabilities, resolveTransactionSupport, sequentialId, softDeletePlugin, subdocumentPlugin, supportsTransactions, systemContext, timestampPlugin, toPlain, transactionResolutionOf, uniqueField, validationChainPlugin, withTransaction };
|
|
1039
|
+
export { ALL_OPERATIONS, 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 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 ConvenientTransactionOptions, 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 GroupResult, type GroupSpec, HOOK_PRIORITY, type HookMode, type IdGenerator, type IdempotencyClaim, type IdempotencyStoreMethods, type IdempotencyStorePluginOptions, type ImmutableClaimView, type ImmutableStatesPluginOptions, type InferDocument, type InferRawDoc, type KeysOfType, type KeysetPaginationOptions, 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, type PaginationConfig, type PaginationDefaults, PaginationEngine, type ParseDuplicateKeyOptions, type ParsedQuery, type PartialBy, type Plugin, type PluginFunction, type PluginType, type PolicyKey, type PopulateOption, type PopulateSpec, type PrefixedIdOptions, type PrioritizedHook, type ProjectionSpec, type PurgeMode, type PurgeableRepoLike, QueryParser, type QueryParserOptions, type QuerySchema, READ_OPERATIONS, type ReadOptions, type ReadPreferenceType, type ReferencePurgeResult, type ReferenceRelation, Repository, Repository as default, type RepositoryCacheHandle, type RepositoryCachePluginOptions, type RepositoryContext, type RepositoryEvent, type RepositoryInstance, type RepositoryOperation, type RepositoryOptions, type RepositoryPluginName, type RequiredBy, 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, index_d_exports as actions, adminBypass, aggregateHelpersPlugin, appendOnlyPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, capabilitiesForSupport, cascadePlugin, cascadePurgeReferences, classifyHelloReply, compileFilterToMongo, configureLogger, configurePaginationDefaults, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, defineModel, defineModels, elasticSearchPlugin, ensureAuditTrailReady, fieldFilterPlugin, filterResponseData, getFieldsForUser, getMongooseProjection, getNextSequence, getPaginationDefaults, idVariants, idempotencyStorePlugin, immutableField, immutableStatesPlugin, isCreateManyPartialError, isDuplicateKeyError, isModelRegistered, isTransactionUnsupported, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, probeMongoCapabilities, repoOptionsFromCtx, requireField, resetCapabilityProbeCache, resetPaginationDefaults, resolveMongoCapabilities, resolveTransactionSupport, sequentialId, softDeletePlugin, subdocumentPlugin, supportsTransactions, systemContext, timestampPlugin, toPlain, transactionResolutionOf, uniqueField, validationChainPlugin, withTransaction };
|
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { n as idVariants } from "./id-resolution-BqDrk0S2.mjs";
|
|
2
|
-
import { _ as resetCapabilityProbeCache, a as supportsTransactions, b as transactionResolutionOf, c as ALL_OPERATIONS, d as READ_OPERATIONS, f as operationsByPolicyKey, g as probeMongoCapabilities, h as classifyHelloReply, i as isTransactionUnsupported, l as MUTATING_OPERATIONS, m as capabilitiesForSupport, n as Repository, o as withTransaction, p as MONGOKIT_CAPABILITIES, r as batchTransaction, s as AggregationBuilder, t as HOOK_PRIORITY, u as OP_REGISTRY, v as resolveMongoCapabilities, x as createMongoPurgePort, y as resolveTransactionSupport } from "./Repository-
|
|
3
|
-
import {
|
|
2
|
+
import { _ as resetCapabilityProbeCache, a as supportsTransactions, b as transactionResolutionOf, c as ALL_OPERATIONS, d as READ_OPERATIONS, f as operationsByPolicyKey, g as probeMongoCapabilities, h as classifyHelloReply, i as isTransactionUnsupported, l as MUTATING_OPERATIONS, m as capabilitiesForSupport, n as Repository, o as withTransaction, p as MONGOKIT_CAPABILITIES, r as batchTransaction, s as AggregationBuilder, t as HOOK_PRIORITY, u as OP_REGISTRY, v as resolveMongoCapabilities, x as createMongoPurgePort, y as resolveTransactionSupport } from "./Repository-D7fDpyFx.mjs";
|
|
3
|
+
import { _ as compileFilterToMongo, g as LookupBuilder, x as isCreateManyPartialError } from "./update-c_01A0if.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 { t as actions_exports } from "./actions/index.mjs";
|
|
7
|
-
import { a as customIdPlugin, c as prefixedId, d as AuditTrailQuery, f as auditTrailPlugin, i as multiTenantPlugin, l as sequentialId, m as auditLogPlugin, n as softDeletePlugin, o as dateSequentialId, p as ensureAuditTrailReady, r as adminBypass, s as getNextSequence, t as timestampPlugin, u as cachePlugin } from "./timestamp.plugin-
|
|
8
|
-
import { n as batchOperationsPlugin, t as methodRegistryPlugin } from "./method-registry.plugin-
|
|
9
|
-
import { t as PaginationEngine } from "./PaginationEngine-
|
|
7
|
+
import { a as customIdPlugin, c as prefixedId, d as AuditTrailQuery, f as auditTrailPlugin, i as multiTenantPlugin, l as sequentialId, m as auditLogPlugin, n as softDeletePlugin, o as dateSequentialId, p as ensureAuditTrailReady, r as adminBypass, s as getNextSequence, t as timestampPlugin, u as cachePlugin } from "./timestamp.plugin-B5eiaItQ.mjs";
|
|
8
|
+
import { n as batchOperationsPlugin, t as methodRegistryPlugin } from "./method-registry.plugin-C63pGn1d.mjs";
|
|
9
|
+
import { a as getPaginationDefaults, i as configurePaginationDefaults, o as resetPaginationDefaults, t as PaginationEngine } from "./PaginationEngine-DQ7beTCR.mjs";
|
|
10
10
|
import { isGeoOperator, parseGeoFilter } from "./query/primitives/geo.mjs";
|
|
11
|
-
import { t as createRepository } from "./create-repository-
|
|
11
|
+
import { t as createRepository } from "./create-repository-DOe9E_5F.mjs";
|
|
12
12
|
import { n as defineModel, r as isModelRegistered, t as ModelCollisionError } from "./model-registry-ClKtWiHa.mjs";
|
|
13
|
-
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-
|
|
13
|
+
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-Bju1D1Sn.mjs";
|
|
14
14
|
import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-FSQFLpsU.mjs";
|
|
15
15
|
import { buildFieldTypeMap, coerceFieldValue, coerceHeuristic } from "./query/primitives/coercion.mjs";
|
|
16
16
|
import { extractSchemaIndexes } from "./query/primitives/indexes.mjs";
|
|
@@ -509,6 +509,11 @@ function parseFilters(rt, filters, depth = 0) {
|
|
|
509
509
|
rt.reject(`Blocked filter field not in allowlist: ${baseField}`, { field: baseField });
|
|
510
510
|
continue;
|
|
511
511
|
}
|
|
512
|
+
if (key === "$and") {
|
|
513
|
+
const branches = parseCompoundBranches(rt, value, depth);
|
|
514
|
+
if (branches.length > 0) parsedFilters.$and = branches;
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
512
517
|
if (operatorMatch) {
|
|
513
518
|
const [, , operator] = operatorMatch;
|
|
514
519
|
if (rt.dangerousOperators.includes(`$${operator}`)) {
|
|
@@ -707,6 +712,24 @@ function handleBracketSyntax(rt, field, operators, parsedFilters, depth = 0) {
|
|
|
707
712
|
if (typeof parsedFilters[field] === "object" && Object.keys(parsedFilters[field]).length === 0) delete parsedFilters[field];
|
|
708
713
|
}
|
|
709
714
|
/** Parse `?or=[...]` / `?OR=[...]` / `?$or=[...]` groups into an $or array. */
|
|
715
|
+
/**
|
|
716
|
+
* Parse the branches of a compound operator (`$and`, and the body of `$or`).
|
|
717
|
+
*
|
|
718
|
+
* Every branch goes back through `parseFilters`, so the operator block, the allowlist and the
|
|
719
|
+
* regex budget all apply inside it. Branches that parse to `{}` are DROPPED: a branch holding
|
|
720
|
+
* only a blocked operator would otherwise become match-all, which widens the query instead of
|
|
721
|
+
* failing it — the exact shape `parseOr` documents below.
|
|
722
|
+
*/
|
|
723
|
+
function parseCompoundBranches(rt, raw, depth) {
|
|
724
|
+
const items = Array.isArray(raw) ? raw : typeof raw === "object" && raw ? Object.values(raw) : [];
|
|
725
|
+
const branches = [];
|
|
726
|
+
for (const item of items) {
|
|
727
|
+
if (typeof item !== "object" || !item) continue;
|
|
728
|
+
const parsed = parseFilters(rt, item, depth + 1);
|
|
729
|
+
if (Object.keys(parsed).length > 0) branches.push(parsed);
|
|
730
|
+
}
|
|
731
|
+
return branches;
|
|
732
|
+
}
|
|
710
733
|
function parseOr(rt, query) {
|
|
711
734
|
const orArray = [];
|
|
712
735
|
const raw = query?.or || query?.OR || query?.$or;
|
|
@@ -1758,4 +1781,4 @@ function systemContext(extra) {
|
|
|
1758
1781
|
*/
|
|
1759
1782
|
var src_default = Repository;
|
|
1760
1783
|
//#endregion
|
|
1761
|
-
export { ALL_OPERATIONS, AggregationBuilder, AuditTrailQuery, HOOK_PRIORITY, LookupBuilder, MONGOKIT_CAPABILITIES, MONGOKIT_PLUGIN_NAMES, MUTATING_OPERATIONS, ModelCollisionError, OP_REGISTRY, PaginationEngine, QueryParser, READ_OPERATIONS, Repository, actions_exports as actions, adminBypass, aggregateHelpersPlugin, appendOnlyPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, capabilitiesForSupport, cascadePlugin, cascadePurgeReferences, classifyHelloReply, compileFilterToMongo, configureLogger, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, src_default as default, defineModel, defineModels, elasticSearchPlugin, ensureAuditTrailReady, fieldFilterPlugin, filterResponseData, getFieldsForUser, getMongooseProjection, getNextSequence, idVariants, idempotencyStorePlugin, immutableField, immutableStatesPlugin, isDuplicateKeyError, isModelRegistered, isTransactionUnsupported, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, probeMongoCapabilities, repoOptionsFromCtx, requireField, resetCapabilityProbeCache, resolveMongoCapabilities, resolveTransactionSupport, sequentialId, softDeletePlugin, subdocumentPlugin, supportsTransactions, systemContext, timestampPlugin, toPlain, transactionResolutionOf, uniqueField, validationChainPlugin, withTransaction };
|
|
1784
|
+
export { ALL_OPERATIONS, AggregationBuilder, AuditTrailQuery, HOOK_PRIORITY, LookupBuilder, MONGOKIT_CAPABILITIES, MONGOKIT_PLUGIN_NAMES, MUTATING_OPERATIONS, ModelCollisionError, OP_REGISTRY, PaginationEngine, QueryParser, READ_OPERATIONS, Repository, actions_exports as actions, adminBypass, aggregateHelpersPlugin, appendOnlyPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, capabilitiesForSupport, cascadePlugin, cascadePurgeReferences, classifyHelloReply, compileFilterToMongo, configureLogger, configurePaginationDefaults, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, src_default as default, defineModel, defineModels, elasticSearchPlugin, ensureAuditTrailReady, fieldFilterPlugin, filterResponseData, getFieldsForUser, getMongooseProjection, getNextSequence, getPaginationDefaults, idVariants, idempotencyStorePlugin, immutableField, immutableStatesPlugin, isCreateManyPartialError, isDuplicateKeyError, isModelRegistered, isTransactionUnsupported, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, probeMongoCapabilities, repoOptionsFromCtx, requireField, resetCapabilityProbeCache, resetPaginationDefaults, resolveMongoCapabilities, resolveTransactionSupport, sequentialId, softDeletePlugin, subdocumentPlugin, supportsTransactions, systemContext, timestampPlugin, toPlain, transactionResolutionOf, uniqueField, validationChainPlugin, withTransaction };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
//#region src/indexes/verify-indexes.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Compare DECLARED indexes against what a database actually has.
|
|
4
|
+
*
|
|
5
|
+
* `unique: true` on a schema is a correctness constraint only if the index was
|
|
6
|
+
* built. A skipped deploy step is otherwise SILENT — one deployment ran with
|
|
7
|
+
* 401 declared indexes absent, accumulated duplicate rows on a "unique" field,
|
|
8
|
+
* and nothing anywhere said the constraint did not exist. mongokit owns the
|
|
9
|
+
* declaration, so it owns the means to check it.
|
|
10
|
+
*
|
|
11
|
+
* Read-only. It NEVER builds: index builds belong to a deploy step, not to a
|
|
12
|
+
* serving process.
|
|
13
|
+
*
|
|
14
|
+
* Missing UNIQUE indexes are reported separately from missing regular ones —
|
|
15
|
+
* the first silently admits duplicate data, the second only costs a scan.
|
|
16
|
+
*
|
|
17
|
+
* DELIBERATELY ONE-DIRECTIONAL: an index present in the database but absent
|
|
18
|
+
* from a schema is NOT drift. Auth libraries and migrations manage indexes
|
|
19
|
+
* outside the ODM, and treating those as removable is exactly what makes a
|
|
20
|
+
* `syncIndexes()` unsafe.
|
|
21
|
+
*
|
|
22
|
+
* Sibling of `query/primitives/indexes`, which reads DECLARATIONS only and
|
|
23
|
+
* touches no connection. This module is the live comparison.
|
|
24
|
+
*/
|
|
25
|
+
/** The slice of a Mongoose-like connection this needs. Structural on purpose. */
|
|
26
|
+
interface IndexVerifiableConnection {
|
|
27
|
+
modelNames(): string[];
|
|
28
|
+
model(name: string): IndexVerifiableModel;
|
|
29
|
+
}
|
|
30
|
+
interface IndexVerifiableModel {
|
|
31
|
+
schema: {
|
|
32
|
+
indexes(): Array<[Record<string, unknown>, Record<string, unknown>?]>;
|
|
33
|
+
};
|
|
34
|
+
collection: {
|
|
35
|
+
name: string;
|
|
36
|
+
listIndexes(): {
|
|
37
|
+
toArray(): Promise<Array<Record<string, unknown>>>;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
interface MissingIndex {
|
|
42
|
+
model: string;
|
|
43
|
+
collection: string;
|
|
44
|
+
/** The declared key, JSON-stringified — stable to log and to diff. */
|
|
45
|
+
key: string;
|
|
46
|
+
}
|
|
47
|
+
interface IndexVerifyReport {
|
|
48
|
+
modelsChecked: number;
|
|
49
|
+
/** Declared `unique` indexes with nothing behind them. Duplicates can already exist. */
|
|
50
|
+
missingUnique: MissingIndex[];
|
|
51
|
+
missingRegular: MissingIndex[];
|
|
52
|
+
/** Models whose indexes could not be read — collection absent, or no permission. */
|
|
53
|
+
unreadable: string[];
|
|
54
|
+
}
|
|
55
|
+
interface VerifyIndexesOptions {
|
|
56
|
+
/**
|
|
57
|
+
* Include a model in the sweep. Default: every model.
|
|
58
|
+
*
|
|
59
|
+
* A kernel that materialises different model sets per mode must skip exactly
|
|
60
|
+
* the set its deploy step skips — indexing a model CREATES its collection, so
|
|
61
|
+
* a mismatch here reports permanent phantom drift instead of a real gap.
|
|
62
|
+
*/
|
|
63
|
+
includeModel?: (modelName: string) => boolean;
|
|
64
|
+
}
|
|
65
|
+
declare function verifyIndexes(connection: IndexVerifiableConnection, options?: VerifyIndexesOptions): Promise<IndexVerifyReport>;
|
|
66
|
+
/** One-line summary for a boot log. */
|
|
67
|
+
declare function formatIndexReport(report: IndexVerifyReport): string;
|
|
68
|
+
//#endregion
|
|
69
|
+
export { IndexVerifiableConnection, IndexVerifiableModel, IndexVerifyReport, MissingIndex, VerifyIndexesOptions, formatIndexReport, verifyIndexes };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
//#region src/indexes/verify-indexes.ts
|
|
2
|
+
/**
|
|
3
|
+
* Order-sensitive: a compound index is not the same index with keys swapped.
|
|
4
|
+
*
|
|
5
|
+
* A SINGLE-field numeric index is direction-agnostic though — mongo traverses
|
|
6
|
+
* an index either way, so `{t:1}` and `{t:-1}` are the same index and a schema
|
|
7
|
+
* declaring one against a database holding the other is not drift. Only numeric
|
|
8
|
+
* directions collapse; `2dsphere` / `hashed` are index TYPES, not directions.
|
|
9
|
+
*/
|
|
10
|
+
function normalizeKey(key) {
|
|
11
|
+
const entries = Object.entries(key);
|
|
12
|
+
if (entries.length === 1 && typeof entries[0]?.[1] === "number") return JSON.stringify([[entries[0][0]]]);
|
|
13
|
+
return JSON.stringify(entries);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A TEXT index is stored under a key mongo invents (`{_fts, _ftsx}`) with the
|
|
17
|
+
* real fields moved to `weights`, so it never matches its own declaration by
|
|
18
|
+
* key. Compare the field SET instead, or every text index reads as permanently
|
|
19
|
+
* missing and the whole check becomes noise nobody reads.
|
|
20
|
+
*/
|
|
21
|
+
function textFields(key) {
|
|
22
|
+
const fields = Object.entries(key).filter(([, dir]) => dir === "text").map(([field]) => field);
|
|
23
|
+
return fields.length > 0 ? fields.sort() : null;
|
|
24
|
+
}
|
|
25
|
+
async function verifyIndexes(connection, options = {}) {
|
|
26
|
+
const include = options.includeModel ?? (() => true);
|
|
27
|
+
const report = {
|
|
28
|
+
modelsChecked: 0,
|
|
29
|
+
missingUnique: [],
|
|
30
|
+
missingRegular: [],
|
|
31
|
+
unreadable: []
|
|
32
|
+
};
|
|
33
|
+
for (const name of connection.modelNames().sort()) {
|
|
34
|
+
if (!include(name)) continue;
|
|
35
|
+
const model = connection.model(name);
|
|
36
|
+
const declared = model.schema.indexes();
|
|
37
|
+
if (declared.length === 0) continue;
|
|
38
|
+
let existing;
|
|
39
|
+
let existingText;
|
|
40
|
+
try {
|
|
41
|
+
const live = await model.collection.listIndexes().toArray();
|
|
42
|
+
existing = new Set(live.map((i) => normalizeKey(i.key)));
|
|
43
|
+
existingText = new Set(live.filter((i) => i.weights).map((i) => JSON.stringify(Object.keys(i.weights).sort())));
|
|
44
|
+
} catch {
|
|
45
|
+
report.unreadable.push(name);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
report.modelsChecked += 1;
|
|
49
|
+
for (const [key, indexOptions] of declared) {
|
|
50
|
+
const asText = textFields(key);
|
|
51
|
+
if (asText) {
|
|
52
|
+
if (existingText.has(JSON.stringify(asText))) continue;
|
|
53
|
+
} else if (existing.has(normalizeKey(key))) continue;
|
|
54
|
+
const entry = {
|
|
55
|
+
model: name,
|
|
56
|
+
collection: model.collection.name,
|
|
57
|
+
key: JSON.stringify(key)
|
|
58
|
+
};
|
|
59
|
+
if (indexOptions?.unique) report.missingUnique.push(entry);
|
|
60
|
+
else report.missingRegular.push(entry);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return report;
|
|
64
|
+
}
|
|
65
|
+
/** One-line summary for a boot log. */
|
|
66
|
+
function formatIndexReport(report) {
|
|
67
|
+
const parts = [
|
|
68
|
+
`${report.modelsChecked} models checked`,
|
|
69
|
+
`missing unique: ${report.missingUnique.length}`,
|
|
70
|
+
`missing regular: ${report.missingRegular.length}`
|
|
71
|
+
];
|
|
72
|
+
if (report.unreadable.length > 0) parts.push(`unreadable: ${report.unreadable.length}`);
|
|
73
|
+
return `[index-check] ${parts.join(" — ")}`;
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
export { formatIndexReport, verifyIndexes };
|
|
@@ -16,6 +16,58 @@ import { t as createError } from "./error-BuByZwKU.mjs";
|
|
|
16
16
|
* // bulkWrite is what this plugin contributes.
|
|
17
17
|
* await repo.bulkWrite([...ops]);
|
|
18
18
|
*/
|
|
19
|
+
/**
|
|
20
|
+
* Driver options `bulkWrite` forwards, and the only ones it forwards.
|
|
21
|
+
*
|
|
22
|
+
* The signature used to be `{ session?, ordered?, [key: string]: unknown }` and
|
|
23
|
+
* the call forwarded exactly two of them. So `writeConcern: { w: 'majority' }`
|
|
24
|
+
* on a money import was accepted by the type, dropped on the floor, and the
|
|
25
|
+
* write went out under the default concern with nothing raised.
|
|
26
|
+
*/
|
|
27
|
+
const BULK_WRITE_OPTIONS = [
|
|
28
|
+
"ordered",
|
|
29
|
+
"session",
|
|
30
|
+
"writeConcern",
|
|
31
|
+
"bypassDocumentValidation",
|
|
32
|
+
"comment",
|
|
33
|
+
"let",
|
|
34
|
+
"ignoreUndefined"
|
|
35
|
+
];
|
|
36
|
+
/**
|
|
37
|
+
* Driver options that EXIST but this method does not forward.
|
|
38
|
+
*
|
|
39
|
+
* The options bag is dual-purpose by design: it is spread into
|
|
40
|
+
* `_buildContext`, so it also carries plugin context — `organizationId` for
|
|
41
|
+
* multi-tenant scoping, and whatever else a host's plugins read off it.
|
|
42
|
+
* Refusing every unrecognised key therefore breaks legitimate callers, which
|
|
43
|
+
* is exactly how the first version of this fence failed: it rejected the
|
|
44
|
+
* tenant id and took two passing tests with it.
|
|
45
|
+
*
|
|
46
|
+
* So the line sits where the caller's expectation is. If the DRIVER would
|
|
47
|
+
* understand the option and we would silently not pass it on, refuse — that is
|
|
48
|
+
* the case where someone believes they configured the write. A key the driver
|
|
49
|
+
* does not know either is plugin context, and passes through untouched.
|
|
50
|
+
*/
|
|
51
|
+
const UNSUPPORTED_DRIVER_OPTIONS = /* @__PURE__ */ new Set([
|
|
52
|
+
"forceServerObjectId",
|
|
53
|
+
"timeoutMS",
|
|
54
|
+
"maxTimeMS",
|
|
55
|
+
"retryWrites",
|
|
56
|
+
"checkKeys",
|
|
57
|
+
"serializeFunctions",
|
|
58
|
+
"enableUtf8Validation",
|
|
59
|
+
"raw",
|
|
60
|
+
"explain"
|
|
61
|
+
]);
|
|
62
|
+
/** Narrow the bag to driver options, refusing the ones we would silently drop. */
|
|
63
|
+
function pickBulkWriteOptions(options) {
|
|
64
|
+
const dropped = Object.keys(options).filter((k) => UNSUPPORTED_DRIVER_OPTIONS.has(k));
|
|
65
|
+
if (dropped.length > 0) throw createError(400, `bulkWrite: option(s) ${dropped.map((k) => `'${k}'`).join(", ")} are MongoDB driver options this method does not forward. Refused rather than ignored, because silently dropping one changes what the write does. Supported: ${BULK_WRITE_OPTIONS.join(", ")}.`);
|
|
66
|
+
const out = {};
|
|
67
|
+
for (const key of BULK_WRITE_OPTIONS) if (options[key] !== void 0) out[key] = options[key];
|
|
68
|
+
out.ordered = options.ordered ?? true;
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
19
71
|
function batchOperationsPlugin() {
|
|
20
72
|
return {
|
|
21
73
|
name: "batch-operations",
|
|
@@ -36,6 +88,7 @@ function batchOperationsPlugin() {
|
|
|
36
88
|
* ]);
|
|
37
89
|
*/
|
|
38
90
|
repo.registerMethod("bulkWrite", async function(operations, options = {}) {
|
|
91
|
+
const driverOptions = pickBulkWriteOptions(options);
|
|
39
92
|
const context = await this._buildContext("bulkWrite", {
|
|
40
93
|
operations,
|
|
41
94
|
...options
|
|
@@ -43,10 +96,7 @@ function batchOperationsPlugin() {
|
|
|
43
96
|
try {
|
|
44
97
|
const finalOps = context.operations || operations;
|
|
45
98
|
if (!finalOps || finalOps.length === 0) throw createError(400, "bulkWrite requires at least one operation");
|
|
46
|
-
const result = await this.Model.bulkWrite(finalOps,
|
|
47
|
-
ordered: options.ordered ?? true,
|
|
48
|
-
session: options.session
|
|
49
|
-
});
|
|
99
|
+
const result = await this.Model.bulkWrite(finalOps, driverOptions);
|
|
50
100
|
const bulkResult = {
|
|
51
101
|
ok: result.ok,
|
|
52
102
|
insertedCount: result.insertedCount,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { l as Plugin, p as RepositoryContext } from "./repository-
|
|
1
|
+
import { g as ObjectId } from "./pagination-BpIv2bdS.mjs";
|
|
2
|
+
import { l as Plugin, p as RepositoryContext } from "./repository-ZbLtL7Nk.mjs";
|
|
3
3
|
import mongoose, { Connection } from "mongoose";
|
|
4
4
|
import { CacheAdapter as CacheAdapter$1, CacheOptions, RepositoryCacheHandle as RepositoryCacheHandle$1, RepositoryCachePluginOptions, cachePlugin } from "@classytic/repo-core/cache";
|
|
5
5
|
import { TenantConfig } from "@classytic/repo-core/tenant";
|
|
@@ -312,7 +312,10 @@ interface SequentialIdOptions {
|
|
|
312
312
|
prefix: string;
|
|
313
313
|
/** Mongoose model — used to derive the counter key from model name */
|
|
314
314
|
model: mongoose.Model<any>;
|
|
315
|
-
/**
|
|
315
|
+
/**
|
|
316
|
+
* MINIMUM number of digits (default: 4 → "0001"). Never truncates —
|
|
317
|
+
* sequence 10000 under `padding: 4` renders as `INV-10000`.
|
|
318
|
+
*/
|
|
316
319
|
padding?: number;
|
|
317
320
|
/** Separator between prefix and number (default: '-') */
|
|
318
321
|
separator?: string;
|
|
@@ -346,10 +349,54 @@ interface DateSequentialIdOptions {
|
|
|
346
349
|
* - 'daily' → BILL-2026-02-20-0001, resets every day
|
|
347
350
|
*/
|
|
348
351
|
partition?: 'yearly' | 'monthly' | 'daily';
|
|
349
|
-
/**
|
|
352
|
+
/**
|
|
353
|
+
* MINIMUM number of digits for the sequence (default: 4). `padStart` never
|
|
354
|
+
* truncates, so the 10,000th id of a period under `padding: 4` is
|
|
355
|
+
* `BILL-2026-10000` — it grows a digit rather than wrapping to `0000`.
|
|
356
|
+
* Lexical sort order therefore only holds while a period stays below
|
|
357
|
+
* 10^padding; size the padding for your peak period.
|
|
358
|
+
*/
|
|
350
359
|
padding?: number;
|
|
351
360
|
/** Separator (default: '-') */
|
|
352
361
|
separator?: string;
|
|
362
|
+
/**
|
|
363
|
+
* Counter scope.
|
|
364
|
+
* - `'global'` (default) — one counter per model + period, shared by
|
|
365
|
+
* every tenant in the database. Ids are unique across the deployment.
|
|
366
|
+
* - `'tenant'` — one counter per tenant + model + period, keyed by
|
|
367
|
+
* `context[tenantKey]`. Every tenant's numbering starts at 1 (Shopify-
|
|
368
|
+
* style per-shop order numbers) and the write hot spot on the single
|
|
369
|
+
* shared counter document splits per tenant. Ids are unique WITHIN a
|
|
370
|
+
* tenant only — index the field compound with the tenant field.
|
|
371
|
+
* Fails closed: a create with no tenant in context throws rather than
|
|
372
|
+
* falling back to the global key, which would silently merge two
|
|
373
|
+
* tenants' sequences.
|
|
374
|
+
*/
|
|
375
|
+
scope?: 'global' | 'tenant';
|
|
376
|
+
/**
|
|
377
|
+
* Context key carrying the tenant id under `scope: 'tenant'` (default:
|
|
378
|
+
* `'organizationId'` — the same default as `multiTenantPlugin`'s
|
|
379
|
+
* `contextKey`, so `repo.create(data, { organizationId })` feeds both).
|
|
380
|
+
*/
|
|
381
|
+
tenantKey?: string;
|
|
382
|
+
/**
|
|
383
|
+
* Which clock decides the period boundary.
|
|
384
|
+
*
|
|
385
|
+
* - `'local'` (default) — the server's `TZ`. Kept as the default because it
|
|
386
|
+
* is what every existing deployment already generated: flipping it would
|
|
387
|
+
* retroactively change which period an id near a month boundary belongs
|
|
388
|
+
* to, and those ids are invoice and order numbers.
|
|
389
|
+
* - `'utc'` — **the correct choice for more than one replica.** Two replicas
|
|
390
|
+
* with different `TZ` settings derive different counter keys for the same
|
|
391
|
+
* logical month and each increments its own, so the same number is issued
|
|
392
|
+
* twice inside one tenant-period. UTC is the one boundary every replica
|
|
393
|
+
* agrees on. It also matches the ecosystem's other period key,
|
|
394
|
+
* `usagePeriod()` in `@classytic/repo-core/usage`.
|
|
395
|
+
*
|
|
396
|
+
* Containers usually run UTC anyway, which is exactly why the difference
|
|
397
|
+
* stays invisible until one host is configured otherwise.
|
|
398
|
+
*/
|
|
399
|
+
timezone?: 'local' | 'utc';
|
|
353
400
|
}
|
|
354
401
|
/**
|
|
355
402
|
* Generator: Date-partitioned sequential counter.
|
|
@@ -371,6 +418,15 @@ interface DateSequentialIdOptions {
|
|
|
371
418
|
* }),
|
|
372
419
|
* })
|
|
373
420
|
* ```
|
|
421
|
+
*
|
|
422
|
+
* @example Per-tenant numbering in a shared database
|
|
423
|
+
* ```typescript
|
|
424
|
+
* customIdPlugin({
|
|
425
|
+
* field: 'orderNumber',
|
|
426
|
+
* generator: dateSequentialId({ prefix: 'ORD', model: OrderModel, scope: 'tenant' }),
|
|
427
|
+
* })
|
|
428
|
+
* // org-a: ORD-2026-02-0001, ORD-2026-02-0002 … org-b: ORD-2026-02-0001 …
|
|
429
|
+
* ```
|
|
374
430
|
*/
|
|
375
431
|
declare function dateSequentialId(options: DateSequentialIdOptions): IdGenerator;
|
|
376
432
|
interface PrefixedIdOptions {
|