@classytic/mongokit 3.38.1 → 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-Ck5x43wF.mjs → Repository-D7fDpyFx.mjs} +400 -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.mjs +2 -2
- package/dist/{create-repository-BU4x9Kb0.d.mts → create-repository-CRXjDa3N.d.mts} +5 -5
- package/dist/{create-repository-B5EulQ31.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 +8 -8
- 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 +1 -1
- package/dist/pagination/utils/limits.mjs +22 -1
- 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-CBQukQzV.mjs → timestamp.plugin-B5eiaItQ.mjs} +31 -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-DhNyxNCw.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 +7 -3
- package/dist/PaginationEngine-BX9o_-4R.mjs +0 -735
- package/dist/core-62oo3N1C.d.mts +0 -50
- package/dist/pagination-jSUdrACK.d.mts +0 -158
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { S as RepositoryPluginName, b as MONGOKIT_PLUGIN_NAMES, l as Plugin, x as MongoKitPluginName } from "../repository-
|
|
2
|
-
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, 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-
|
|
3
|
-
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, 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, x as MethodRegistryRepository, y as MongoOperationsMethods, z as batchOperationsPlugin } from "../validation-chain.plugin-
|
|
1
|
+
import { S as RepositoryPluginName, b as MONGOKIT_PLUGIN_NAMES, l as Plugin, x as MongoKitPluginName } from "../repository-ZbLtL7Nk.mjs";
|
|
2
|
+
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, 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";
|
|
3
|
+
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, 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, x as MethodRegistryRepository, y as MongoOperationsMethods, z as batchOperationsPlugin } from "../validation-chain.plugin-DvrLJIbJ.mjs";
|
|
4
4
|
import { ChangeLogStore } from "@classytic/repo-core/sync";
|
|
5
5
|
//#region src/plugins/change-log.plugin.d.ts
|
|
6
6
|
interface ChangeLogPluginOptions {
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
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, s as getNextSequence, t as timestampPlugin, u as cachePlugin } from "../timestamp.plugin-
|
|
2
|
-
import { n as batchOperationsPlugin, t as methodRegistryPlugin } from "../method-registry.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-
|
|
1
|
+
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, s as getNextSequence, t as timestampPlugin, u as cachePlugin } from "../timestamp.plugin-B5eiaItQ.mjs";
|
|
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-Bju1D1Sn.mjs";
|
|
4
4
|
//#region src/plugins/change-log.plugin.ts
|
|
5
5
|
const PLUGIN_NAME = "changeLog";
|
|
6
6
|
function isSkipped(context) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as PopulateSpec, g as ObjectId, h as FilterQuery, i as CountStrategy, p as AnyDocument, v as ReadPreferenceType, x as SortSpec, y as SelectSpec } from "./pagination-BpIv2bdS.mjs";
|
|
2
2
|
import { r as DocField } from "./type-utils-CLzRFtIA.mjs";
|
|
3
|
-
import { RepoCapabilities, RepositoryBase } from "@classytic/repo-core/repository";
|
|
3
|
+
import { DistributionConfig, DistributionMissHandler, RepoCapabilities, RepositoryBase } from "@classytic/repo-core/repository";
|
|
4
4
|
import { Model, PipelineStage } from "mongoose";
|
|
5
5
|
import { HttpError } from "@classytic/repo-core/errors";
|
|
6
6
|
import { OffsetPaginationResult } from "@classytic/repo-core/pagination";
|
|
@@ -199,6 +199,28 @@ interface RepositoryOptions {
|
|
|
199
199
|
* ```
|
|
200
200
|
*/
|
|
201
201
|
requirePlugins?: readonly RepositoryPluginName[];
|
|
202
|
+
/**
|
|
203
|
+
* Declare the collection's shard key so every filter-taking verb
|
|
204
|
+
* (`getAll`, `findAll`, `getOne`, `count`, `updateMany`, `aggregate`, …)
|
|
205
|
+
* catches a filter that omits it — the query mongos has to fan out to
|
|
206
|
+
* every shard. Id-addressed verbs (`getById`, `update`, `delete`,
|
|
207
|
+
* `claim`) are not checked; their `_id` match is routed, not scattered.
|
|
208
|
+
*
|
|
209
|
+
* The check runs AFTER `before:*` hooks, so a tenant field injected by
|
|
210
|
+
* `multiTenantPlugin` satisfies a `key: 'organizationId'` guard and the
|
|
211
|
+
* guard only ever fires on the calls that dropped the scope —
|
|
212
|
+
* `bypassTenant: true`, an unscoped repo, a hand-built cross-tenant
|
|
213
|
+
* `$or`. List verbs a host legitimately runs cross-shard (a global
|
|
214
|
+
* dashboard's `aggregate`) in `exemptOperations`.
|
|
215
|
+
*
|
|
216
|
+
* `onMissingKey` defaults to `'warn'` — once per operation name through
|
|
217
|
+
* mongokit's logger (`configureLogger` routes it); pass `onMiss` to
|
|
218
|
+
* observe every miss yourself, or `'throw'` for hosts where a scatter-
|
|
219
|
+
* gather is never acceptable. Omit the option entirely and nothing runs.
|
|
220
|
+
*/
|
|
221
|
+
distribution?: DistributionConfig & {
|
|
222
|
+
onMiss?: DistributionMissHandler;
|
|
223
|
+
};
|
|
202
224
|
/**
|
|
203
225
|
* Override the whole runtime capability descriptor.
|
|
204
226
|
*
|
|
@@ -295,6 +317,8 @@ interface RepositoryContext {
|
|
|
295
317
|
limit?: number;
|
|
296
318
|
/** Cursor for next page (keyset pagination) */
|
|
297
319
|
after?: string;
|
|
320
|
+
/** Cursor for the PREVIOUS page (keyset pagination). Mutually exclusive with `after`. */
|
|
321
|
+
before?: string;
|
|
298
322
|
/** Search query string */
|
|
299
323
|
search?: string;
|
|
300
324
|
/** Pagination mode */
|
|
@@ -303,8 +327,10 @@ interface RepositoryContext {
|
|
|
303
327
|
hint?: string | Record<string, 1 | -1>;
|
|
304
328
|
/** Maximum execution time in milliseconds */
|
|
305
329
|
maxTimeMS?: number;
|
|
306
|
-
/** Count strategy for offset pagination */
|
|
307
|
-
countStrategy?:
|
|
330
|
+
/** Count strategy for offset pagination. See {@link CountStrategy}. */
|
|
331
|
+
countStrategy?: CountStrategy;
|
|
332
|
+
/** Ceiling for `countStrategy: 'capped'` (default 10000). */
|
|
333
|
+
countLimit?: number;
|
|
308
334
|
/** Whether this is a soft delete operation (set by softDeletePlugin) */
|
|
309
335
|
softDeleted?: boolean;
|
|
310
336
|
/** Include soft-deleted documents in queries */
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Schema } from "mongoose";
|
|
2
|
+
import { ResolvedTenantConfig } from "@classytic/repo-core/tenant";
|
|
3
|
+
//#region src/tenant/index.d.ts
|
|
4
|
+
/** Which read an index serves. Default `'tenant'`. See the module docblock. */
|
|
5
|
+
type IndexScope = 'tenant' | 'global';
|
|
6
|
+
/** Key directions and types a declaration may use. Mirrors what `schema.index()` accepts. */
|
|
7
|
+
type IndexKeyValue = 1 | -1 | 'text' | '2dsphere' | '2d' | 'hashed';
|
|
8
|
+
/**
|
|
9
|
+
* Index options passed through to `schema.index()`. `name` is the only one this module
|
|
10
|
+
* reads (to apply and to explain exemptions); everything else is Mongoose's.
|
|
11
|
+
*/
|
|
12
|
+
interface IndexDeclarationOptions {
|
|
13
|
+
name?: string | undefined;
|
|
14
|
+
unique?: boolean | undefined;
|
|
15
|
+
sparse?: boolean | undefined;
|
|
16
|
+
partialFilterExpression?: Record<string, unknown> | undefined;
|
|
17
|
+
expireAfterSeconds?: number | undefined;
|
|
18
|
+
collation?: Record<string, unknown> | undefined;
|
|
19
|
+
background?: boolean | undefined;
|
|
20
|
+
[option: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* One index, declared by a kernel for its own model or by a host through a kernel's
|
|
24
|
+
* `indexes` seam. The kernel applies it through {@link injectTenantField}, which is what
|
|
25
|
+
* makes `scope` mean something: a `'tenant'` declaration is prefixed exactly like the
|
|
26
|
+
* kernel's own indexes, a `'global'` one is kept as written.
|
|
27
|
+
*/
|
|
28
|
+
interface IndexDeclaration {
|
|
29
|
+
readonly fields: Readonly<Record<string, IndexKeyValue>>;
|
|
30
|
+
readonly options?: IndexDeclarationOptions | undefined;
|
|
31
|
+
/** @default 'tenant' */
|
|
32
|
+
readonly scope?: IndexScope | undefined;
|
|
33
|
+
}
|
|
34
|
+
interface InjectTenantFieldOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Index NAMES (the `name` option of `schema.index()`) already on the schema whose key
|
|
37
|
+
* spec must NOT get the tenant prefix. The escape hatch for a kernel's OWN global
|
|
38
|
+
* identity index declared inline in its schema builder (`order_event_id_unique`: the
|
|
39
|
+
* event id is a kernel-generated UUID and the drain's idempotency contract is exactly
|
|
40
|
+
* one row per event regardless of tenant). Prefer declaring such an index through
|
|
41
|
+
* `indexes` with `scope: 'global'`; this exists so a schema builder need not know the
|
|
42
|
+
* tenant config. Unnamed indexes cannot be exempted: give the index a name first.
|
|
43
|
+
*/
|
|
44
|
+
readonly skipIndexes?: readonly string[] | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Additional declarations, applied AFTER the prepend pass so their `scope` is honoured.
|
|
47
|
+
* This is where a kernel threads its host's `indexes` seam.
|
|
48
|
+
*/
|
|
49
|
+
readonly indexes?: readonly IndexDeclaration[] | undefined;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Refuse a declaration that cannot mean what it says. Called before any schema mutation
|
|
53
|
+
* so a bad host config fails at DESCRIBE time, with the fix in the message, rather than
|
|
54
|
+
* building a wrong index on the first bind.
|
|
55
|
+
*/
|
|
56
|
+
declare function assertIndexDeclaration(declaration: IndexDeclaration, tenant: Pick<ResolvedTenantConfig, 'tenantField'>): void;
|
|
57
|
+
/**
|
|
58
|
+
* Add `declarations` to `schema` honouring each one's scope.
|
|
59
|
+
*
|
|
60
|
+
* `'tenant'` declarations are prefixed with the tenant field when scoping is enabled
|
|
61
|
+
* (unless they already lead with it, so a host that wrote it out is not double-prefixed);
|
|
62
|
+
* `'global'` ones are added exactly as written. When scoping is disabled every declaration
|
|
63
|
+
* is added as written, because there is no partition to lead with.
|
|
64
|
+
*
|
|
65
|
+
* Exported for kernels whose optional models inject the tenant field on their own path and
|
|
66
|
+
* only need the host's extra declarations applied afterwards.
|
|
67
|
+
*/
|
|
68
|
+
declare function declareIndexes(schema: Schema, tenant: ResolvedTenantConfig, declarations: readonly IndexDeclaration[] | undefined): void;
|
|
69
|
+
/**
|
|
70
|
+
* Inject the tenant field into a Mongoose schema and make its indexes tenant-correct.
|
|
71
|
+
*
|
|
72
|
+
* 1. Adds the field, typed by `tenant.fieldType` (`ObjectId` with `ref`, or `String`).
|
|
73
|
+
* `required` only when scoping is enabled and the config says so: a single-tenant
|
|
74
|
+
* deployment still gets the field, because domain verbs reference it in raw queries.
|
|
75
|
+
* 2. When scoping is enabled, prepends the tenant field to every index already declared
|
|
76
|
+
* on the schema, EXCEPT: one that already names the field; a TTL index (MongoDB rejects
|
|
77
|
+
* a compound TTL spec outright, and a time-driven sweep has no tenant to give); and any
|
|
78
|
+
* index named in `skipIndexes`.
|
|
79
|
+
* 3. Applies `indexes` through {@link declareIndexes}, so a `'global'` declaration is never
|
|
80
|
+
* touched by step 2 whatever order the caller thought about it in.
|
|
81
|
+
* 4. Guarantees one tenant-leading index. After the prepend any compound serves a
|
|
82
|
+
* tenant-only query via the prefix rule, so a bare `{ tenant: 1 }` is added ONLY when
|
|
83
|
+
* nothing was prepended: next to a compound it is a redundant prefix paid on every
|
|
84
|
+
* insert (PACKAGE_RULES P11.1; the fleet index audit found this pattern behind most of
|
|
85
|
+
* 86 redundant indexes across 615).
|
|
86
|
+
*/
|
|
87
|
+
declare function injectTenantField(schema: Schema, tenant: ResolvedTenantConfig, options?: InjectTenantFieldOptions): void;
|
|
88
|
+
//#endregion
|
|
89
|
+
export { IndexDeclaration, IndexDeclarationOptions, IndexKeyValue, IndexScope, InjectTenantFieldOptions, assertIndexDeclaration, declareIndexes, injectTenantField };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
//#region src/tenant/index.ts
|
|
3
|
+
/** Mongoose keeps declared indexes on `schema._indexes`; `schema.indexes()` is a copy. */
|
|
4
|
+
function indexEntries(schema) {
|
|
5
|
+
return schema._indexes ?? [];
|
|
6
|
+
}
|
|
7
|
+
function isScoped(tenant) {
|
|
8
|
+
return tenant.enabled && tenant.strategy === "field";
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Refuse a declaration that cannot mean what it says. Called before any schema mutation
|
|
12
|
+
* so a bad host config fails at DESCRIBE time, with the fix in the message, rather than
|
|
13
|
+
* building a wrong index on the first bind.
|
|
14
|
+
*/
|
|
15
|
+
function assertIndexDeclaration(declaration, tenant) {
|
|
16
|
+
if (Object.keys(declaration.fields).length === 0) throw new Error("[mongokit/tenant] an index declaration needs at least one field");
|
|
17
|
+
if (declaration.scope === "global") {
|
|
18
|
+
if (typeof declaration.options?.name !== "string" || declaration.options.name.length === 0) throw new Error(`[mongokit/tenant] a global index must be named: { fields: ${JSON.stringify(declaration.fields)}, scope: 'global' } has no \`options.name\`. A tenant exemption is deliberate, and an unnamed one cannot be told from an oversight.`);
|
|
19
|
+
if (declaration.fields[tenant.tenantField] !== void 0) throw new Error(`[mongokit/tenant] index "${declaration.options.name}" is scope 'global' but names the tenant field "${tenant.tenantField}". A global index serves reads that have no tenant to give; drop the field, or declare the index with scope 'tenant'.`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Add `declarations` to `schema` honouring each one's scope.
|
|
24
|
+
*
|
|
25
|
+
* `'tenant'` declarations are prefixed with the tenant field when scoping is enabled
|
|
26
|
+
* (unless they already lead with it, so a host that wrote it out is not double-prefixed);
|
|
27
|
+
* `'global'` ones are added exactly as written. When scoping is disabled every declaration
|
|
28
|
+
* is added as written, because there is no partition to lead with.
|
|
29
|
+
*
|
|
30
|
+
* Exported for kernels whose optional models inject the tenant field on their own path and
|
|
31
|
+
* only need the host's extra declarations applied afterwards.
|
|
32
|
+
*/
|
|
33
|
+
function declareIndexes(schema, tenant, declarations) {
|
|
34
|
+
if (!declarations || declarations.length === 0) return;
|
|
35
|
+
for (const declaration of declarations) {
|
|
36
|
+
assertIndexDeclaration(declaration, tenant);
|
|
37
|
+
const options = declaration.options;
|
|
38
|
+
const scoped = isScoped(tenant) && declaration.scope !== "global";
|
|
39
|
+
const leadsWithTenant = Object.keys(declaration.fields)[0] === tenant.tenantField;
|
|
40
|
+
const fields = scoped && !leadsWithTenant ? {
|
|
41
|
+
[tenant.tenantField]: 1,
|
|
42
|
+
...declaration.fields
|
|
43
|
+
} : { ...declaration.fields };
|
|
44
|
+
schema.index(fields, options);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Inject the tenant field into a Mongoose schema and make its indexes tenant-correct.
|
|
49
|
+
*
|
|
50
|
+
* 1. Adds the field, typed by `tenant.fieldType` (`ObjectId` with `ref`, or `String`).
|
|
51
|
+
* `required` only when scoping is enabled and the config says so: a single-tenant
|
|
52
|
+
* deployment still gets the field, because domain verbs reference it in raw queries.
|
|
53
|
+
* 2. When scoping is enabled, prepends the tenant field to every index already declared
|
|
54
|
+
* on the schema, EXCEPT: one that already names the field; a TTL index (MongoDB rejects
|
|
55
|
+
* a compound TTL spec outright, and a time-driven sweep has no tenant to give); and any
|
|
56
|
+
* index named in `skipIndexes`.
|
|
57
|
+
* 3. Applies `indexes` through {@link declareIndexes}, so a `'global'` declaration is never
|
|
58
|
+
* touched by step 2 whatever order the caller thought about it in.
|
|
59
|
+
* 4. Guarantees one tenant-leading index. After the prepend any compound serves a
|
|
60
|
+
* tenant-only query via the prefix rule, so a bare `{ tenant: 1 }` is added ONLY when
|
|
61
|
+
* nothing was prepended: next to a compound it is a redundant prefix paid on every
|
|
62
|
+
* insert (PACKAGE_RULES P11.1; the fleet index audit found this pattern behind most of
|
|
63
|
+
* 86 redundant indexes across 615).
|
|
64
|
+
*/
|
|
65
|
+
function injectTenantField(schema, tenant, options = {}) {
|
|
66
|
+
for (const declaration of options.indexes ?? []) assertIndexDeclaration(declaration, tenant);
|
|
67
|
+
const isObjectId = tenant.fieldType === "objectId";
|
|
68
|
+
const scoped = isScoped(tenant);
|
|
69
|
+
schema.add({ [tenant.tenantField]: {
|
|
70
|
+
type: isObjectId ? mongoose.Schema.Types.ObjectId : String,
|
|
71
|
+
...scoped && tenant.required ? { required: true } : {},
|
|
72
|
+
...isObjectId && tenant.ref ? { ref: tenant.ref } : {}
|
|
73
|
+
} });
|
|
74
|
+
if (!scoped) {
|
|
75
|
+
declareIndexes(schema, tenant, options.indexes);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const skip = new Set(options.skipIndexes ?? []);
|
|
79
|
+
for (const entry of indexEntries(schema)) {
|
|
80
|
+
const [fields, indexOptions] = entry;
|
|
81
|
+
if (fields[tenant.tenantField] !== void 0) continue;
|
|
82
|
+
if (indexOptions?.expireAfterSeconds !== void 0) continue;
|
|
83
|
+
const name = indexOptions?.name;
|
|
84
|
+
if (typeof name === "string" && skip.has(name)) continue;
|
|
85
|
+
entry[0] = {
|
|
86
|
+
[tenant.tenantField]: 1,
|
|
87
|
+
...fields
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
declareIndexes(schema, tenant, options.indexes);
|
|
91
|
+
if (!indexEntries(schema).some(([fields]) => Object.keys(fields)[0] === tenant.tenantField)) schema.index({ [tenant.tenantField]: 1 });
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
export { assertIndexDeclaration, declareIndexes, injectTenantField };
|
package/dist/testkit/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as Repository } from "../Repository-
|
|
2
|
-
import { n as CreateRepositoryConfig } from "../create-repository-
|
|
1
|
+
import { n as Repository } from "../Repository-IxI983_m.mjs";
|
|
2
|
+
import { n as CreateRepositoryConfig } from "../create-repository-CRXjDa3N.mjs";
|
|
3
3
|
import { Connection, Model, Schema } from "mongoose";
|
|
4
4
|
import { MongoMemoryReplSet, MongoMemoryServer } from "mongodb-memory-server";
|
|
5
5
|
//#region src/testkit/index.d.ts
|
package/dist/testkit/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as ALL_OPERATIONS, t as HOOK_PRIORITY, u as OP_REGISTRY } from "./Repository-
|
|
1
|
+
import { c as ALL_OPERATIONS, t as HOOK_PRIORITY, u as OP_REGISTRY } from "./Repository-D7fDpyFx.mjs";
|
|
2
2
|
import { n as warn } from "./logger-K7dPmu2U.mjs";
|
|
3
3
|
import { throwIfAborted, withRetry } from "@classytic/repo-core/repository";
|
|
4
4
|
import mongoose from "mongoose";
|
|
@@ -795,30 +795,53 @@ function sequentialId(options) {
|
|
|
795
795
|
* }),
|
|
796
796
|
* })
|
|
797
797
|
* ```
|
|
798
|
+
*
|
|
799
|
+
* @example Per-tenant numbering in a shared database
|
|
800
|
+
* ```typescript
|
|
801
|
+
* customIdPlugin({
|
|
802
|
+
* field: 'orderNumber',
|
|
803
|
+
* generator: dateSequentialId({ prefix: 'ORD', model: OrderModel, scope: 'tenant' }),
|
|
804
|
+
* })
|
|
805
|
+
* // org-a: ORD-2026-02-0001, ORD-2026-02-0002 … org-b: ORD-2026-02-0001 …
|
|
806
|
+
* ```
|
|
798
807
|
*/
|
|
799
808
|
function dateSequentialId(options) {
|
|
800
|
-
const { prefix, model, partition = "monthly", padding = 4, separator = "-" } = options;
|
|
809
|
+
const { prefix, model, partition = "monthly", padding = 4, separator = "-", scope = "global", tenantKey = "organizationId", timezone = "local" } = options;
|
|
810
|
+
/** Per-generator, not module-level — two generators warn independently. */
|
|
811
|
+
const overflowWarned = /* @__PURE__ */ new Set();
|
|
812
|
+
const paddingCeiling = 10 ** padding;
|
|
801
813
|
return async (context) => {
|
|
802
814
|
const now = /* @__PURE__ */ new Date();
|
|
803
|
-
const
|
|
804
|
-
const
|
|
805
|
-
const
|
|
815
|
+
const utc = timezone === "utc";
|
|
816
|
+
const year = String(utc ? now.getUTCFullYear() : now.getFullYear());
|
|
817
|
+
const month = String((utc ? now.getUTCMonth() : now.getMonth()) + 1).padStart(2, "0");
|
|
818
|
+
const day = String(utc ? now.getUTCDate() : now.getDate()).padStart(2, "0");
|
|
819
|
+
let keyBase = model.modelName;
|
|
820
|
+
if (scope === "tenant") {
|
|
821
|
+
const tenantId = context[tenantKey];
|
|
822
|
+
if (tenantId === void 0 || tenantId === null || tenantId === "") throw new Error(`[mongokit] dateSequentialId: scope 'tenant' requires '${tenantKey}' in context for '${model.modelName}' create, but none was provided. Pass it per call (repo.create(data, { ${tenantKey}: '<id>' })) or resolve it ambiently; the generator never falls back to the global counter.`);
|
|
823
|
+
keyBase = `${model.modelName}:${String(tenantId)}`;
|
|
824
|
+
}
|
|
806
825
|
let datePart;
|
|
807
826
|
let counterKey;
|
|
808
827
|
switch (partition) {
|
|
809
828
|
case "yearly":
|
|
810
829
|
datePart = year;
|
|
811
|
-
counterKey = `${
|
|
830
|
+
counterKey = `${keyBase}:${year}`;
|
|
812
831
|
break;
|
|
813
832
|
case "daily":
|
|
814
833
|
datePart = `${year}${separator}${month}${separator}${day}`;
|
|
815
|
-
counterKey = `${
|
|
834
|
+
counterKey = `${keyBase}:${year}-${month}-${day}`;
|
|
816
835
|
break;
|
|
817
836
|
default:
|
|
818
837
|
datePart = `${year}${separator}${month}`;
|
|
819
|
-
counterKey = `${
|
|
838
|
+
counterKey = `${keyBase}:${year}-${month}`;
|
|
820
839
|
}
|
|
821
840
|
const seq = await getNextSequence(counterKey, 1, context._counterConnection, context.session);
|
|
841
|
+
if (seq >= paddingCeiling && !overflowWarned.has(counterKey)) {
|
|
842
|
+
overflowWarned.add(counterKey);
|
|
843
|
+
warn(`[mongokit] dateSequentialId: '${model.modelName}' sequence ${seq} exceeds padding ${padding} (max ${paddingCeiling - 1}) for period '${counterKey}'. Ids remain unique but no longer sort lexically — raise \`padding\` for new periods, or use a finer \`partition\`.`);
|
|
844
|
+
}
|
|
822
845
|
return `${prefix}${separator}${datePart}${separator}${String(seq).padStart(padding, "0")}`;
|
|
823
846
|
};
|
|
824
847
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { v as UserContext } from "./repository-
|
|
2
|
-
import { r as FieldPreset } from "./plugin-options-
|
|
1
|
+
import { v as UserContext } from "./repository-ZbLtL7Nk.mjs";
|
|
2
|
+
import { r as FieldPreset } from "./plugin-options-BuvtOSZf.mjs";
|
|
3
3
|
import mongoose, { Schema } from "mongoose";
|
|
4
4
|
import { CacheAdapter } from "@classytic/repo-core/cache";
|
|
5
5
|
import { HttpError } from "@classytic/repo-core/errors";
|
|
@@ -2,6 +2,99 @@ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
|
2
2
|
import { n as warn } from "./logger-K7dPmu2U.mjs";
|
|
3
3
|
import { t as createError } from "./error-BuByZwKU.mjs";
|
|
4
4
|
import { coerceFilterDates, isFilter } from "@classytic/repo-core/filter";
|
|
5
|
+
//#region src/actions/create.ts
|
|
6
|
+
var create_exports = /* @__PURE__ */ __exportAll({
|
|
7
|
+
create: () => create,
|
|
8
|
+
createDefault: () => createDefault,
|
|
9
|
+
createMany: () => createMany,
|
|
10
|
+
isCreateManyPartialError: () => isCreateManyPartialError,
|
|
11
|
+
upsert: () => upsert
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* Create single document
|
|
15
|
+
*/
|
|
16
|
+
async function create(Model, data, options = {}) {
|
|
17
|
+
const document = new Model(data);
|
|
18
|
+
await document.save({ session: options.session });
|
|
19
|
+
return document;
|
|
20
|
+
}
|
|
21
|
+
/** Narrow a caught error to one carrying a partial-write report. */
|
|
22
|
+
function isCreateManyPartialError(err) {
|
|
23
|
+
return err instanceof Error && typeof err.partial === "object" && err.partial !== null;
|
|
24
|
+
}
|
|
25
|
+
/** Pull the positional failures out of a driver bulk-write error. */
|
|
26
|
+
function readFailures(err, dataArray) {
|
|
27
|
+
const raw = err.writeErrors;
|
|
28
|
+
return (Array.isArray(raw) ? raw : raw ? [raw] : []).map((entry) => {
|
|
29
|
+
const e = entry;
|
|
30
|
+
const inner = e.err ?? e;
|
|
31
|
+
const index = Number(inner.index ?? e.index ?? -1);
|
|
32
|
+
return {
|
|
33
|
+
index,
|
|
34
|
+
doc: dataArray[index] ?? {},
|
|
35
|
+
...typeof inner.code === "number" ? { code: inner.code } : {},
|
|
36
|
+
message: String(inner.errmsg ?? inner.message ?? e.message ?? "write failed")
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create multiple documents.
|
|
42
|
+
*
|
|
43
|
+
* **A rejection does NOT mean nothing was written.** Neither ordering does:
|
|
44
|
+
* `ordered: true` stops at the first failure and keeps everything before it,
|
|
45
|
+
* `ordered: false` keeps everything valid. Measured on a six-document batch
|
|
46
|
+
* with a conflict in the middle — ordered wrote 3, unordered wrote 5. Only a
|
|
47
|
+
* transaction gives all-or-nothing.
|
|
48
|
+
*
|
|
49
|
+
* So the rejection carries a `partial` report naming what landed and what did
|
|
50
|
+
* not, because the alternative is a caller retrying the whole batch and
|
|
51
|
+
* double-writing everything that had already succeeded. Use it to retry only
|
|
52
|
+
* `failed`, or to reconcile — and prefer a unique index or an idempotency key
|
|
53
|
+
* for anything that will be retried automatically.
|
|
54
|
+
*/
|
|
55
|
+
async function createMany(Model, dataArray, options = {}) {
|
|
56
|
+
try {
|
|
57
|
+
return await Model.insertMany(dataArray, {
|
|
58
|
+
session: options.session,
|
|
59
|
+
ordered: options.ordered === true
|
|
60
|
+
});
|
|
61
|
+
} catch (err) {
|
|
62
|
+
const inserted = err.insertedDocs;
|
|
63
|
+
const failed = readFailures(err, dataArray);
|
|
64
|
+
if (Array.isArray(inserted) || failed.length > 0) err.partial = {
|
|
65
|
+
inserted: Array.isArray(inserted) ? inserted : [],
|
|
66
|
+
failed
|
|
67
|
+
};
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create with defaults (useful for initialization)
|
|
73
|
+
*/
|
|
74
|
+
async function createDefault(Model, overrides = {}, options = {}) {
|
|
75
|
+
const defaults = {};
|
|
76
|
+
Model.schema.eachPath((path, schemaType) => {
|
|
77
|
+
const schemaOptions = schemaType.options;
|
|
78
|
+
if (schemaOptions.default !== void 0 && path !== "_id") defaults[path] = typeof schemaOptions.default === "function" ? schemaOptions.default() : schemaOptions.default;
|
|
79
|
+
});
|
|
80
|
+
return create(Model, {
|
|
81
|
+
...defaults,
|
|
82
|
+
...overrides
|
|
83
|
+
}, options);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Upsert (create or update)
|
|
87
|
+
*/
|
|
88
|
+
async function upsert(Model, query, data, options = {}) {
|
|
89
|
+
return Model.findOneAndUpdate(query, { $setOnInsert: data }, {
|
|
90
|
+
upsert: true,
|
|
91
|
+
returnDocument: "after",
|
|
92
|
+
runValidators: true,
|
|
93
|
+
session: options.session,
|
|
94
|
+
...options.updatePipeline !== void 0 ? { updatePipeline: options.updatePipeline } : {}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
5
98
|
//#region src/filter/compile.ts
|
|
6
99
|
/**
|
|
7
100
|
* Compile a Filter IR node to a MongoDB query object. Returns `{}`
|
|
@@ -611,24 +704,35 @@ async function aggregate(Model, pipeline, options = {}) {
|
|
|
611
704
|
return aggregation.exec();
|
|
612
705
|
}
|
|
613
706
|
/**
|
|
614
|
-
* Aggregate with pagination
|
|
615
|
-
*
|
|
616
|
-
*
|
|
707
|
+
* Aggregate with pagination.
|
|
708
|
+
*
|
|
709
|
+
* Page and count run as TWO concurrent pipelines rather than one `$facet`.
|
|
710
|
+
* `$facet` bundles every returned document plus the count into a SINGLE output
|
|
711
|
+
* document, and no stage may exceed 16MB — so a page of large documents failed
|
|
712
|
+
* with `BSONObjectTooLarge` instead of paginating, and the only defence was a
|
|
713
|
+
* warning above an arbitrary limit of 1000 that told the caller to go
|
|
714
|
+
* elsewhere. `$facet` also cannot use an index for the stages inside it.
|
|
715
|
+
*
|
|
716
|
+
* The trade: two reads, so a concurrent write between them can leave `total`
|
|
717
|
+
* a document out of step with `data` — the same trade `PaginationEngine`
|
|
718
|
+
* already makes on both its offset and aggregate paths.
|
|
617
719
|
*/
|
|
618
720
|
async function aggregatePaginate(Model, pipeline, options = {}) {
|
|
619
721
|
const page = parseInt(String(options.page || 1), 10);
|
|
620
722
|
const limit = parseInt(String(options.limit || 10), 10);
|
|
621
723
|
const skip = (page - 1) * limit;
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
}
|
|
627
|
-
const
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
724
|
+
const run = (stages) => {
|
|
725
|
+
const aggregation = Model.aggregate(stages);
|
|
726
|
+
if (options.session) aggregation.session(options.session);
|
|
727
|
+
return aggregation.exec();
|
|
728
|
+
};
|
|
729
|
+
const [dataRows, countRows] = await Promise.all([run([
|
|
730
|
+
...pipeline,
|
|
731
|
+
{ $skip: skip },
|
|
732
|
+
{ $limit: limit }
|
|
733
|
+
]), run([...pipeline, { $count: "count" }])]);
|
|
734
|
+
const data = dataRows || [];
|
|
735
|
+
const total = countRows[0]?.count || 0;
|
|
632
736
|
const pages = Math.ceil(total / limit);
|
|
633
737
|
return {
|
|
634
738
|
data,
|
|
@@ -748,57 +852,6 @@ async function minMax(Model, field, query = {}, options = {}) {
|
|
|
748
852
|
};
|
|
749
853
|
}
|
|
750
854
|
//#endregion
|
|
751
|
-
//#region src/actions/create.ts
|
|
752
|
-
var create_exports = /* @__PURE__ */ __exportAll({
|
|
753
|
-
create: () => create,
|
|
754
|
-
createDefault: () => createDefault,
|
|
755
|
-
createMany: () => createMany,
|
|
756
|
-
upsert: () => upsert
|
|
757
|
-
});
|
|
758
|
-
/**
|
|
759
|
-
* Create single document
|
|
760
|
-
*/
|
|
761
|
-
async function create(Model, data, options = {}) {
|
|
762
|
-
const document = new Model(data);
|
|
763
|
-
await document.save({ session: options.session });
|
|
764
|
-
return document;
|
|
765
|
-
}
|
|
766
|
-
/**
|
|
767
|
-
* Create multiple documents
|
|
768
|
-
*/
|
|
769
|
-
async function createMany(Model, dataArray, options = {}) {
|
|
770
|
-
return Model.insertMany(dataArray, {
|
|
771
|
-
session: options.session,
|
|
772
|
-
ordered: options.ordered === true
|
|
773
|
-
});
|
|
774
|
-
}
|
|
775
|
-
/**
|
|
776
|
-
* Create with defaults (useful for initialization)
|
|
777
|
-
*/
|
|
778
|
-
async function createDefault(Model, overrides = {}, options = {}) {
|
|
779
|
-
const defaults = {};
|
|
780
|
-
Model.schema.eachPath((path, schemaType) => {
|
|
781
|
-
const schemaOptions = schemaType.options;
|
|
782
|
-
if (schemaOptions.default !== void 0 && path !== "_id") defaults[path] = typeof schemaOptions.default === "function" ? schemaOptions.default() : schemaOptions.default;
|
|
783
|
-
});
|
|
784
|
-
return create(Model, {
|
|
785
|
-
...defaults,
|
|
786
|
-
...overrides
|
|
787
|
-
}, options);
|
|
788
|
-
}
|
|
789
|
-
/**
|
|
790
|
-
* Upsert (create or update)
|
|
791
|
-
*/
|
|
792
|
-
async function upsert(Model, query, data, options = {}) {
|
|
793
|
-
return Model.findOneAndUpdate(query, { $setOnInsert: data }, {
|
|
794
|
-
upsert: true,
|
|
795
|
-
returnDocument: "after",
|
|
796
|
-
runValidators: true,
|
|
797
|
-
session: options.session,
|
|
798
|
-
...options.updatePipeline !== void 0 ? { updatePipeline: options.updatePipeline } : {}
|
|
799
|
-
});
|
|
800
|
-
}
|
|
801
|
-
//#endregion
|
|
802
855
|
//#region src/actions/delete.ts
|
|
803
856
|
var delete_exports = /* @__PURE__ */ __exportAll({
|
|
804
857
|
deleteById: () => deleteById,
|
|
@@ -813,8 +866,8 @@ var delete_exports = /* @__PURE__ */ __exportAll({
|
|
|
813
866
|
*/
|
|
814
867
|
async function deleteById(Model, id, options = {}) {
|
|
815
868
|
const query = {
|
|
816
|
-
|
|
817
|
-
|
|
869
|
+
...options.query,
|
|
870
|
+
_id: id
|
|
818
871
|
};
|
|
819
872
|
if (!await Model.findOneAndDelete(query).session(options.session ?? null)) return null;
|
|
820
873
|
return {
|
|
@@ -1053,8 +1106,8 @@ function parsePopulate(populate) {
|
|
|
1053
1106
|
async function update(Model, id, data, options = {}) {
|
|
1054
1107
|
assertUpdatePipelineAllowed(data, options.updatePipeline);
|
|
1055
1108
|
const query = {
|
|
1056
|
-
|
|
1057
|
-
|
|
1109
|
+
...options.query,
|
|
1110
|
+
_id: id
|
|
1058
1111
|
};
|
|
1059
1112
|
return await Model.findOneAndUpdate(query, data, {
|
|
1060
1113
|
returnDocument: "after",
|
|
@@ -1071,8 +1124,8 @@ async function update(Model, id, data, options = {}) {
|
|
|
1071
1124
|
async function updateWithConstraints(Model, id, data, constraints = {}, options = {}) {
|
|
1072
1125
|
assertUpdatePipelineAllowed(data, options.updatePipeline);
|
|
1073
1126
|
const query = {
|
|
1074
|
-
|
|
1075
|
-
|
|
1127
|
+
...constraints,
|
|
1128
|
+
_id: id
|
|
1076
1129
|
};
|
|
1077
1130
|
return await Model.findOneAndUpdate(query, data, {
|
|
1078
1131
|
returnDocument: "after",
|
|
@@ -1097,8 +1150,8 @@ async function updateWithValidation(Model, id, data, validationOptions = {}, opt
|
|
|
1097
1150
|
};
|
|
1098
1151
|
}
|
|
1099
1152
|
const findQuery = {
|
|
1100
|
-
|
|
1101
|
-
|
|
1153
|
+
...options.query,
|
|
1154
|
+
_id: id
|
|
1102
1155
|
};
|
|
1103
1156
|
const existing = await Model.findOne(findQuery).select(options.select || "").session(options.session ?? null).lean();
|
|
1104
1157
|
if (!existing) return {
|
|
@@ -1204,4 +1257,4 @@ async function pullFromArray(Model, id, field, value, options = {}) {
|
|
|
1204
1257
|
return update(Model, id, { $pull: { [field]: value } }, options);
|
|
1205
1258
|
}
|
|
1206
1259
|
//#endregion
|
|
1207
|
-
export { upsert as _, count as a,
|
|
1260
|
+
export { upsert as S, compileFilterToMongo as _, count as a, create_exports as b, getByQuery as c, deleteById as d, deleteByQuery as f, LookupBuilder as g, distinct as h, update_exports as i, getOrCreate as l, aggregate_exports as m, update as n, exists as o, delete_exports as p, updateByQuery as r, getById as s, findOneAndUpdate as t, read_exports as u, create as v, isCreateManyPartialError as x, createMany as y };
|
package/dist/utils/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as getMongooseProjection, a as createMemoryCache, b as createError, c as IdType, d as isObjectIdInstance, f as isValidIdForType, g as getFieldsForUser, h as filterResponseData, i as buildCrudSchemasFromMongooseSchema, l as getSchemaIdType, m as createFieldPreset, n as CrudSchemasFramework, o as LoggerConfig, p as toObjectId, r as buildCrudSchemasFromModel, s as configureLogger, t as toPlain, v as CreateErrorOptions, y as ParseDuplicateKeyOptions } from "../to-plain-
|
|
1
|
+
import { _ as getMongooseProjection, a as createMemoryCache, b as createError, c as IdType, d as isObjectIdInstance, f as isValidIdForType, g as getFieldsForUser, h as filterResponseData, i as buildCrudSchemasFromMongooseSchema, l as getSchemaIdType, m as createFieldPreset, n as CrudSchemasFramework, o as LoggerConfig, p as toObjectId, r as buildCrudSchemasFromModel, s as configureLogger, t as toPlain, v as CreateErrorOptions, y as ParseDuplicateKeyOptions } from "../to-plain-B8ufk3Qz.mjs";
|
|
2
2
|
import { ClientSession, Model } from "mongoose";
|
|
3
3
|
//#region src/utils/id-chunks.d.ts
|
|
4
4
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as collectIds, r as idChunks, t as DEFAULT_ID_CHUNK } from "./id-chunks-BmAwsqNk.mjs";
|
|
2
|
-
import { c as ALL_OPERATIONS, u as OP_REGISTRY } from "./Repository-
|
|
3
|
-
import {
|
|
2
|
+
import { c as ALL_OPERATIONS, u as OP_REGISTRY } from "./Repository-D7fDpyFx.mjs";
|
|
3
|
+
import { S as upsert } from "./update-c_01A0if.mjs";
|
|
4
4
|
import { n as warn } from "./logger-K7dPmu2U.mjs";
|
|
5
5
|
import { t as createError } from "./error-BuByZwKU.mjs";
|
|
6
6
|
import { r as getFieldsForUser } from "./field-selection-FSQFLpsU.mjs";
|