@classytic/mongokit 3.20.0 → 3.21.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.
@@ -22,8 +22,18 @@ interface MongooseAdapterOptions<TDoc = unknown> {
22
22
  */
23
23
  repository: AdapterRepositoryInput<TDoc>;
24
24
  /**
25
- * External schema generator plugin for OpenAPI / introspection docs.
26
- * When provided, the adapter delegates schema generation to it.
25
+ * Schema generator for OpenAPI / introspection docs.
26
+ *
27
+ * **Defaults to mongokit's own `buildCrudSchemasFromModel`** (3.21) — the
28
+ * canonical Mongoose→JSON-Schema generator ships in this package, so
29
+ * omitting the option now means "use it" rather than "no schemas". An
30
+ * audit of a 68-resource production host found 28 adapters that omitted
31
+ * it by accident and silently shipped `null` OpenAPI bodies + empty MCP
32
+ * tool schemas — correct-by-default closes that failure class.
33
+ *
34
+ * Pass `false` to opt OUT of schema generation entirely (`generateSchemas`
35
+ * returns `null`, hosts fall back to permissive bodies). Pass your own
36
+ * `SchemaGenerator` to replace the default.
27
37
  *
28
38
  * **Model type is intentionally `Model<unknown>`, not `Model<TDoc>`**:
29
39
  * schema generators introspect `.schema.paths` — they read metadata,
@@ -35,17 +45,14 @@ interface MongooseAdapterOptions<TDoc = unknown> {
35
45
  *
36
46
  * @example
37
47
  * ```ts
38
- * import { buildCrudSchemasFromModel, createMongooseAdapter } from '@classytic/mongokit';
39
- * import { createMongooseAdapter as fromAdapterSubpath } from '@classytic/mongokit/adapter';
48
+ * // Default — full OpenAPI/MCP schemas, zero config:
49
+ * createMongooseAdapter({ model: ProductModel, repository: productRepository });
40
50
  *
41
- * createMongooseAdapter({
42
- * model: ProductModel,
43
- * repository: productRepository,
44
- * schemaGenerator: buildCrudSchemasFromModel,
45
- * });
51
+ * // Explicit opt-out (permissive bodies, no generated schemas):
52
+ * createMongooseAdapter({ model, repository, schemaGenerator: false });
46
53
  * ```
47
54
  */
48
- schemaGenerator?: SchemaGenerator<Model<unknown>>;
55
+ schemaGenerator?: SchemaGenerator<Model<unknown>> | false;
49
56
  }
50
57
  /**
51
58
  * Mongoose data adapter — implements the `DataAdapter<TDoc>` contract from
@@ -1,2 +1,2 @@
1
- import { n as createMongooseAdapter, r as isMongooseModel, t as MongooseAdapter } from "../adapter-CW1EL0fF.mjs";
1
+ import { n as createMongooseAdapter, r as isMongooseModel, t as MongooseAdapter } from "../adapter-rTPLUrAV.mjs";
2
2
  export { MongooseAdapter, createMongooseAdapter, isMongooseModel };
@@ -1,4 +1,5 @@
1
1
  import { n as warn } from "./logger-K7dPmu2U.mjs";
2
+ import { t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-CVnrKFDq.mjs";
2
3
  import { mergeFieldRuleConstraints } from "@classytic/repo-core/schema";
3
4
  import { asRepositoryLike, isRepository } from "@classytic/repo-core/adapter";
4
5
  //#region src/adapter/types.ts
@@ -77,7 +78,7 @@ var MongooseAdapter = class {
77
78
  if (!isRepository(options.repository)) throw new TypeError(formatInvalidRepositoryError(options.repository, options.model));
78
79
  this.model = options.model;
79
80
  this.repository = asRepositoryLike(options.repository);
80
- this.schemaGenerator = options.schemaGenerator;
81
+ this.schemaGenerator = options.schemaGenerator === false ? void 0 : options.schemaGenerator ?? buildCrudSchemasFromModel;
81
82
  this.name = `MongooseAdapter<${options.model.modelName}>`;
82
83
  }
83
84
  /**
@@ -1,5 +1,5 @@
1
1
  import { n as Repository } from "../Repository-dbbgOGjK.mjs";
2
- import { n as createMongooseAdapter } from "../adapter-CW1EL0fF.mjs";
2
+ import { n as createMongooseAdapter } from "../adapter-rTPLUrAV.mjs";
3
3
  import { pluralizeBetterAuthCollection, resolveBetterAuthCollections } from "@classytic/repo-core/better-auth";
4
4
  //#region src/better-auth/index.ts
5
5
  /**
package/dist/index.mjs CHANGED
@@ -12,7 +12,8 @@ import { a as uniqueField, c as subdocumentPlugin, d as leasePlugin, f as fieldF
12
12
  import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-FSQFLpsU.mjs";
13
13
  import { buildFieldTypeMap, coerceFieldValue, coerceHeuristic } from "./query/primitives/coercion.mjs";
14
14
  import { extractSchemaIndexes } from "./query/primitives/indexes.mjs";
15
- import { n as buildCrudSchemasFromMongooseSchema, r as createMemoryCache, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-khdzVo8x.mjs";
15
+ import { t as createMemoryCache } from "./memory-cache-DI1jb4dz.mjs";
16
+ import { n as buildCrudSchemasFromMongooseSchema, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-CVnrKFDq.mjs";
16
17
  import { runChunkedPurge } from "@classytic/repo-core/repository";
17
18
  import { isControlParam } from "@classytic/repo-core/query-parser";
18
19
  //#region src/actions/cascade-references.ts
@@ -0,0 +1,67 @@
1
+ //#region src/utils/memory-cache.ts
2
+ /**
3
+ * Creates an in-memory cache adapter
4
+ *
5
+ * Features:
6
+ * - Automatic TTL expiration
7
+ * - Pattern-based clearing (simple glob with *)
8
+ * - Max entries limit to prevent memory leaks
9
+ *
10
+ * @param maxEntries - Maximum cache entries before oldest are evicted (default: 1000)
11
+ */
12
+ function createMemoryCache(maxEntries = 1e3) {
13
+ const cache = /* @__PURE__ */ new Map();
14
+ let lastCleanup = Date.now();
15
+ const CLEANUP_INTERVAL_MS = 6e4;
16
+ function cleanupIfNeeded() {
17
+ const now = Date.now();
18
+ if (now - lastCleanup < CLEANUP_INTERVAL_MS) return;
19
+ lastCleanup = now;
20
+ for (const [key, entry] of cache) if (entry.expiresAt < now) cache.delete(key);
21
+ }
22
+ function evictOldest() {
23
+ while (cache.size >= maxEntries) {
24
+ const firstKey = cache.keys().next().value;
25
+ if (firstKey) cache.delete(firstKey);
26
+ else break;
27
+ }
28
+ }
29
+ return {
30
+ async get(key) {
31
+ const entry = cache.get(key);
32
+ if (!entry) return null;
33
+ if (entry.expiresAt < Date.now()) {
34
+ cache.delete(key);
35
+ return null;
36
+ }
37
+ cache.delete(key);
38
+ cache.set(key, entry);
39
+ return entry.value;
40
+ },
41
+ async set(key, value, ttl) {
42
+ cache.delete(key);
43
+ if (cache.size >= maxEntries) {
44
+ cleanupIfNeeded();
45
+ evictOldest();
46
+ }
47
+ cache.set(key, {
48
+ value,
49
+ expiresAt: Date.now() + ttl * 1e3
50
+ });
51
+ },
52
+ async delete(key) {
53
+ cache.delete(key);
54
+ },
55
+ async clear(pattern) {
56
+ if (!pattern) {
57
+ cache.clear();
58
+ return;
59
+ }
60
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
61
+ const regex = new RegExp(`^${escaped}$`);
62
+ for (const key of cache.keys()) if (regex.test(key)) cache.delete(key);
63
+ }
64
+ };
65
+ }
66
+ //#endregion
67
+ export { createMemoryCache as t };
@@ -1,72 +1,6 @@
1
1
  import { r as isObjectIdInstance } from "./id-resolution-P2OzcyRl.mjs";
2
2
  import mongoose from "mongoose";
3
3
  import { applyFieldRules, collectFieldsToOmit } from "@classytic/repo-core/schema";
4
- //#region src/utils/memory-cache.ts
5
- /**
6
- * Creates an in-memory cache adapter
7
- *
8
- * Features:
9
- * - Automatic TTL expiration
10
- * - Pattern-based clearing (simple glob with *)
11
- * - Max entries limit to prevent memory leaks
12
- *
13
- * @param maxEntries - Maximum cache entries before oldest are evicted (default: 1000)
14
- */
15
- function createMemoryCache(maxEntries = 1e3) {
16
- const cache = /* @__PURE__ */ new Map();
17
- let lastCleanup = Date.now();
18
- const CLEANUP_INTERVAL_MS = 6e4;
19
- function cleanupIfNeeded() {
20
- const now = Date.now();
21
- if (now - lastCleanup < CLEANUP_INTERVAL_MS) return;
22
- lastCleanup = now;
23
- for (const [key, entry] of cache) if (entry.expiresAt < now) cache.delete(key);
24
- }
25
- function evictOldest() {
26
- while (cache.size >= maxEntries) {
27
- const firstKey = cache.keys().next().value;
28
- if (firstKey) cache.delete(firstKey);
29
- else break;
30
- }
31
- }
32
- return {
33
- async get(key) {
34
- const entry = cache.get(key);
35
- if (!entry) return null;
36
- if (entry.expiresAt < Date.now()) {
37
- cache.delete(key);
38
- return null;
39
- }
40
- cache.delete(key);
41
- cache.set(key, entry);
42
- return entry.value;
43
- },
44
- async set(key, value, ttl) {
45
- cache.delete(key);
46
- if (cache.size >= maxEntries) {
47
- cleanupIfNeeded();
48
- evictOldest();
49
- }
50
- cache.set(key, {
51
- value,
52
- expiresAt: Date.now() + ttl * 1e3
53
- });
54
- },
55
- async delete(key) {
56
- cache.delete(key);
57
- },
58
- async clear(pattern) {
59
- if (!pattern) {
60
- cache.clear();
61
- return;
62
- }
63
- const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
64
- const regex = new RegExp(`^${escaped}$`);
65
- for (const key of cache.keys()) if (regex.test(key)) cache.delete(key);
66
- }
67
- };
68
- }
69
- //#endregion
70
4
  //#region src/utils/mongooseToJsonSchema.ts
71
5
  /**
72
6
  * Mongoose → JSON Schema converter.
@@ -624,4 +558,4 @@ function buildJsonSchemaForQuery(_tree, options) {
624
558
  return basePagination;
625
559
  }
626
560
  //#endregion
627
- export { buildCrudSchemasFromMongooseSchema as n, createMemoryCache as r, buildCrudSchemasFromModel as t };
561
+ export { buildCrudSchemasFromMongooseSchema as n, buildCrudSchemasFromModel as t };
@@ -2,5 +2,6 @@ import { i as isValidIdForType, r as isObjectIdInstance, t as getSchemaIdType }
2
2
  import { t as configureLogger } from "../logger-K7dPmu2U.mjs";
3
3
  import { t as createError } from "../error-BuByZwKU.mjs";
4
4
  import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "../field-selection-FSQFLpsU.mjs";
5
- import { n as buildCrudSchemasFromMongooseSchema, r as createMemoryCache, t as buildCrudSchemasFromModel } from "../mongooseToJsonSchema-khdzVo8x.mjs";
5
+ import { t as createMemoryCache } from "../memory-cache-DI1jb4dz.mjs";
6
+ import { n as buildCrudSchemasFromMongooseSchema, t as buildCrudSchemasFromModel } from "../mongooseToJsonSchema-CVnrKFDq.mjs";
6
7
  export { buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, configureLogger, createError, createFieldPreset, createMemoryCache, filterResponseData, getFieldsForUser, getMongooseProjection, getSchemaIdType, isObjectIdInstance, isValidIdForType };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/mongokit",
3
- "version": "3.20.0",
3
+ "version": "3.21.0",
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,