@classytic/mongokit 3.10.2 → 3.10.3

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/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { $ as RepositoryContext, A as InferRawDoc, B as OffsetPaginationOptions, C as EventPhase, Ct as IControllerResponse, D as HookMode, Dt as LookupOptions, E as GroupResult, Et as LookupBuilder, F as LookupPopulateOptions, G as PartialBy, H as OperationOptions, I as LookupPopulateResult, J as PluginType, K as Plugin, L as MinMaxResult, M as KeysetPaginationOptions, N as KeysetPaginationResult, O as HttpError, P as Logger, Q as ReadPreferenceType, R as NonNullableFields, S as EventPayload, St as IController, T as FindOneAndUpdateOptions, Tt as IResponseFormatter, U as PaginationConfig, V as OffsetPaginationResult, W as PaginationResult, X as PrioritizedHook, Y as PopulateSpec, Z as ReadOptions, _ as DecodedCursor, _t as UserContext, a as AnyDocument, at as SelectSpec, b as DocField, bt as WithPlugins, c as CacheOperationOptions, ct as SoftDeleteOptions, d as CacheableOptions, dt as SortSpec, et as RepositoryEvent, f as CascadeOptions, ft as Strict, g as CreateOptions, gt as UpdateWithValidationResult, h as CreateInput, ht as UpdateOptions, i as AllPluginMethods, it as RequiredBy, j as KeysOfType, k as InferDocument, l as CacheOptions, lt as SoftDeleteRepository, m as CollationOptions, mt as UpdateManyResult, n as AggregatePaginationOptions, nt as RepositoryOperation, o as AnyModel, ot as SessionOptions, p as CascadeRelation, pt as UpdateInput, q as PluginFunction, r as AggregatePaginationResult, rt as RepositoryOptions, s as CacheAdapter, st as SoftDeleteFilterMode, t as AggregateOptions, tt as RepositoryInstance, u as CacheStats, ut as SortDirection, v as DeepPartial, vt as ValidationChainOptions, w as FieldPreset, wt as IRequestContext, x as EventHandlers, xt as WithTransactionOptions, y as DeleteResult, yt as ValidatorDefinition, z as ObjectId } from "./types-CYFJa36g.mjs";
2
2
  import { t as index_d_exports } from "./index-CNNavGpM.mjs";
3
3
  import { PaginationEngine } from "./pagination/PaginationEngine.mjs";
4
- import { $ as aggregateHelpersPlugin, A as PrefixedIdOptions, B as BatchOperationsMethods, C as methodRegistryPlugin, D as CustomIdOptions, E as elasticSearchPlugin, F as prefixedId, G as AuditQueryOptions, H as batchOperationsPlugin, I as sequentialId, J as AuditTrailOptions, K as AuditQueryResult, L as cascadePlugin, M as customIdPlugin, N as dateSequentialId, O as DateSequentialIdOptions, P as getNextSequence, Q as AggregateHelpersMethods, R as CacheMethods, T as ElasticSearchOptions, U as AuditEntry, V as BulkWriteResult, W as AuditOperation, X as auditTrailPlugin, Y as AuditTrailQuery, Z as auditLogPlugin, _ as observabilityPlugin, a as uniqueField, b as MongoOperationsMethods, c as TenantContext, d as SubdocumentMethods, f as subdocumentPlugin, g as OperationMetric, h as ObservabilityOptions, i as requireField, j as SequentialIdOptions, k as IdGenerator, l as TenantStore, m as softDeletePlugin, n as blockIf, o as validationChainPlugin, p as SoftDeleteMethods, q as AuditTrailMethods, r as immutableField, s as timestampPlugin, t as autoInject, u as createTenantContext, v as MultiTenantOptions, w as fieldFilterPlugin, x as mongoOperationsPlugin, y as multiTenantPlugin, z as cachePlugin } from "./validation-chain.plugin-BNG3coI0.mjs";
4
+ import { $ as aggregateHelpersPlugin, A as PrefixedIdOptions, B as BatchOperationsMethods, C as methodRegistryPlugin, D as CustomIdOptions, E as elasticSearchPlugin, F as prefixedId, G as AuditQueryOptions, H as batchOperationsPlugin, I as sequentialId, J as AuditTrailOptions, K as AuditQueryResult, L as cascadePlugin, M as customIdPlugin, N as dateSequentialId, O as DateSequentialIdOptions, P as getNextSequence, Q as AggregateHelpersMethods, R as CacheMethods, T as ElasticSearchOptions, U as AuditEntry, V as BulkWriteResult, W as AuditOperation, X as auditTrailPlugin, Y as AuditTrailQuery, Z as auditLogPlugin, _ as observabilityPlugin, a as uniqueField, b as MongoOperationsMethods, c as TenantContext, d as SubdocumentMethods, f as subdocumentPlugin, g as OperationMetric, h as ObservabilityOptions, i as requireField, j as SequentialIdOptions, k as IdGenerator, l as TenantStore, m as softDeletePlugin, n as blockIf, o as validationChainPlugin, p as SoftDeleteMethods, q as AuditTrailMethods, r as immutableField, s as timestampPlugin, t as autoInject, u as createTenantContext, v as MultiTenantOptions, w as fieldFilterPlugin, x as mongoOperationsPlugin, y as multiTenantPlugin, z as cachePlugin } from "./validation-chain.plugin-BYJo0Y6g.mjs";
5
5
  import { n as SchemaPathsLike, t as FieldType$1 } from "./coercion-oM8G4b6m.mjs";
6
6
  import { n as SchemaIndexes } from "./indexes-C26GNZRU.mjs";
7
7
  import { a as createFieldPreset, c as getMongooseProjection, d as parseDuplicateKeyError, i as configureLogger, l as createError, n as buildCrudSchemasFromMongooseSchema, o as filterResponseData, r as createMemoryCache, s as getFieldsForUser, t as buildCrudSchemasFromModel, u as isDuplicateKeyError } from "./mongooseToJsonSchema-Bi8hNbj8.mjs";
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import { r as warn, t as configureLogger } from "./logger-DJ7egMnd.mjs";
2
2
  import { b as LookupBuilder } from "./update-CWXfFC6O.mjs";
3
3
  import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-CzYwrfUP.mjs";
4
4
  import { t as actions_exports } from "./actions/index.mjs";
5
- import { A as AuditTrailQuery, C as cachePlugin, D as withTransaction, E as isTransactionUnsupported, F as MUTATING_OPERATIONS, I as OP_REGISTRY, L as READ_OPERATIONS, M as auditLogPlugin, N as aggregateHelpersPlugin, O as AggregationBuilder, P as ALL_OPERATIONS, R as operationsByPolicyKey, S as cascadePlugin, T as Repository, _ as customIdPlugin, a as uniqueField, b as prefixedId, c as createTenantContext, d as observabilityPlugin, f as multiTenantPlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, j as auditTrailPlugin, k as batchOperationsPlugin, l as subdocumentPlugin, m as methodRegistryPlugin, n as blockIf, o as validationChainPlugin, p as mongoOperationsPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as softDeletePlugin, v as dateSequentialId, w as HOOK_PRIORITY, x as sequentialId, y as getNextSequence } from "./validation-chain.plugin-Bt8HepWW.mjs";
5
+ import { A as AuditTrailQuery, C as cachePlugin, D as withTransaction, E as isTransactionUnsupported, F as MUTATING_OPERATIONS, I as OP_REGISTRY, L as READ_OPERATIONS, M as auditLogPlugin, N as aggregateHelpersPlugin, O as AggregationBuilder, P as ALL_OPERATIONS, R as operationsByPolicyKey, S as cascadePlugin, T as Repository, _ as customIdPlugin, a as uniqueField, b as prefixedId, c as createTenantContext, d as observabilityPlugin, f as multiTenantPlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, j as auditTrailPlugin, k as batchOperationsPlugin, l as subdocumentPlugin, m as methodRegistryPlugin, n as blockIf, o as validationChainPlugin, p as mongoOperationsPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as softDeletePlugin, v as dateSequentialId, w as HOOK_PRIORITY, x as sequentialId, y as getNextSequence } from "./validation-chain.plugin-D-yH2f8a.mjs";
6
6
  import { t as PaginationEngine } from "./PaginationEngine-B93fLCcO.mjs";
7
7
  import { isGeoOperator, parseGeoFilter } from "./query/primitives/geo.mjs";
8
8
  import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-dI0m4RBs.mjs";
@@ -1,2 +1,2 @@
1
- import { $ as aggregateHelpersPlugin, A as PrefixedIdOptions, B as BatchOperationsMethods, C as methodRegistryPlugin, D as CustomIdOptions, E as elasticSearchPlugin, F as prefixedId, G as AuditQueryOptions, H as batchOperationsPlugin, I as sequentialId, J as AuditTrailOptions, K as AuditQueryResult, L as cascadePlugin, M as customIdPlugin, N as dateSequentialId, O as DateSequentialIdOptions, P as getNextSequence, Q as AggregateHelpersMethods, R as CacheMethods, S as MethodRegistryRepository, T as ElasticSearchOptions, U as AuditEntry, W as AuditOperation, X as auditTrailPlugin, Y as AuditTrailQuery, Z as auditLogPlugin, _ as observabilityPlugin, a as uniqueField, b as MongoOperationsMethods, c as TenantContext, d as SubdocumentMethods, f as subdocumentPlugin, g as OperationMetric, h as ObservabilityOptions, i as requireField, j as SequentialIdOptions, k as IdGenerator, l as TenantStore, m as softDeletePlugin, n as blockIf, o as validationChainPlugin, p as SoftDeleteMethods, q as AuditTrailMethods, r as immutableField, s as timestampPlugin, t as autoInject, u as createTenantContext, v as MultiTenantOptions, w as fieldFilterPlugin, x as mongoOperationsPlugin, y as multiTenantPlugin, z as cachePlugin } from "../validation-chain.plugin-BNG3coI0.mjs";
1
+ import { $ as aggregateHelpersPlugin, A as PrefixedIdOptions, B as BatchOperationsMethods, C as methodRegistryPlugin, D as CustomIdOptions, E as elasticSearchPlugin, F as prefixedId, G as AuditQueryOptions, H as batchOperationsPlugin, I as sequentialId, J as AuditTrailOptions, K as AuditQueryResult, L as cascadePlugin, M as customIdPlugin, N as dateSequentialId, O as DateSequentialIdOptions, P as getNextSequence, Q as AggregateHelpersMethods, R as CacheMethods, S as MethodRegistryRepository, T as ElasticSearchOptions, U as AuditEntry, W as AuditOperation, X as auditTrailPlugin, Y as AuditTrailQuery, Z as auditLogPlugin, _ as observabilityPlugin, a as uniqueField, b as MongoOperationsMethods, c as TenantContext, d as SubdocumentMethods, f as subdocumentPlugin, g as OperationMetric, h as ObservabilityOptions, i as requireField, j as SequentialIdOptions, k as IdGenerator, l as TenantStore, m as softDeletePlugin, n as blockIf, o as validationChainPlugin, p as SoftDeleteMethods, q as AuditTrailMethods, r as immutableField, s as timestampPlugin, t as autoInject, u as createTenantContext, v as MultiTenantOptions, w as fieldFilterPlugin, x as mongoOperationsPlugin, y as multiTenantPlugin, z as cachePlugin } from "../validation-chain.plugin-BYJo0Y6g.mjs";
2
2
  export { type AggregateHelpersMethods, type AuditEntry, type AuditOperation, type AuditQueryOptions, type AuditQueryResult, type AuditTrailMethods, type AuditTrailOptions, AuditTrailQuery, type BatchOperationsMethods, type CacheMethods, type CustomIdOptions, type DateSequentialIdOptions, type ElasticSearchOptions, type IdGenerator, type MethodRegistryRepository, type MongoOperationsMethods, type MultiTenantOptions, type ObservabilityOptions, type OperationMetric, type PrefixedIdOptions, type SequentialIdOptions, type SoftDeleteMethods, type SubdocumentMethods, type TenantContext, type TenantStore, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, createTenantContext, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
@@ -1,2 +1,2 @@
1
- import { A as AuditTrailQuery, C as cachePlugin, M as auditLogPlugin, N as aggregateHelpersPlugin, S as cascadePlugin, _ as customIdPlugin, a as uniqueField, b as prefixedId, c as createTenantContext, d as observabilityPlugin, f as multiTenantPlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, j as auditTrailPlugin, k as batchOperationsPlugin, l as subdocumentPlugin, m as methodRegistryPlugin, n as blockIf, o as validationChainPlugin, p as mongoOperationsPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as softDeletePlugin, v as dateSequentialId, x as sequentialId, y as getNextSequence } from "../validation-chain.plugin-Bt8HepWW.mjs";
1
+ import { A as AuditTrailQuery, C as cachePlugin, M as auditLogPlugin, N as aggregateHelpersPlugin, S as cascadePlugin, _ as customIdPlugin, a as uniqueField, b as prefixedId, c as createTenantContext, d as observabilityPlugin, f as multiTenantPlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, j as auditTrailPlugin, k as batchOperationsPlugin, l as subdocumentPlugin, m as methodRegistryPlugin, n as blockIf, o as validationChainPlugin, p as mongoOperationsPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as softDeletePlugin, v as dateSequentialId, x as sequentialId, y as getNextSequence } from "../validation-chain.plugin-D-yH2f8a.mjs";
2
2
  export { AuditTrailQuery, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, createTenantContext, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
@@ -827,6 +827,27 @@ interface MultiTenantOptions {
827
827
  * `$lookup` and `.populate()` against the referenced collection.
828
828
  */
829
829
  fieldType?: 'string' | 'objectId';
830
+ /**
831
+ * When `true` (default), bypass the `required` throw if the operation's
832
+ * policy target already carries the tenant field. This lets hosts that
833
+ * stamp the tenant into the payload themselves (e.g., `data[tenantField]`
834
+ * on writes, `filters[tenantField]` on paginated reads) use the plugin
835
+ * without having to hand-roll a `skipWhen` that duplicates this check.
836
+ *
837
+ * Set to `false` to restore the pre-data-injection strict behavior: the
838
+ * tenant MUST come from `context` or `resolveContext`, otherwise the
839
+ * plugin throws (when `required: true`).
840
+ *
841
+ * Composition: a user-supplied `skipWhen` still runs first and can always
842
+ * opt out. This option controls the behavior after `skipWhen` and
843
+ * `resolveContext` have had their turn.
844
+ *
845
+ * Safety: when the payload supplies the tenant, the plugin skips its own
846
+ * injection (it does not overwrite). Cross-tenant isolation is therefore
847
+ * only as strong as the caller's own stamping — same guarantee as a
848
+ * hand-rolled `skipWhen`.
849
+ */
850
+ allowDataInjection?: boolean;
830
851
  }
831
852
  declare function multiTenantPlugin(options?: MultiTenantOptions): Plugin;
832
853
  //#endregion
@@ -4507,8 +4507,57 @@ function mongoOperationsPlugin() {
4507
4507
  * ]);
4508
4508
  * ```
4509
4509
  */
4510
+ /**
4511
+ * True when the op's policy target already has `tenantField` set by the
4512
+ * caller. Used to decide whether the plugin can safely skip injecting a
4513
+ * tenant scope rather than throwing on a missing context.
4514
+ *
4515
+ * - `data` — `context.data[tenantField]` is present
4516
+ * - `dataArray` — every row in `context.dataArray` has `tenantField`
4517
+ * - `query` — `context.query[tenantField]` is present
4518
+ * - `filters` — `context.filters[tenantField]` is present
4519
+ * - `operations` — every bulkWrite sub-op's filter/document has `tenantField`
4520
+ * - `none` — unreachable (the hook isn't registered for these ops)
4521
+ *
4522
+ * For multi-row targets (`dataArray`, `operations`) we require EVERY row to
4523
+ * be stamped. Partial stamping is ambiguous (we have no resolver value to
4524
+ * fill in the gaps) and is safer to treat as "not stamped" so the caller
4525
+ * either stamps all rows or supplies a context/resolver.
4526
+ */
4527
+ function payloadHasTenantField(context, policyKey, tenantField) {
4528
+ switch (policyKey) {
4529
+ case "data": return context.data?.[tenantField] != null;
4530
+ case "dataArray": {
4531
+ const arr = context.dataArray;
4532
+ if (!Array.isArray(arr) || arr.length === 0) return false;
4533
+ return arr.every((row) => row && row[tenantField] != null);
4534
+ }
4535
+ case "query": return context.query?.[tenantField] != null;
4536
+ case "filters": return context.filters?.[tenantField] != null;
4537
+ case "operations": {
4538
+ const ops = context.operations;
4539
+ if (!Array.isArray(ops) || ops.length === 0) return false;
4540
+ return ops.every((subOp) => {
4541
+ for (const key of [
4542
+ "updateOne",
4543
+ "updateMany",
4544
+ "deleteOne",
4545
+ "deleteMany",
4546
+ "replaceOne"
4547
+ ]) {
4548
+ const body = subOp[key];
4549
+ if (body) return body.filter?.[tenantField] != null;
4550
+ }
4551
+ const ins = subOp.insertOne;
4552
+ if (ins) return ins.document?.[tenantField] != null;
4553
+ return false;
4554
+ });
4555
+ }
4556
+ default: return false;
4557
+ }
4558
+ }
4510
4559
  function multiTenantPlugin(options = {}) {
4511
- const { tenantField = "organizationId", contextKey = "organizationId", required = true, skipOperations = [], skipWhen, resolveContext, fieldType = "string" } = options;
4560
+ const { tenantField = "organizationId", contextKey = "organizationId", required = true, skipOperations = [], skipWhen, resolveContext, fieldType = "string", allowDataInjection = true } = options;
4512
4561
  const extraOps = [{
4513
4562
  op: "getDeleted",
4514
4563
  policyKey: "filters"
@@ -4530,6 +4579,7 @@ function multiTenantPlugin(options = {}) {
4530
4579
  tenantId = resolveContext();
4531
4580
  if (tenantId) context[contextKey] = tenantId;
4532
4581
  }
4582
+ if (!tenantId && allowDataInjection && payloadHasTenantField(context, policyKey, tenantField)) return;
4533
4583
  if (!tenantId && required) throw new Error(`[mongokit] Multi-tenant: Missing '${contextKey}' in context for '${op}'. Pass it via options or set required: false.`);
4534
4584
  if (!tenantId) return;
4535
4585
  const castId = fieldType === "objectId" ? new mongoose.Types.ObjectId(tenantId) : tenantId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/mongokit",
3
- "version": "3.10.2",
3
+ "version": "3.10.3",
4
4
  "description": "Production-grade MongoDB repositories - smart pagination, events, and plugins. Built on @classytic/repo-core.",
5
5
  "type": "module",
6
6
  "sideEffects": false,