@classytic/mongokit 3.6.0 → 3.6.2

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 CHANGED
@@ -220,7 +220,7 @@ mongokit's job stops at "the hook has `context.session`." Everything else is com
220
220
  |---|---|
221
221
  | `methodRegistryPlugin` | Prerequisite for plugins that attach new methods |
222
222
  | `batchOperationsPlugin` | `updateMany`, `deleteMany`, `bulkWrite` with hook support |
223
- | `multiTenantPlugin` | Inject tenant scope at POLICY priority — impossible to forget |
223
+ | `multiTenantPlugin` | Inject tenant scope at POLICY priority — supports `fieldType: 'objectId'` for `$lookup`/`.populate()` |
224
224
  | `softDeletePlugin` | `deletedAt` / custom field, `restore`, `getDeleted`, TTL, `before:restore` / `after:restore` hooks |
225
225
  | `cascadePlugin` | Cascade delete; prefer `{ repo: targetRepo, foreignKey, softDelete? }` to route through the target's hook pipeline |
226
226
  | `customIdPlugin` | Stripe-style prefixed public IDs (`txn_a7b3xk9m`) on top of `_id` |
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { $ as ReadPreferenceType, A as InferDocument, At as LookupOptions, B as NonNullableFields, C as EventPayload, Ct as WithPlugins, D as GroupResult, Dt as IRequestContext, E as FieldRules, Et as IControllerResponse, F as KeysetPaginationResult, G as PaginationConfig, H as OffsetPaginationOptions, I as Logger, J as Plugin, K as PaginationResult, L as LookupPopulateOptions, M as JsonSchema, N as KeysOfType, O as HookMode, Ot as IResponseFormatter, P as KeysetPaginationOptions, Q as ReadOptions, R as LookupPopulateResult, S as EventHandlers, St as ValidatorDefinition, T as FieldPreset, Tt as IController, U as OffsetPaginationResult, V as ObjectId, W as OperationOptions, X as PluginType, Y as PluginFunction, Z as PopulateSpec, _ as CrudSchemas, _t as UpdateOptions, a as AnyDocument, at as RequiredBy, b as DeleteResult, bt as ValidationChainOptions, c as CacheOperationOptions, ct as SessionOptions, d as CacheableOptions, dt as SoftDeleteRepository, et as RepositoryContext, f as CascadeOptions, ft as SortDirection, g as CreateOptions, gt as UpdateManyResult, h as CreateInput, ht as UpdateInput, i as AllPluginMethods, it as RepositoryOptions, j as InferRawDoc, k as HttpError, kt as LookupBuilder, l as CacheOptions, lt as SoftDeleteFilterMode, m as CollationOptions, mt as Strict, n as AggregatePaginationOptions, nt as RepositoryInstance, o as AnyModel, ot as SchemaBuilderOptions, p as CascadeRelation, pt as SortSpec, q as PartialBy, r as AggregatePaginationResult, rt as RepositoryOperation, s as CacheAdapter, st as SelectSpec, t as AggregateOptions, tt as RepositoryEvent, u as CacheStats, ut as SoftDeleteOptions, v as DecodedCursor, vt as UpdateWithValidationResult, w as EventPhase, wt as WithTransactionOptions, x as DocField, xt as ValidationResult, y as DeepPartial, yt as UserContext, z as MinMaxResult } from "./types-DiQfDesD.mjs";
2
2
  import { t as index_d_exports } from "./index-BSRSsRRx.mjs";
3
3
  import { PaginationEngine } from "./pagination/PaginationEngine.mjs";
4
- import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, R as BulkWriteResult, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, z as batchOperationsPlugin } from "./validation-chain.plugin-COKNRAwp.mjs";
4
+ import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, R as BulkWriteResult, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, z as batchOperationsPlugin } from "./validation-chain.plugin-BsFzKVnO.mjs";
5
5
  import { n as SchemaPathsLike, t as FieldType$1 } from "./coercion-B19MD38s.mjs";
6
6
  import { n as SchemaIndexes } from "./indexes-qIBCZ3mY.mjs";
7
7
  import { a as isFieldUpdateAllowed, c as configureLogger, d as getFieldsForUser, f as getMongooseProjection, i as getSystemManagedFields, l as createFieldPreset, m as parseDuplicateKeyError, n as buildCrudSchemasFromMongooseSchema, o as validateUpdateBody, p as createError, r as getImmutableFields, s as createMemoryCache, t as buildCrudSchemasFromModel, u as filterResponseData } from "./mongooseToJsonSchema-D2YjHo7W.mjs";
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import { a as warn, n as parseDuplicateKeyError, r as configureLogger, t as crea
2
2
  import { y as LookupBuilder } from "./update-AVfKWNGt.mjs";
3
3
  import { t as actions_exports } from "./actions/index.mjs";
4
4
  import { t as PaginationEngine } from "./PaginationEngine-CunXkR9p.mjs";
5
- import { A as auditTrailPlugin, C as HOOK_PRIORITY, D as AggregationBuilder, E as withTransaction, M as aggregateHelpersPlugin, O as batchOperationsPlugin, S as cachePlugin, T as isTransactionUnsupported, _ as dateSequentialId, a as uniqueField, b as sequentialId, c as subdocumentPlugin, d as multiTenantPlugin, f as mongoOperationsPlugin, g as customIdPlugin, h as elasticSearchPlugin, i as requireField, j as auditLogPlugin, k as AuditTrailQuery, l as softDeletePlugin, m as fieldFilterPlugin, n as blockIf, o as validationChainPlugin, p as methodRegistryPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as observabilityPlugin, v as getNextSequence, w as Repository, x as cascadePlugin, y as prefixedId } from "./validation-chain.plugin-3rr7dlw6.mjs";
5
+ import { A as auditTrailPlugin, C as HOOK_PRIORITY, D as AggregationBuilder, E as withTransaction, M as aggregateHelpersPlugin, O as batchOperationsPlugin, S as cachePlugin, T as isTransactionUnsupported, _ as dateSequentialId, a as uniqueField, b as sequentialId, c as subdocumentPlugin, d as multiTenantPlugin, f as mongoOperationsPlugin, g as customIdPlugin, h as elasticSearchPlugin, i as requireField, j as auditLogPlugin, k as AuditTrailQuery, l as softDeletePlugin, m as fieldFilterPlugin, n as blockIf, o as validationChainPlugin, p as methodRegistryPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as observabilityPlugin, v as getNextSequence, w as Repository, x as cascadePlugin, y as prefixedId } from "./validation-chain.plugin-7A5qGEQq.mjs";
6
6
  import { isGeoOperator, parseGeoFilter } from "./query/primitives/geo.mjs";
7
7
  import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-C5o7jyyA.mjs";
8
8
  import { buildFieldTypeMap, coerceFieldValue, coerceHeuristic } from "./query/primitives/coercion.mjs";
@@ -1,2 +1,2 @@
1
- import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, y as MethodRegistryRepository, z as batchOperationsPlugin } from "../validation-chain.plugin-COKNRAwp.mjs";
1
+ import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, y as MethodRegistryRepository, z as batchOperationsPlugin } from "../validation-chain.plugin-BsFzKVnO.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, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, 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 auditTrailPlugin, M as aggregateHelpersPlugin, O as batchOperationsPlugin, S as cachePlugin, _ as dateSequentialId, a as uniqueField, b as sequentialId, c as subdocumentPlugin, d as multiTenantPlugin, f as mongoOperationsPlugin, g as customIdPlugin, h as elasticSearchPlugin, i as requireField, j as auditLogPlugin, k as AuditTrailQuery, l as softDeletePlugin, m as fieldFilterPlugin, n as blockIf, o as validationChainPlugin, p as methodRegistryPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as observabilityPlugin, v as getNextSequence, x as cascadePlugin, y as prefixedId } from "../validation-chain.plugin-3rr7dlw6.mjs";
1
+ import { A as auditTrailPlugin, M as aggregateHelpersPlugin, O as batchOperationsPlugin, S as cachePlugin, _ as dateSequentialId, a as uniqueField, b as sequentialId, c as subdocumentPlugin, d as multiTenantPlugin, f as mongoOperationsPlugin, g as customIdPlugin, h as elasticSearchPlugin, i as requireField, j as auditLogPlugin, k as AuditTrailQuery, l as softDeletePlugin, m as fieldFilterPlugin, n as blockIf, o as validationChainPlugin, p as methodRegistryPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as observabilityPlugin, v as getNextSequence, x as cascadePlugin, y as prefixedId } from "../validation-chain.plugin-7A5qGEQq.mjs";
2
2
  export { AuditTrailQuery, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
@@ -3154,6 +3154,11 @@ function getCounterModel(connection) {
3154
3154
  *
3155
3155
  * @param counterKey - Unique key identifying this counter (e.g., "Invoice" or "Invoice:2026-02")
3156
3156
  * @param increment - Value to increment by (default: 1)
3157
+ * @param connection - Mongoose connection to use (defaults to the default connection)
3158
+ * @param session - Optional client session. When provided, the counter bump
3159
+ * participates in the caller's transaction — if the surrounding transaction
3160
+ * aborts, the counter does NOT advance. Without a session, the bump commits
3161
+ * immediately and is not rolled back if a sibling write fails.
3157
3162
  * @returns The next sequence number (after increment)
3158
3163
  *
3159
3164
  * @example
@@ -3163,11 +3168,19 @@ function getCounterModel(connection) {
3163
3168
  * @example Batch increment for createMany
3164
3169
  * const startSeq = await getNextSequence('invoices', 5);
3165
3170
  * // If current was 10, returns 15 (you use 11, 12, 13, 14, 15)
3171
+ *
3172
+ * @example Transactional counter bump
3173
+ * await withTransaction(conn, async (session) => {
3174
+ * const seq = await getNextSequence('invoices', 1, conn, session);
3175
+ * await invoiceRepo.create({ invoiceNumber: `INV-${seq}` }, { session });
3176
+ * // if this throws, the counter is rolled back with the insert
3177
+ * });
3166
3178
  */
3167
- async function getNextSequence(counterKey, increment = 1, connection) {
3179
+ async function getNextSequence(counterKey, increment = 1, connection, session) {
3168
3180
  const result = await getCounterModel(connection).findOneAndUpdate({ _id: counterKey }, { $inc: { seq: increment } }, {
3169
3181
  upsert: true,
3170
- returnDocument: "after"
3182
+ returnDocument: "after",
3183
+ session
3171
3184
  });
3172
3185
  if (!result) throw new Error(`Failed to increment counter '${counterKey}'`);
3173
3186
  return result.seq;
@@ -3190,7 +3203,7 @@ function sequentialId(options) {
3190
3203
  const { prefix, model, padding = 4, separator = "-", counterKey } = options;
3191
3204
  const key = counterKey || model.modelName;
3192
3205
  return async (context) => {
3193
- const seq = await getNextSequence(key, 1, context._counterConnection);
3206
+ const seq = await getNextSequence(key, 1, context._counterConnection, context.session);
3194
3207
  return `${prefix}${separator}${String(seq).padStart(padding, "0")}`;
3195
3208
  };
3196
3209
  }
@@ -3238,7 +3251,7 @@ function dateSequentialId(options) {
3238
3251
  counterKey = `${model.modelName}:${year}-${month}`;
3239
3252
  break;
3240
3253
  }
3241
- const seq = await getNextSequence(counterKey, 1, context._counterConnection);
3254
+ const seq = await getNextSequence(counterKey, 1, context._counterConnection, context.session);
3242
3255
  return `${prefix}${separator}${datePart}${separator}${String(seq).padStart(padding, "0")}`;
3243
3256
  };
3244
3257
  }
@@ -3706,7 +3719,7 @@ function mongoOperationsPlugin() {
3706
3719
  * ```
3707
3720
  */
3708
3721
  function multiTenantPlugin(options = {}) {
3709
- const { tenantField = "organizationId", contextKey = "organizationId", required = true, skipOperations = [], skipWhen, resolveContext } = options;
3722
+ const { tenantField = "organizationId", contextKey = "organizationId", required = true, skipOperations = [], skipWhen, resolveContext, fieldType = "string" } = options;
3710
3723
  const filterOps = [
3711
3724
  "getAll",
3712
3725
  "findAll",
@@ -3755,25 +3768,26 @@ function multiTenantPlugin(options = {}) {
3755
3768
  }
3756
3769
  if (!tenantId && required) throw new Error(`[mongokit] Multi-tenant: Missing '${contextKey}' in context for '${op}'. Pass it via options or set required: false.`);
3757
3770
  if (!tenantId) return;
3771
+ const castId = fieldType === "objectId" ? new mongoose.Types.ObjectId(tenantId) : tenantId;
3758
3772
  if (filterOps.includes(op) || filterReadOps.includes(op)) context.filters = {
3759
3773
  ...context.filters,
3760
- [tenantField]: tenantId
3774
+ [tenantField]: castId
3761
3775
  };
3762
3776
  if (queryReadOps.includes(op)) context.query = {
3763
3777
  ...context.query,
3764
- [tenantField]: tenantId
3778
+ [tenantField]: castId
3765
3779
  };
3766
- if (op === "create" && context.data) context.data[tenantField] = tenantId;
3780
+ if (op === "create" && context.data) context.data[tenantField] = castId;
3767
3781
  if (op === "createMany" && context.dataArray) {
3768
- for (const doc of context.dataArray) if (doc && typeof doc === "object") doc[tenantField] = tenantId;
3782
+ for (const doc of context.dataArray) if (doc && typeof doc === "object") doc[tenantField] = castId;
3769
3783
  }
3770
3784
  if (constrainedWriteOps.includes(op)) context.query = {
3771
3785
  ...context.query,
3772
- [tenantField]: tenantId
3786
+ [tenantField]: castId
3773
3787
  };
3774
3788
  if (batchQueryOps.includes(op)) context.query = {
3775
3789
  ...context.query,
3776
- [tenantField]: tenantId
3790
+ [tenantField]: castId
3777
3791
  };
3778
3792
  if (op === "bulkWrite" && context.operations) {
3779
3793
  const ops = context.operations;
@@ -3788,11 +3802,11 @@ function multiTenantPlugin(options = {}) {
3788
3802
  const opBody = subOp[key];
3789
3803
  if (opBody?.filter) opBody.filter = {
3790
3804
  ...opBody.filter,
3791
- [tenantField]: tenantId
3805
+ [tenantField]: castId
3792
3806
  };
3793
3807
  }
3794
3808
  const insertBody = subOp.insertOne;
3795
- if (insertBody?.document) insertBody.document[tenantField] = tenantId;
3809
+ if (insertBody?.document) insertBody.document[tenantField] = castId;
3796
3810
  }
3797
3811
  }
3798
3812
  }, { priority: HOOK_PRIORITY.POLICY });
@@ -432,6 +432,11 @@ interface CustomIdOptions {
432
432
  *
433
433
  * @param counterKey - Unique key identifying this counter (e.g., "Invoice" or "Invoice:2026-02")
434
434
  * @param increment - Value to increment by (default: 1)
435
+ * @param connection - Mongoose connection to use (defaults to the default connection)
436
+ * @param session - Optional client session. When provided, the counter bump
437
+ * participates in the caller's transaction — if the surrounding transaction
438
+ * aborts, the counter does NOT advance. Without a session, the bump commits
439
+ * immediately and is not rolled back if a sibling write fails.
435
440
  * @returns The next sequence number (after increment)
436
441
  *
437
442
  * @example
@@ -441,8 +446,15 @@ interface CustomIdOptions {
441
446
  * @example Batch increment for createMany
442
447
  * const startSeq = await getNextSequence('invoices', 5);
443
448
  * // If current was 10, returns 15 (you use 11, 12, 13, 14, 15)
449
+ *
450
+ * @example Transactional counter bump
451
+ * await withTransaction(conn, async (session) => {
452
+ * const seq = await getNextSequence('invoices', 1, conn, session);
453
+ * await invoiceRepo.create({ invoiceNumber: `INV-${seq}` }, { session });
454
+ * // if this throws, the counter is rolled back with the insert
455
+ * });
444
456
  */
445
- declare function getNextSequence(counterKey: string, increment?: number, connection?: mongoose.Connection): Promise<number>;
457
+ declare function getNextSequence(counterKey: string, increment?: number, connection?: mongoose.Connection, session?: mongoose.ClientSession): Promise<number>;
446
458
  interface SequentialIdOptions {
447
459
  /** Prefix string (e.g., 'INV', 'ORD') */
448
460
  prefix: string;
@@ -835,6 +847,17 @@ interface MultiTenantOptions {
835
847
  * ```
836
848
  */
837
849
  resolveContext?: () => string | undefined;
850
+ /**
851
+ * How to store/query the tenant ID.
852
+ *
853
+ * - `'string'` (default): inject the tenant ID as-is (raw string).
854
+ * - `'objectId'`: cast to `mongoose.Types.ObjectId` before injecting.
855
+ *
856
+ * Choose `'objectId'` when the schema declares the tenant field as
857
+ * `Schema.Types.ObjectId` (e.g., Flow, accounting). This enables
858
+ * `$lookup` and `.populate()` against the referenced collection.
859
+ */
860
+ fieldType?: 'string' | 'objectId';
838
861
  }
839
862
  declare function multiTenantPlugin(options?: MultiTenantOptions): Plugin;
840
863
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/mongokit",
3
- "version": "3.6.0",
3
+ "version": "3.6.2",
4
4
  "description": "Production-grade MongoDB repositories with zero dependencies - smart pagination, events, and plugins",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -118,13 +118,15 @@
118
118
  "release:major": "npm version major && npm run release"
119
119
  },
120
120
  "devDependencies": {
121
+ "@arethetypeswrong/cli": "^0.18.2",
121
122
  "@biomejs/biome": "^2.4.10",
122
123
  "@types/node": "^22.0.0",
123
124
  "@vitest/coverage-v8": "^3.2.4",
124
125
  "knip": "^6.3.0",
125
126
  "mongodb-memory-server": "^10.4.3",
126
127
  "mongoose": "^9.4.1",
127
- "tsdown": "^0.21.7",
128
+ "publint": "^0.3.18",
129
+ "tsdown": "^0.21.8",
128
130
  "typescript": "^5.7.0",
129
131
  "vitest": "^3.2.4"
130
132
  }