@classytic/mongokit 3.34.0 → 3.36.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/adapter/index.d.mts +30 -14
- package/dist/adapter/index.mjs +1 -1
- package/dist/{adapter-BitHg-CN.mjs → adapter-Bfqz8yHE.mjs} +43 -1
- package/dist/better-auth/index.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{mongooseToJsonSchema-DKbnKduN.mjs → mongooseToJsonSchema-waUVQwK4.mjs} +29 -1
- package/dist/utils/index.mjs +1 -1
- package/package.json +3 -3
package/dist/adapter/index.d.mts
CHANGED
|
@@ -3,15 +3,25 @@ import { Document, Model } from "mongoose";
|
|
|
3
3
|
import { SchemaBuilderOptions, SchemaGenerator } from "@classytic/repo-core/schema";
|
|
4
4
|
import { AdapterRepositoryInput, AdapterSchemaContext, AdapterValidationResult, DataAdapter, OpenApiSchemas, RepositoryLike, SchemaMetadata } from "@classytic/repo-core/adapter";
|
|
5
5
|
//#region src/adapter/mongoose-adapter.d.ts
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
interface MongooseAdapterOptions<TDoc = unknown, TModelDoc = unknown> {
|
|
7
|
+
/**
|
|
8
|
+
* The Mongoose model. Still a real `Model`, so a Schema or a hand-built
|
|
9
|
+
* object literal is a COMPILE error — but its document type is INDEPENDENT of
|
|
10
|
+
* `TDoc`.
|
|
11
|
+
*
|
|
12
|
+
* `Model<T>` is invariant in `T`, so `Model<TDoc>` here forced every caller
|
|
13
|
+
* whose repository speaks a lean entity (string ids) while its schema-inferred
|
|
14
|
+
* model carries hydrated documents to cast: the two describe one collection
|
|
15
|
+
* and can never unify. The adapter reads the model for `modelName` and
|
|
16
|
+
* `.schema.paths` metadata only, never for document typing.
|
|
17
|
+
*
|
|
18
|
+
* Decoupling the two parameters removes a static check, so the constructor
|
|
19
|
+
* restores it at RUNTIME by comparing this model against the one the
|
|
20
|
+
* repository owns — see `assertModelMatchesRepository`. That check is
|
|
21
|
+
* strictly stronger: it also rejects two DIFFERENT collections that happen to
|
|
22
|
+
* share a document shape, which no type could distinguish.
|
|
23
|
+
*/
|
|
24
|
+
model: Model<TModelDoc>;
|
|
15
25
|
/**
|
|
16
26
|
* Repository implementing CRUD operations.
|
|
17
27
|
*
|
|
@@ -58,13 +68,19 @@ interface MongooseAdapterOptions<TDoc = unknown> {
|
|
|
58
68
|
* Mongoose data adapter — implements the `DataAdapter<TDoc>` contract from
|
|
59
69
|
* `@classytic/repo-core/adapter`.
|
|
60
70
|
*/
|
|
61
|
-
declare class MongooseAdapter<TDoc = unknown> implements DataAdapter<TDoc> {
|
|
71
|
+
declare class MongooseAdapter<TDoc = unknown, TModelDoc = unknown> implements DataAdapter<TDoc> {
|
|
62
72
|
readonly type: "mongoose";
|
|
63
73
|
readonly name: string;
|
|
64
|
-
|
|
74
|
+
/**
|
|
75
|
+
* The model as given. Its document type is NOT `TDoc` — a lean repository
|
|
76
|
+
* legitimately pairs with a hydrated schema-inferred model, so claiming
|
|
77
|
+
* `Model<TDoc>` here was an assertion the code could not honour. Read it for
|
|
78
|
+
* `modelName` and `.schema`; narrow it yourself if you need document typing.
|
|
79
|
+
*/
|
|
80
|
+
readonly model: Model<unknown>;
|
|
65
81
|
readonly repository: RepositoryLike<TDoc>;
|
|
66
82
|
private readonly schemaGenerator?;
|
|
67
|
-
constructor(options: MongooseAdapterOptions<TDoc>);
|
|
83
|
+
constructor(options: MongooseAdapterOptions<TDoc, TModelDoc>);
|
|
68
84
|
/**
|
|
69
85
|
* Lightweight path-existence check for hosts that infer absent fields
|
|
70
86
|
* (e.g. arc's `defineResource()` infers `tenantField: false` when the
|
|
@@ -159,8 +175,8 @@ declare class MongooseAdapter<TDoc = unknown> implements DataAdapter<TDoc> {
|
|
|
159
175
|
* const adapter = createMongooseAdapter(ProductModel, productRepository);
|
|
160
176
|
* ```
|
|
161
177
|
*/
|
|
162
|
-
declare function createMongooseAdapter<TDoc = unknown>(model: Model<
|
|
163
|
-
declare function createMongooseAdapter<TDoc = unknown>(options: MongooseAdapterOptions<TDoc>): DataAdapter<TDoc>;
|
|
178
|
+
declare function createMongooseAdapter<TDoc = unknown, TModelDoc = unknown>(model: Model<TModelDoc>, repository: AdapterRepositoryInput<TDoc>): DataAdapter<TDoc>;
|
|
179
|
+
declare function createMongooseAdapter<TDoc = unknown, TModelDoc = unknown>(options: MongooseAdapterOptions<TDoc, TModelDoc>): DataAdapter<TDoc>;
|
|
164
180
|
//#endregion
|
|
165
181
|
//#region src/adapter/types.d.ts
|
|
166
182
|
/**
|
package/dist/adapter/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as createMongooseAdapter, r as isMongooseModel, t as MongooseAdapter } from "../adapter-
|
|
1
|
+
import { n as createMongooseAdapter, r as isMongooseModel, t as MongooseAdapter } from "../adapter-Bfqz8yHE.mjs";
|
|
2
2
|
export { MongooseAdapter, createMongooseAdapter, isMongooseModel };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as warn } from "./logger-K7dPmu2U.mjs";
|
|
2
|
-
import { t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-
|
|
2
|
+
import { t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-waUVQwK4.mjs";
|
|
3
3
|
import { matchesRecordFilter } from "@classytic/repo-core/filter";
|
|
4
4
|
import { mergeFieldRuleConstraints } from "@classytic/repo-core/schema";
|
|
5
5
|
import { asRepositoryLike, isRepository } from "@classytic/repo-core/adapter";
|
|
@@ -65,18 +65,60 @@ function formatInvalidRepositoryError(repository, model) {
|
|
|
65
65
|
].join("\n");
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
|
+
* Options for creating a Mongoose adapter.
|
|
69
|
+
*
|
|
70
|
+
* `TDoc` is auto-inferred from the Mongoose model — no explicit type
|
|
71
|
+
* needed in most call sites.
|
|
72
|
+
*/
|
|
73
|
+
/**
|
|
74
|
+
* The model and the repository must name the SAME collection.
|
|
75
|
+
*
|
|
76
|
+
* Decoupling their document types (so a lean repository pairs with a hydrated
|
|
77
|
+
* schema-inferred model) removes the static cross-check that `Model<TDoc>` +
|
|
78
|
+
* `AdapterRepositoryInput<TDoc>` gave. This restores it where it can actually be
|
|
79
|
+
* decided — at construction, against `Repository.Model`, which every kit-native
|
|
80
|
+
* repository carries. It is strictly stronger than the type was: two different
|
|
81
|
+
* collections sharing a document shape were always statically indistinguishable.
|
|
82
|
+
*
|
|
83
|
+
* Silent when the repository does not expose a model (a BYO/mock repository) —
|
|
84
|
+
* absence of an answer is not a negative answer, and refusing there would break
|
|
85
|
+
* every legitimate custom repository.
|
|
86
|
+
*/
|
|
87
|
+
function assertModelMatchesRepository(model, repository) {
|
|
88
|
+
const repoModel = repository?.Model;
|
|
89
|
+
const repoModelName = typeof repoModel?.modelName === "string" ? repoModel.modelName : void 0;
|
|
90
|
+
if (repoModelName === void 0 || repoModelName === model.modelName) return;
|
|
91
|
+
throw new TypeError([
|
|
92
|
+
`MongooseAdapter: model/repository mismatch — model is '${model.modelName}' but the repository is bound to '${repoModelName}'.`,
|
|
93
|
+
"",
|
|
94
|
+
"The adapter reads schema metadata from the MODEL (arc infers a missing",
|
|
95
|
+
"`tenantField` from it) and reads/writes through the REPOSITORY. Mismatched,",
|
|
96
|
+
"the tenant probe answers about the wrong collection and queries are either",
|
|
97
|
+
"filtered to zero rows or left unscoped — neither of which errors.",
|
|
98
|
+
"",
|
|
99
|
+
"Fix: pass the model that repository was constructed with."
|
|
100
|
+
].join("\n"));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
68
103
|
* Mongoose data adapter — implements the `DataAdapter<TDoc>` contract from
|
|
69
104
|
* `@classytic/repo-core/adapter`.
|
|
70
105
|
*/
|
|
71
106
|
var MongooseAdapter = class {
|
|
72
107
|
type = "mongoose";
|
|
73
108
|
name;
|
|
109
|
+
/**
|
|
110
|
+
* The model as given. Its document type is NOT `TDoc` — a lean repository
|
|
111
|
+
* legitimately pairs with a hydrated schema-inferred model, so claiming
|
|
112
|
+
* `Model<TDoc>` here was an assertion the code could not honour. Read it for
|
|
113
|
+
* `modelName` and `.schema`; narrow it yourself if you need document typing.
|
|
114
|
+
*/
|
|
74
115
|
model;
|
|
75
116
|
repository;
|
|
76
117
|
schemaGenerator;
|
|
77
118
|
constructor(options) {
|
|
78
119
|
if (!isMongooseModel(options.model)) throw new TypeError(formatInvalidModelError(options.model));
|
|
79
120
|
if (!isRepository(options.repository)) throw new TypeError(formatInvalidRepositoryError(options.repository, options.model));
|
|
121
|
+
assertModelMatchesRepository(options.model, options.repository);
|
|
80
122
|
this.model = options.model;
|
|
81
123
|
this.repository = asRepositoryLike(options.repository);
|
|
82
124
|
this.schemaGenerator = options.schemaGenerator === false ? void 0 : options.schemaGenerator ?? buildCrudSchemasFromModel;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as Repository } from "../Repository-BArvU32x.mjs";
|
|
2
|
-
import { n as createMongooseAdapter } from "../adapter-
|
|
2
|
+
import { n as createMongooseAdapter } from "../adapter-Bfqz8yHE.mjs";
|
|
3
3
|
import { asReadOnlyRepo } from "@classytic/repo-core/repository";
|
|
4
4
|
import { pluralizeBetterAuthCollection, resolveBetterAuthCollections } from "@classytic/repo-core/better-auth";
|
|
5
5
|
//#region src/better-auth/index.ts
|
package/dist/index.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForU
|
|
|
15
15
|
import { buildFieldTypeMap, coerceFieldValue, coerceHeuristic } from "./query/primitives/coercion.mjs";
|
|
16
16
|
import { extractSchemaIndexes } from "./query/primitives/indexes.mjs";
|
|
17
17
|
import { n as createMemoryCache, t as toPlain } from "./to-plain-vksRrLtc.mjs";
|
|
18
|
-
import { n as buildCrudSchemasFromMongooseSchema, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-
|
|
18
|
+
import { n as buildCrudSchemasFromMongooseSchema, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-waUVQwK4.mjs";
|
|
19
19
|
import { runChunkedPurge } from "@classytic/repo-core/repository";
|
|
20
20
|
import { isControlParam } from "@classytic/repo-core/query-parser";
|
|
21
21
|
//#region src/actions/cascade-references.ts
|
|
@@ -474,9 +474,37 @@ function stripDefaultsDeep(node) {
|
|
|
474
474
|
delete obj.default;
|
|
475
475
|
for (const value of Object.values(obj)) stripDefaultsDeep(value);
|
|
476
476
|
}
|
|
477
|
+
/**
|
|
478
|
+
* Recursively delete every `required` keyword from a JSON-schema subtree
|
|
479
|
+
* (properties, array items, nested subdocuments).
|
|
480
|
+
*
|
|
481
|
+
* PATCH semantics mean every field is optional at EVERY nesting depth, not
|
|
482
|
+
* just the root — a caller may send a partial subdocument-array item (e.g.
|
|
483
|
+
* `variants: [{ sku, isActive }]` to toggle a flag) without re-supplying
|
|
484
|
+
* every field the CREATE schema requires for that item. The one-line
|
|
485
|
+
* `delete clone.required` below only stripped the top-level key; a
|
|
486
|
+
* DocumentArray's `items` schema carries its OWN `required` (built by
|
|
487
|
+
* `subSchemaToJsonSchema`), which survived untouched — so a partial nested
|
|
488
|
+
* item still failed AJV's `required` check before the request ever reached
|
|
489
|
+
* the repository (real defect: PATCHing a product to add ONE variant with
|
|
490
|
+
* no `variationAttributes` 400'd on `variants/0` missing `attributes`, even
|
|
491
|
+
* though `attributes: {}` is a valid, already-persisted value). Same fix
|
|
492
|
+
* shape as `stripDefaultsDeep` above, for the identical reason: an UPDATE
|
|
493
|
+
* schema's partial-field semantics belong to the whole tree, not its root.
|
|
494
|
+
*/
|
|
495
|
+
function stripRequiredDeep(node) {
|
|
496
|
+
if (Array.isArray(node)) {
|
|
497
|
+
for (const item of node) stripRequiredDeep(item);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
if (!node || typeof node !== "object") return;
|
|
501
|
+
const obj = node;
|
|
502
|
+
delete obj.required;
|
|
503
|
+
for (const value of Object.values(obj)) stripRequiredDeep(value);
|
|
504
|
+
}
|
|
477
505
|
function buildJsonSchemaForUpdate(createJson, options) {
|
|
478
506
|
const clone = JSON.parse(JSON.stringify(createJson));
|
|
479
|
-
|
|
507
|
+
stripRequiredDeep(clone);
|
|
480
508
|
const fieldsToOmit = collectFieldsToOmit(options, "update");
|
|
481
509
|
applyFieldRules(clone, fieldsToOmit, options);
|
|
482
510
|
stripDefaultsDeep(clone);
|
package/dist/utils/index.mjs
CHANGED
|
@@ -4,5 +4,5 @@ import { t as configureLogger } from "../logger-K7dPmu2U.mjs";
|
|
|
4
4
|
import { t as createError } from "../error-BuByZwKU.mjs";
|
|
5
5
|
import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "../field-selection-FSQFLpsU.mjs";
|
|
6
6
|
import { n as createMemoryCache, t as toPlain } from "../to-plain-vksRrLtc.mjs";
|
|
7
|
-
import { n as buildCrudSchemasFromMongooseSchema, t as buildCrudSchemasFromModel } from "../mongooseToJsonSchema-
|
|
7
|
+
import { n as buildCrudSchemasFromMongooseSchema, t as buildCrudSchemasFromModel } from "../mongooseToJsonSchema-waUVQwK4.mjs";
|
|
8
8
|
export { DEFAULT_ID_CHUNK, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, collectIds, configureLogger, createError, createFieldPreset, createMemoryCache, filterResponseData, getFieldsForUser, getMongooseProjection, getSchemaIdType, idChunks, isObjectIdInstance, isValidIdForType, keysetFilter, narrowToIds, selectKeysetChunk, toObjectId, toPlain };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@classytic/mongokit",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.36.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,
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
},
|
|
123
123
|
"homepage": "https://github.com/classytic/mongokit#readme",
|
|
124
124
|
"peerDependencies": {
|
|
125
|
-
"@classytic/repo-core": ">=0.
|
|
125
|
+
"@classytic/repo-core": ">=0.25.0",
|
|
126
126
|
"mongodb-memory-server": ">=10.4.3",
|
|
127
127
|
"mongoose": ">=9.4.1"
|
|
128
128
|
},
|
|
@@ -174,7 +174,7 @@
|
|
|
174
174
|
"@better-auth/mongo-adapter": "^1.6.29",
|
|
175
175
|
"@biomejs/biome": "^2.5.8",
|
|
176
176
|
"@classytic/dev-tools": "^0.2.0",
|
|
177
|
-
"@classytic/repo-core": "^0.
|
|
177
|
+
"@classytic/repo-core": "^0.25.0",
|
|
178
178
|
"@types/node": "^26.2.0",
|
|
179
179
|
"@vitest/coverage-v8": "^4.1.10",
|
|
180
180
|
"ajv": "^8.20.0",
|