@classytic/mongokit 3.11.0 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -2
- package/dist/{PaginationEngine-B93fLCcO.mjs → PaginationEngine-BDaAsyPn.mjs} +2 -2
- package/dist/actions/index.d.mts +1 -1
- package/dist/actions/index.mjs +1 -1
- package/dist/ai/index.d.mts +1 -1
- package/dist/ai/index.mjs +3 -3
- package/dist/{error-CzYwrfUP.mjs → error-B00pI7dV.mjs} +11 -4
- package/dist/{index-C1MzVFsT.d.mts → index-D9cORR-o.d.mts} +1 -1
- package/dist/index.d.mts +16 -11
- package/dist/index.mjs +21 -6
- package/dist/{mongooseToJsonSchema-D1sdCOmj.mjs → mongooseToJsonSchema-B187ufOP.mjs} +67 -19
- package/dist/{mongooseToJsonSchema-BH6OFec5.d.mts → mongooseToJsonSchema-rtkdbBhf.d.mts} +44 -8
- package/dist/pagination/PaginationEngine.d.mts +2 -1
- package/dist/pagination/PaginationEngine.mjs +1 -1
- package/dist/plugins/index.d.mts +1 -1
- package/dist/plugins/index.mjs +1 -1
- package/dist/{types-xOyTec4n.d.mts → types-DXscZnLu.d.mts} +49 -81
- package/dist/{update-CWXfFC6O.mjs → update-CDxPtpsk.mjs} +145 -20
- package/dist/utils/index.d.mts +2 -2
- package/dist/utils/index.mjs +3 -3
- package/dist/{validation-chain.plugin-CLjEFr0c.mjs → validation-chain.plugin-BicIgzzt.mjs} +43 -180
- package/dist/{validation-chain.plugin-BGdr5KRw.d.mts → validation-chain.plugin-CH-xPoKM.d.mts} +17 -19
- package/package.json +146 -143
- /package/dist/{logger-DJ7egMnd.mjs → logger-8-VS1za6.mjs} +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import {
|
|
3
|
-
import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-
|
|
4
|
-
import { t as PaginationEngine } from "./PaginationEngine-
|
|
1
|
+
import { _ as upsert, a as count, b as LookupBuilder, c as getByQuery, d as deleteById, f as deleteByQuery, h as createMany, l as getOrCreate, m as create, n as update, o as exists, r as updateByQuery, s as getById, t as findOneAndUpdate, x as compileFilterToMongo, y as distinct } from "./update-CDxPtpsk.mjs";
|
|
2
|
+
import { n as debug, r as warn } from "./logger-8-VS1za6.mjs";
|
|
3
|
+
import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-B00pI7dV.mjs";
|
|
4
|
+
import { t as PaginationEngine } from "./PaginationEngine-BDaAsyPn.mjs";
|
|
5
5
|
import { hasNearOperator, rewriteNearForCount } from "./query/primitives/geo.mjs";
|
|
6
6
|
import { r as isValidIdForType, t as getSchemaIdType } from "./id-resolution-e4BT9zAV.mjs";
|
|
7
7
|
import { a as byIdKey, c as listQueryKey, l as modelPattern, o as byQueryKey, r as getFieldsForUser, u as versionKey } from "./field-selection-dI0m4RBs.mjs";
|
|
8
|
-
import mongoose from "mongoose";
|
|
9
8
|
import { isFilter } from "@classytic/repo-core/filter";
|
|
9
|
+
import mongoose from "mongoose";
|
|
10
10
|
import { HOOK_PRIORITY } from "@classytic/repo-core/hooks";
|
|
11
11
|
import { RepositoryBase, validatePluginOrder } from "@classytic/repo-core/repository";
|
|
12
12
|
import { compileUpdateSpecToMongo, isUpdateSpec } from "@classytic/repo-core/update";
|
|
@@ -728,102 +728,6 @@ function batchOperationsPlugin() {
|
|
|
728
728
|
};
|
|
729
729
|
}
|
|
730
730
|
//#endregion
|
|
731
|
-
//#region src/filter/compile.ts
|
|
732
|
-
/**
|
|
733
|
-
* Compile a Filter IR node to a MongoDB query object. Returns `{}`
|
|
734
|
-
* when the node is `TRUE` (or an empty `and`) so callers can merge
|
|
735
|
-
* with other scopes without special-casing.
|
|
736
|
-
*
|
|
737
|
-
* The `input` is typed as `unknown` so callers can pass either a
|
|
738
|
-
* Filter IR node or an already-built Mongo query and we dispatch
|
|
739
|
-
* appropriately. This keeps the portable API ergonomic for apps that
|
|
740
|
-
* write Mongo queries directly today.
|
|
741
|
-
*/
|
|
742
|
-
function compileFilterToMongo(input) {
|
|
743
|
-
if (!input) return {};
|
|
744
|
-
if (!isFilter(input)) return input;
|
|
745
|
-
return compile(input);
|
|
746
|
-
}
|
|
747
|
-
function compile(filter) {
|
|
748
|
-
switch (filter.op) {
|
|
749
|
-
case "true": return {};
|
|
750
|
-
case "false": return { $expr: false };
|
|
751
|
-
case "eq": return { [filter.field]: filter.value };
|
|
752
|
-
case "ne": return filter.value === null ? { [filter.field]: { $ne: null } } : { $and: [{ [filter.field]: { $ne: filter.value } }, { [filter.field]: { $ne: null } }] };
|
|
753
|
-
case "gt": return { [filter.field]: { $gt: filter.value } };
|
|
754
|
-
case "gte": return { [filter.field]: { $gte: filter.value } };
|
|
755
|
-
case "lt": return { [filter.field]: { $lt: filter.value } };
|
|
756
|
-
case "lte": return { [filter.field]: { $lte: filter.value } };
|
|
757
|
-
case "in":
|
|
758
|
-
if (filter.values.length === 0) return { $expr: false };
|
|
759
|
-
return { [filter.field]: { $in: [...filter.values] } };
|
|
760
|
-
case "nin":
|
|
761
|
-
if (filter.values.length === 0) return {};
|
|
762
|
-
return { [filter.field]: { $nin: [...filter.values] } };
|
|
763
|
-
case "exists": return filter.exists ? { [filter.field]: { $ne: null } } : { [filter.field]: null };
|
|
764
|
-
case "like": return { [filter.field]: likeToRegex(filter.pattern, filter.caseSensitivity) };
|
|
765
|
-
case "regex": return { [filter.field]: { $regex: filter.pattern } };
|
|
766
|
-
case "and": {
|
|
767
|
-
if (filter.children.length === 0) return {};
|
|
768
|
-
const parts = filter.children.map(compile);
|
|
769
|
-
if (parts.length === 1) return parts[0];
|
|
770
|
-
return { $and: parts };
|
|
771
|
-
}
|
|
772
|
-
case "or": {
|
|
773
|
-
if (filter.children.length === 0) return { $expr: false };
|
|
774
|
-
const parts = filter.children.map(compile);
|
|
775
|
-
if (parts.length === 1) return parts[0];
|
|
776
|
-
return { $or: parts };
|
|
777
|
-
}
|
|
778
|
-
case "not": return { $nor: [compile(filter.child)] };
|
|
779
|
-
case "raw": throw new Error("mongokit/filter: `raw` is a SQL escape hatch and has no safe MongoDB translation. Pass a Mongo query object directly to the filter slot instead.");
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
/**
|
|
783
|
-
* Translate a SQL-style LIKE pattern to a MongoDB regex.
|
|
784
|
-
*
|
|
785
|
-
* SQL semantics:
|
|
786
|
-
* - `%` → match zero or more characters (`.*`)
|
|
787
|
-
* - `_` → match exactly one character (`.`)
|
|
788
|
-
* - `\%` → literal percent (escape via backslash)
|
|
789
|
-
* - `\_` → literal underscore
|
|
790
|
-
* - `\\` → literal backslash
|
|
791
|
-
* - everything else is literal — regex metacharacters get escaped.
|
|
792
|
-
*
|
|
793
|
-
* The naive implementation `pattern.replace(/%/g, '.*')` is wrong:
|
|
794
|
-
* it also expands escaped `\%` into a wildcard. We walk the pattern
|
|
795
|
-
* char-by-char, honoring backslash escapes, so `like('notes', '50\\% off')`
|
|
796
|
-
* matches the literal string `50% off` instead of `50<anything> off`.
|
|
797
|
-
*
|
|
798
|
-
* Anchored with `^` / `$` so LIKE matches the whole field value, the
|
|
799
|
-
* same way sqlitekit's `LIKE` semantically does.
|
|
800
|
-
*/
|
|
801
|
-
function likeToRegex(pattern, caseSensitivity) {
|
|
802
|
-
let out = "^";
|
|
803
|
-
for (let i = 0; i < pattern.length; i++) {
|
|
804
|
-
const ch = pattern[i];
|
|
805
|
-
if (ch === "\\" && i + 1 < pattern.length) {
|
|
806
|
-
const next = pattern[i + 1];
|
|
807
|
-
if (next === "%" || next === "_" || next === "\\") {
|
|
808
|
-
out += escapeRegexChar(next);
|
|
809
|
-
i++;
|
|
810
|
-
continue;
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
if (ch === "%") out += ".*";
|
|
814
|
-
else if (ch === "_") out += ".";
|
|
815
|
-
else out += escapeRegexChar(ch);
|
|
816
|
-
}
|
|
817
|
-
out += "$";
|
|
818
|
-
return caseSensitivity === "sensitive" ? { $regex: out } : {
|
|
819
|
-
$regex: out,
|
|
820
|
-
$options: "i"
|
|
821
|
-
};
|
|
822
|
-
}
|
|
823
|
-
function escapeRegexChar(ch) {
|
|
824
|
-
return /[.*+?^${}()|[\]\\]/.test(ch) ? `\\${ch}` : ch;
|
|
825
|
-
}
|
|
826
|
-
//#endregion
|
|
827
731
|
//#region src/actions/aggregate-ir/normalize.ts
|
|
828
732
|
/**
|
|
829
733
|
* Normalize `AggRequest['groupBy']` into a readonly string array.
|
|
@@ -1626,32 +1530,6 @@ function createTxBoundRepo(outer, session) {
|
|
|
1626
1530
|
}
|
|
1627
1531
|
//#endregion
|
|
1628
1532
|
//#region src/Repository.ts
|
|
1629
|
-
/**
|
|
1630
|
-
* Repository Pattern - Data Access Layer
|
|
1631
|
-
*
|
|
1632
|
-
* Event-driven, plugin-based abstraction for MongoDB operations
|
|
1633
|
-
* Inspired by Meta & Stripe's repository patterns
|
|
1634
|
-
*
|
|
1635
|
-
* @example
|
|
1636
|
-
* ```typescript
|
|
1637
|
-
* const userRepo = new Repository(UserModel, [
|
|
1638
|
-
* timestampPlugin(),
|
|
1639
|
-
* softDeletePlugin(),
|
|
1640
|
-
* ]);
|
|
1641
|
-
*
|
|
1642
|
-
* // Create
|
|
1643
|
-
* const user = await userRepo.create({ name: 'John', email: 'john@example.com' });
|
|
1644
|
-
*
|
|
1645
|
-
* // Read with pagination
|
|
1646
|
-
* const users = await userRepo.getAll({ page: 1, limit: 20, filters: { status: 'active' } });
|
|
1647
|
-
*
|
|
1648
|
-
* // Update
|
|
1649
|
-
* const updated = await userRepo.update(user._id, { name: 'John Doe' });
|
|
1650
|
-
*
|
|
1651
|
-
* // Delete
|
|
1652
|
-
* await userRepo.delete(user._id);
|
|
1653
|
-
* ```
|
|
1654
|
-
*/
|
|
1655
1533
|
function ensureLookupProjectionIncludesCursorFields(projection, sort) {
|
|
1656
1534
|
if (!projection || !sort) return projection;
|
|
1657
1535
|
if (!Object.values(projection).some((value) => value === 1)) return projection;
|
|
@@ -2300,7 +2178,7 @@ var Repository = class extends RepositoryBase {
|
|
|
2300
2178
|
if (context.softDeleted) {
|
|
2301
2179
|
const result = {
|
|
2302
2180
|
acknowledged: true,
|
|
2303
|
-
deletedCount: 0,
|
|
2181
|
+
deletedCount: context.softDeletedCount ?? 0,
|
|
2304
2182
|
soft: true
|
|
2305
2183
|
};
|
|
2306
2184
|
await this._emitHook("after:deleteMany", {
|
|
@@ -2488,19 +2366,31 @@ var Repository = class extends RepositoryBase {
|
|
|
2488
2366
|
* Merge policy-hook-injected filters (multi-tenant scope,
|
|
2489
2367
|
* soft-delete) into the pre-aggregate `filter` slot of the request.
|
|
2490
2368
|
* Plugins speak mongo-query shape (`context.query` / `context.filters`);
|
|
2491
|
-
*
|
|
2369
|
+
* the caller's `req.filter` may be either Filter IR or a mongo query.
|
|
2492
2370
|
*
|
|
2493
|
-
*
|
|
2494
|
-
*
|
|
2495
|
-
*
|
|
2496
|
-
*
|
|
2371
|
+
* Each part is compiled through `compileFilterToMongo` BEFORE the
|
|
2372
|
+
* `$and` merge — otherwise an IR node like `eq('status', 'paid')`
|
|
2373
|
+
* (`{ op, field, value }`) gets nested inside `$and` as a literal,
|
|
2374
|
+
* `compileFilterToMongo` of the merged value finds no top-level `op`
|
|
2375
|
+
* (so `isFilter` is false), and Mongo receives the IR object as a
|
|
2376
|
+
* raw query clause that matches no real document. Symptom: aggregates
|
|
2377
|
+
* silently return 0 rows whenever a callerpasses IR + a policy
|
|
2378
|
+
* plugin is installed.
|
|
2497
2379
|
*/
|
|
2498
2380
|
_injectPolicyScopeIntoAgg(req, context) {
|
|
2499
2381
|
const scopeCandidates = [];
|
|
2500
2382
|
for (const candidate of [context.filters, context.query]) if (candidate && typeof candidate === "object" && Object.keys(candidate).length > 0) scopeCandidates.push(candidate);
|
|
2501
2383
|
if (scopeCandidates.length === 0) return req;
|
|
2502
|
-
const parts = [
|
|
2503
|
-
|
|
2384
|
+
const parts = [];
|
|
2385
|
+
for (const c of scopeCandidates) {
|
|
2386
|
+
const compiled = compileFilterToMongo(c);
|
|
2387
|
+
if (Object.keys(compiled).length > 0) parts.push(compiled);
|
|
2388
|
+
}
|
|
2389
|
+
if (req.filter) {
|
|
2390
|
+
const compiled = compileFilterToMongo(req.filter);
|
|
2391
|
+
if (Object.keys(compiled).length > 0) parts.push(compiled);
|
|
2392
|
+
}
|
|
2393
|
+
if (parts.length === 0) return req;
|
|
2504
2394
|
const merged = parts.length === 1 ? parts[0] : { $and: parts };
|
|
2505
2395
|
return {
|
|
2506
2396
|
...req,
|
|
@@ -2892,7 +2782,22 @@ var Repository = class extends RepositoryBase {
|
|
|
2892
2782
|
];
|
|
2893
2783
|
} else query.$or = orConds;
|
|
2894
2784
|
} else if (this._hasTextIndex) query.$text = { $search: search };
|
|
2895
|
-
else
|
|
2785
|
+
else {
|
|
2786
|
+
const modelName = String(this.model);
|
|
2787
|
+
throw createError(400, `No text index found for ${modelName}. Cannot perform text search. Configure ${modelName}'s Repository with { searchMode: 'regex', searchFields: [...] } to enable index-free search, or create a text index on the collection for searchMode: 'text'. See https://github.com/classytic/mongokit/blob/main/docs/README.md#queryparser-url--filter`, {
|
|
2788
|
+
code: "SEARCH_NOT_CONFIGURED",
|
|
2789
|
+
meta: {
|
|
2790
|
+
model: modelName,
|
|
2791
|
+
configuredMode: this.searchMode,
|
|
2792
|
+
availableModes: [
|
|
2793
|
+
"text",
|
|
2794
|
+
"regex",
|
|
2795
|
+
"auto"
|
|
2796
|
+
],
|
|
2797
|
+
docs: "https://github.com/classytic/mongokit/blob/main/docs/README.md#queryparser-url--filter"
|
|
2798
|
+
}
|
|
2799
|
+
});
|
|
2800
|
+
}
|
|
2896
2801
|
return query;
|
|
2897
2802
|
}
|
|
2898
2803
|
/**
|
|
@@ -4315,49 +4220,6 @@ function mongoOperationsPlugin() {
|
|
|
4315
4220
|
//#endregion
|
|
4316
4221
|
//#region src/plugins/multi-tenant.plugin.ts
|
|
4317
4222
|
/**
|
|
4318
|
-
* Multi-Tenant Plugin
|
|
4319
|
-
*
|
|
4320
|
-
* Automatically injects tenant isolation filters into all queries.
|
|
4321
|
-
* Ensures data isolation by adding organizationId (or custom tenant field)
|
|
4322
|
-
* to every read and write operation.
|
|
4323
|
-
*
|
|
4324
|
-
* Uses HOOK_PRIORITY.POLICY (100) to ensure tenant filters are injected
|
|
4325
|
-
* BEFORE cache keys are computed (HOOK_PRIORITY.CACHE = 200).
|
|
4326
|
-
*
|
|
4327
|
-
* @example
|
|
4328
|
-
* ```typescript
|
|
4329
|
-
* // Basic — scopes every operation by organizationId from context
|
|
4330
|
-
* const repo = new Repository(Invoice, [
|
|
4331
|
-
* multiTenantPlugin({ tenantField: 'organizationId' }),
|
|
4332
|
-
* ]);
|
|
4333
|
-
*
|
|
4334
|
-
* const invoices = await repo.getAll(
|
|
4335
|
-
* { filters: { status: 'paid' } },
|
|
4336
|
-
* { organizationId: 'org_123' }
|
|
4337
|
-
* );
|
|
4338
|
-
* // Actual query: { status: 'paid', organizationId: 'org_123' }
|
|
4339
|
-
*
|
|
4340
|
-
* // Super admin bypass — skip scoping based on context
|
|
4341
|
-
* const repo = new Repository(Invoice, [
|
|
4342
|
-
* multiTenantPlugin({
|
|
4343
|
-
* tenantField: 'organizationId',
|
|
4344
|
-
* skipWhen: (context) => context.role === 'superadmin',
|
|
4345
|
-
* }),
|
|
4346
|
-
* ]);
|
|
4347
|
-
*
|
|
4348
|
-
* // Admin sees all orgs
|
|
4349
|
-
* await repo.getAll({ page: 1, limit: 10 }, { role: 'superadmin' });
|
|
4350
|
-
*
|
|
4351
|
-
* // Automatic context — resolve tenant from AsyncLocalStorage
|
|
4352
|
-
* const repo = new Repository(Invoice, [
|
|
4353
|
-
* multiTenantPlugin({
|
|
4354
|
-
* tenantField: 'organizationId',
|
|
4355
|
-
* resolveContext: () => asyncLocalStorage.getStore()?.tenantId,
|
|
4356
|
-
* }),
|
|
4357
|
-
* ]);
|
|
4358
|
-
* ```
|
|
4359
|
-
*/
|
|
4360
|
-
/**
|
|
4361
4223
|
* True when the op's policy target already has `tenantField` set by the
|
|
4362
4224
|
* caller. Used to decide whether the plugin can safely skip injecting a
|
|
4363
4225
|
* tenant scope rather than throwing on a missing context.
|
|
@@ -4704,8 +4566,9 @@ function softDeletePlugin(options = {}) {
|
|
|
4704
4566
|
...context.query || {},
|
|
4705
4567
|
...deleteFilter
|
|
4706
4568
|
};
|
|
4707
|
-
await repo.Model.updateMany(finalQuery, { $set: { [deletedField]: /* @__PURE__ */ new Date() } }, { session: context.session });
|
|
4569
|
+
const updateRes = await repo.Model.updateMany(finalQuery, { $set: { [deletedField]: /* @__PURE__ */ new Date() } }, { session: context.session });
|
|
4708
4570
|
context.softDeleted = true;
|
|
4571
|
+
context.softDeletedCount = updateRes?.modifiedCount ?? 0;
|
|
4709
4572
|
}
|
|
4710
4573
|
}, { priority: HOOK_PRIORITY$1.POLICY });
|
|
4711
4574
|
if (addRestoreMethod) {
|
package/dist/{validation-chain.plugin-BGdr5KRw.d.mts → validation-chain.plugin-CH-xPoKM.d.mts}
RENAMED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $ as RepositoryInstance, E as FieldPreset, P as Logger, W as Plugin, Z as RepositoryContext, _t as ValidationChainOptions, f as CascadeOptions, l as CacheOptions, lt as SortSpec, ot as SoftDeleteOptions, q as PopulateSpec, rt as SelectSpec, u as CacheStats, vt as ValidatorDefinition, z as ObjectId } from "./types-DXscZnLu.mjs";
|
|
2
2
|
import mongoose from "mongoose";
|
|
3
3
|
import { BulkWriteResult } from "@classytic/repo-core/repository";
|
|
4
4
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
|
+
import { OffsetPaginationResult } from "@classytic/repo-core/pagination";
|
|
6
|
+
import { TenantConfig } from "@classytic/repo-core/tenant";
|
|
5
7
|
|
|
6
8
|
//#region src/plugins/aggregate-helpers.plugin.d.ts
|
|
7
9
|
/**
|
|
@@ -753,13 +755,20 @@ interface MongoOperationsMethods<TDoc> {
|
|
|
753
755
|
}
|
|
754
756
|
//#endregion
|
|
755
757
|
//#region src/plugins/multi-tenant.plugin.d.ts
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
758
|
+
/**
|
|
759
|
+
* Static tenant fields are picked from `@classytic/repo-core/tenant` so the
|
|
760
|
+
* vocabulary (`tenantField`, `contextKey`, `required`, `fieldType`) stays
|
|
761
|
+
* locked to the org-wide canonical source. Mongokit-specific runtime
|
|
762
|
+
* callbacks (`skipWhen`, `resolveContext`, `skipOperations`,
|
|
763
|
+
* `allowDataInjection`) extend on top — those genuinely differ from
|
|
764
|
+
* sqlitekit's runtime shape because mongokit's `RepositoryContext` carries
|
|
765
|
+
* Mongoose-specific bits the resolver may inspect.
|
|
766
|
+
*
|
|
767
|
+
* Mongokit defaults `fieldType` to `'string'` (not repo-core's `'objectId'`)
|
|
768
|
+
* for back-compat — pre-3.x stored tenant ids as raw strings; flipping the
|
|
769
|
+
* default would silently change cast behavior for existing apps.
|
|
770
|
+
*/
|
|
771
|
+
interface MultiTenantOptions extends Pick<TenantConfig, 'tenantField' | 'contextKey' | 'required' | 'fieldType'> {
|
|
763
772
|
/** Operations to skip tenant injection (e.g., for admin/system queries) */
|
|
764
773
|
skipOperations?: string[];
|
|
765
774
|
/**
|
|
@@ -784,17 +793,6 @@ interface MultiTenantOptions {
|
|
|
784
793
|
* ```
|
|
785
794
|
*/
|
|
786
795
|
resolveContext?: () => string | undefined;
|
|
787
|
-
/**
|
|
788
|
-
* How to store/query the tenant ID.
|
|
789
|
-
*
|
|
790
|
-
* - `'string'` (default): inject the tenant ID as-is (raw string).
|
|
791
|
-
* - `'objectId'`: cast to `mongoose.Types.ObjectId` before injecting.
|
|
792
|
-
*
|
|
793
|
-
* Choose `'objectId'` when the schema declares the tenant field as
|
|
794
|
-
* `Schema.Types.ObjectId` (e.g., Flow, accounting). This enables
|
|
795
|
-
* `$lookup` and `.populate()` against the referenced collection.
|
|
796
|
-
*/
|
|
797
|
-
fieldType?: 'string' | 'objectId';
|
|
798
796
|
/**
|
|
799
797
|
* When `true` (default), bypass the `required` throw if the operation's
|
|
800
798
|
* policy target already carries the tenant field. This lets hosts that
|
package/package.json
CHANGED
|
@@ -1,143 +1,146 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@classytic/mongokit",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "Production-grade MongoDB repositories - smart pagination, events, and plugins. Built on @classytic/repo-core.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"sideEffects": false,
|
|
7
|
-
"main": "./dist/index.mjs",
|
|
8
|
-
"module": "./dist/index.mjs",
|
|
9
|
-
"types": "./dist/index.d.mts",
|
|
10
|
-
"exports": {
|
|
11
|
-
".": {
|
|
12
|
-
"types": "./dist/index.d.mts",
|
|
13
|
-
"default": "./dist/index.mjs"
|
|
14
|
-
},
|
|
15
|
-
"./pagination": {
|
|
16
|
-
"types": "./dist/pagination/PaginationEngine.d.mts",
|
|
17
|
-
"default": "./dist/pagination/PaginationEngine.mjs"
|
|
18
|
-
},
|
|
19
|
-
"./plugins": {
|
|
20
|
-
"types": "./dist/plugins/index.d.mts",
|
|
21
|
-
"default": "./dist/plugins/index.mjs"
|
|
22
|
-
},
|
|
23
|
-
"./utils": {
|
|
24
|
-
"types": "./dist/utils/index.d.mts",
|
|
25
|
-
"default": "./dist/utils/index.mjs"
|
|
26
|
-
},
|
|
27
|
-
"./actions": {
|
|
28
|
-
"types": "./dist/actions/index.d.mts",
|
|
29
|
-
"default": "./dist/actions/index.mjs"
|
|
30
|
-
},
|
|
31
|
-
"./ai": {
|
|
32
|
-
"types": "./dist/ai/index.d.mts",
|
|
33
|
-
"default": "./dist/ai/index.mjs"
|
|
34
|
-
},
|
|
35
|
-
"./query/primitives/geo": {
|
|
36
|
-
"types": "./dist/query/primitives/geo.d.mts",
|
|
37
|
-
"default": "./dist/query/primitives/geo.mjs"
|
|
38
|
-
},
|
|
39
|
-
"./query/primitives/coercion": {
|
|
40
|
-
"types": "./dist/query/primitives/coercion.d.mts",
|
|
41
|
-
"default": "./dist/query/primitives/coercion.mjs"
|
|
42
|
-
},
|
|
43
|
-
"./query/primitives/indexes": {
|
|
44
|
-
"types": "./dist/query/primitives/indexes.d.mts",
|
|
45
|
-
"default": "./dist/query/primitives/indexes.mjs"
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
"files": [
|
|
49
|
-
"dist",
|
|
50
|
-
"README.md",
|
|
51
|
-
"LICENSE"
|
|
52
|
-
],
|
|
53
|
-
"keywords": [
|
|
54
|
-
"mongodb",
|
|
55
|
-
"mongoose",
|
|
56
|
-
"repository",
|
|
57
|
-
"repository-pattern",
|
|
58
|
-
"data-access",
|
|
59
|
-
"pagination",
|
|
60
|
-
"cursor-pagination",
|
|
61
|
-
"infinite-scroll",
|
|
62
|
-
"offset-pagination",
|
|
63
|
-
"keyset-pagination",
|
|
64
|
-
"caching",
|
|
65
|
-
"redis",
|
|
66
|
-
"cache",
|
|
67
|
-
"multi-tenant",
|
|
68
|
-
"multi-tenancy",
|
|
69
|
-
"vector-search",
|
|
70
|
-
"embeddings",
|
|
71
|
-
"atlas-search",
|
|
72
|
-
"observability",
|
|
73
|
-
"event-driven",
|
|
74
|
-
"plugin-based",
|
|
75
|
-
"zero-dependencies",
|
|
76
|
-
"express",
|
|
77
|
-
"fastify",
|
|
78
|
-
"nestjs",
|
|
79
|
-
"nextjs",
|
|
80
|
-
"typescript"
|
|
81
|
-
],
|
|
82
|
-
"author": "Classytic <classytic.dev@gmail.com> (https://github.com/classytic)",
|
|
83
|
-
"contributors": [
|
|
84
|
-
"Sadman Chowdhury (https://github.com/siam923)"
|
|
85
|
-
],
|
|
86
|
-
"license": "MIT",
|
|
87
|
-
"repository": {
|
|
88
|
-
"type": "git",
|
|
89
|
-
"url": "git+https://github.com/classytic/mongokit.git"
|
|
90
|
-
},
|
|
91
|
-
"bugs": {
|
|
92
|
-
"url": "https://github.com/classytic/mongokit/issues"
|
|
93
|
-
},
|
|
94
|
-
"homepage": "https://github.com/classytic/mongokit#readme",
|
|
95
|
-
"peerDependencies": {
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
},
|
|
99
|
-
"engines": {
|
|
100
|
-
"node": ">=22"
|
|
101
|
-
},
|
|
102
|
-
"scripts": {
|
|
103
|
-
"build": "tsdown",
|
|
104
|
-
"dev": "tsdown --watch",
|
|
105
|
-
"test": "vitest run --project unit --project integration",
|
|
106
|
-
"test:unit": "vitest run --project unit",
|
|
107
|
-
"test:integration": "vitest run --project integration",
|
|
108
|
-
"test:e2e": "vitest run --project e2e",
|
|
109
|
-
"test:all": "vitest run --project unit --project integration --project e2e",
|
|
110
|
-
"test:watch": "vitest --project unit --project integration",
|
|
111
|
-
"test:coverage": "vitest run --coverage",
|
|
112
|
-
"typecheck": "tsc --noEmit",
|
|
113
|
-
"typecheck:tests": "tsc --noEmit -p tsconfig.tests.json",
|
|
114
|
-
"lint": "biome check src/",
|
|
115
|
-
"lint:fix": "biome check src/ --write",
|
|
116
|
-
"format": "biome format src/ --write",
|
|
117
|
-
"check": "biome ci src/ --diagnostic-level=error",
|
|
118
|
-
"
|
|
119
|
-
"
|
|
120
|
-
"publish:
|
|
121
|
-
"
|
|
122
|
-
"release:
|
|
123
|
-
"release
|
|
124
|
-
"release:
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
"@
|
|
130
|
-
"@
|
|
131
|
-
"@
|
|
132
|
-
"
|
|
133
|
-
"
|
|
134
|
-
"
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
"
|
|
139
|
-
"
|
|
140
|
-
"
|
|
141
|
-
"
|
|
142
|
-
|
|
143
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@classytic/mongokit",
|
|
3
|
+
"version": "3.12.0",
|
|
4
|
+
"description": "Production-grade MongoDB repositories - smart pagination, events, and plugins. Built on @classytic/repo-core.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.mjs",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.mts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.mts",
|
|
13
|
+
"default": "./dist/index.mjs"
|
|
14
|
+
},
|
|
15
|
+
"./pagination": {
|
|
16
|
+
"types": "./dist/pagination/PaginationEngine.d.mts",
|
|
17
|
+
"default": "./dist/pagination/PaginationEngine.mjs"
|
|
18
|
+
},
|
|
19
|
+
"./plugins": {
|
|
20
|
+
"types": "./dist/plugins/index.d.mts",
|
|
21
|
+
"default": "./dist/plugins/index.mjs"
|
|
22
|
+
},
|
|
23
|
+
"./utils": {
|
|
24
|
+
"types": "./dist/utils/index.d.mts",
|
|
25
|
+
"default": "./dist/utils/index.mjs"
|
|
26
|
+
},
|
|
27
|
+
"./actions": {
|
|
28
|
+
"types": "./dist/actions/index.d.mts",
|
|
29
|
+
"default": "./dist/actions/index.mjs"
|
|
30
|
+
},
|
|
31
|
+
"./ai": {
|
|
32
|
+
"types": "./dist/ai/index.d.mts",
|
|
33
|
+
"default": "./dist/ai/index.mjs"
|
|
34
|
+
},
|
|
35
|
+
"./query/primitives/geo": {
|
|
36
|
+
"types": "./dist/query/primitives/geo.d.mts",
|
|
37
|
+
"default": "./dist/query/primitives/geo.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./query/primitives/coercion": {
|
|
40
|
+
"types": "./dist/query/primitives/coercion.d.mts",
|
|
41
|
+
"default": "./dist/query/primitives/coercion.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./query/primitives/indexes": {
|
|
44
|
+
"types": "./dist/query/primitives/indexes.d.mts",
|
|
45
|
+
"default": "./dist/query/primitives/indexes.mjs"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"files": [
|
|
49
|
+
"dist",
|
|
50
|
+
"README.md",
|
|
51
|
+
"LICENSE"
|
|
52
|
+
],
|
|
53
|
+
"keywords": [
|
|
54
|
+
"mongodb",
|
|
55
|
+
"mongoose",
|
|
56
|
+
"repository",
|
|
57
|
+
"repository-pattern",
|
|
58
|
+
"data-access",
|
|
59
|
+
"pagination",
|
|
60
|
+
"cursor-pagination",
|
|
61
|
+
"infinite-scroll",
|
|
62
|
+
"offset-pagination",
|
|
63
|
+
"keyset-pagination",
|
|
64
|
+
"caching",
|
|
65
|
+
"redis",
|
|
66
|
+
"cache",
|
|
67
|
+
"multi-tenant",
|
|
68
|
+
"multi-tenancy",
|
|
69
|
+
"vector-search",
|
|
70
|
+
"embeddings",
|
|
71
|
+
"atlas-search",
|
|
72
|
+
"observability",
|
|
73
|
+
"event-driven",
|
|
74
|
+
"plugin-based",
|
|
75
|
+
"zero-dependencies",
|
|
76
|
+
"express",
|
|
77
|
+
"fastify",
|
|
78
|
+
"nestjs",
|
|
79
|
+
"nextjs",
|
|
80
|
+
"typescript"
|
|
81
|
+
],
|
|
82
|
+
"author": "Classytic <classytic.dev@gmail.com> (https://github.com/classytic)",
|
|
83
|
+
"contributors": [
|
|
84
|
+
"Sadman Chowdhury (https://github.com/siam923)"
|
|
85
|
+
],
|
|
86
|
+
"license": "MIT",
|
|
87
|
+
"repository": {
|
|
88
|
+
"type": "git",
|
|
89
|
+
"url": "git+https://github.com/classytic/mongokit.git"
|
|
90
|
+
},
|
|
91
|
+
"bugs": {
|
|
92
|
+
"url": "https://github.com/classytic/mongokit/issues"
|
|
93
|
+
},
|
|
94
|
+
"homepage": "https://github.com/classytic/mongokit#readme",
|
|
95
|
+
"peerDependencies": {
|
|
96
|
+
"@classytic/repo-core": ">=0.3.0",
|
|
97
|
+
"mongoose": ">=9.4.1"
|
|
98
|
+
},
|
|
99
|
+
"engines": {
|
|
100
|
+
"node": ">=22"
|
|
101
|
+
},
|
|
102
|
+
"scripts": {
|
|
103
|
+
"build": "tsdown",
|
|
104
|
+
"dev": "tsdown --watch",
|
|
105
|
+
"test": "vitest run --project unit --project integration",
|
|
106
|
+
"test:unit": "vitest run --project unit",
|
|
107
|
+
"test:integration": "vitest run --project integration",
|
|
108
|
+
"test:e2e": "vitest run --project e2e",
|
|
109
|
+
"test:all": "vitest run --project unit --project integration --project e2e",
|
|
110
|
+
"test:watch": "vitest --project unit --project integration",
|
|
111
|
+
"test:coverage": "vitest run --coverage",
|
|
112
|
+
"typecheck": "tsc --noEmit",
|
|
113
|
+
"typecheck:tests": "tsc --noEmit -p tsconfig.tests.json",
|
|
114
|
+
"lint": "biome check src/",
|
|
115
|
+
"lint:fix": "biome check src/ --write",
|
|
116
|
+
"format": "biome format src/ --write",
|
|
117
|
+
"check": "biome ci src/ --diagnostic-level=error",
|
|
118
|
+
"push": "classytic-push",
|
|
119
|
+
"prepublishOnly": "npm run check && npm run build && npm run typecheck && npm run typecheck:tests && npm test",
|
|
120
|
+
"publish:dry": "npm publish --dry-run --access public",
|
|
121
|
+
"publish:npm": "npm publish --access public",
|
|
122
|
+
"release:tag": "node -e \"require('child_process').execSync('npm run push -- v'+require('./package.json').version,{stdio:'inherit'})\"",
|
|
123
|
+
"release": "npm run push -- main && npm run release:tag && npm publish",
|
|
124
|
+
"release:patch": "npm version patch && npm run release",
|
|
125
|
+
"release:minor": "npm version minor && npm run release",
|
|
126
|
+
"release:major": "npm version major && npm run release"
|
|
127
|
+
},
|
|
128
|
+
"devDependencies": {
|
|
129
|
+
"@arethetypeswrong/cli": "^0.18.2",
|
|
130
|
+
"@biomejs/biome": "^2.4.10",
|
|
131
|
+
"@classytic/dev-tools": "^0.2.0",
|
|
132
|
+
"@classytic/repo-core": "^0.3.0",
|
|
133
|
+
"@types/node": "^22.0.0",
|
|
134
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
135
|
+
"ajv": "^8.18.0",
|
|
136
|
+
"ajv-formats": "^3.0.1",
|
|
137
|
+
"dotenv": "^17.4.2",
|
|
138
|
+
"knip": "^6.3.0",
|
|
139
|
+
"mongodb-memory-server": "^10.4.3",
|
|
140
|
+
"mongoose": "^9.4.1",
|
|
141
|
+
"publint": "^0.3.18",
|
|
142
|
+
"tsdown": "^0.21.8",
|
|
143
|
+
"typescript": "^5.7.0",
|
|
144
|
+
"vitest": "^3.2.4"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
File without changes
|