@web-ts-toolkit/moo 0.43.0 → 0.47.1
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 +122 -7
- package/index.d.mts +2 -2
- package/index.d.ts +2 -2
- package/index.js +386 -57
- package/index.mjs +386 -57
- package/is.d.mts +2 -2
- package/is.d.ts +2 -2
- package/is.js +8 -7
- package/is.mjs +8 -7
- package/llms.txt +33 -5
- package/package.json +3 -3
- package/plugins/cascade-delete.d.mts +151 -4
- package/plugins/cascade-delete.d.ts +151 -4
- package/plugins/cascade-delete.js +354 -33
- package/plugins/cascade-delete.mjs +354 -33
- package/plugins/index.d.mts +1 -1
- package/plugins/index.d.ts +1 -1
- package/plugins/index.js +354 -33
- package/plugins/index.mjs +354 -33
- package/plugins/keycloak-user-sync.d.mts +32 -4
- package/plugins/keycloak-user-sync.d.ts +32 -4
- package/plugins/keycloak-user-sync.js +207 -45
- package/plugins/keycloak-user-sync.mjs +207 -45
- package/plugins/model-function.d.mts +46 -0
- package/plugins/model-function.d.ts +46 -0
- package/plugins/new-document.d.mts +21 -2
- package/plugins/new-document.d.ts +21 -2
- package/schema.d.mts +34 -5
- package/schema.d.ts +34 -5
- package/schema.js +24 -17
- package/schema.mjs +24 -17
package/README.md
CHANGED
|
@@ -10,8 +10,8 @@ pnpm add mongoose @web-ts-toolkit/moo
|
|
|
10
10
|
|
|
11
11
|
Peer dependencies:
|
|
12
12
|
|
|
13
|
-
- `mongoose >= 8`
|
|
14
|
-
- `@egose/keycloak-fluent
|
|
13
|
+
- `mongoose >= 8` (tested with Mongoose 8.24.x and 9.x)
|
|
14
|
+
- `@egose/keycloak-fluent >=0.12.1 <0.15.0` only when using `@web-ts-toolkit/moo/plugins/keycloak-user-sync` (tested floor `0.12.1`, current `0.14.x`)
|
|
15
15
|
|
|
16
16
|
## Highlights
|
|
17
17
|
|
|
@@ -46,7 +46,7 @@ Subpath entrypoints:
|
|
|
46
46
|
|
|
47
47
|
- `@web-ts-toolkit/moo/schema` — schema field helpers
|
|
48
48
|
- `@web-ts-toolkit/moo/is` — type guards such as `isObjectId(...)`
|
|
49
|
-
- `@web-ts-toolkit/moo/utils` —
|
|
49
|
+
- `@web-ts-toolkit/moo/utils` — `isSchema`, `isObjectIdType`, `isReference`, and the `ReferenceShape` type
|
|
50
50
|
- `@web-ts-toolkit/moo/plugins` — plugin entrypoint
|
|
51
51
|
- `@web-ts-toolkit/moo/plugins/cascade-delete` — cascade-delete plugin
|
|
52
52
|
- `@web-ts-toolkit/moo/plugins/model-function` — model-function plugin
|
|
@@ -73,6 +73,79 @@ userSchema.plugin(cascadeDeletePlugin, {
|
|
|
73
73
|
});
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
## Model Function Plugin
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import mongoose, { type Model } from 'mongoose';
|
|
80
|
+
import {
|
|
81
|
+
type ModelDocument,
|
|
82
|
+
type ModelFunctionInstanceMethods,
|
|
83
|
+
type ModelFunctionStaticMethods,
|
|
84
|
+
modelFunctionPlugin,
|
|
85
|
+
} from '@web-ts-toolkit/moo';
|
|
86
|
+
|
|
87
|
+
type Cart = {
|
|
88
|
+
name: string;
|
|
89
|
+
price: number;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Keep result types free of the CartDocument alias (plain values, not the
|
|
93
|
+
// document) so the aliases never circularly reference each other.
|
|
94
|
+
type CartMethods = ModelFunctionInstanceMethods<'applyDiscount', [suffix: string, priceChange: number], number> &
|
|
95
|
+
ModelFunctionInstanceMethods<'applyDiscountAsync', [suffix: string, priceChange: number], Promise<number>>;
|
|
96
|
+
|
|
97
|
+
type CartDocument = ModelDocument<Cart, CartMethods>;
|
|
98
|
+
|
|
99
|
+
type CartModel = Model<Cart, Record<string, never>, CartMethods> &
|
|
100
|
+
ModelFunctionStaticMethods<'applyDiscount', CartDocument, [suffix: string, priceChange: number], number> &
|
|
101
|
+
ModelFunctionStaticMethods<
|
|
102
|
+
'applyDiscountAsync',
|
|
103
|
+
CartDocument,
|
|
104
|
+
[suffix: string, priceChange: number],
|
|
105
|
+
Promise<number>
|
|
106
|
+
>;
|
|
107
|
+
|
|
108
|
+
const cartSchema = new mongoose.Schema<Cart, CartModel, CartMethods>({
|
|
109
|
+
name: { type: String, required: true },
|
|
110
|
+
price: { type: Number, required: true },
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// No explicit plugin generics: the method name, argument tuple, and result
|
|
114
|
+
// are inferred from the options. The second type argument is the method
|
|
115
|
+
// *name* (for example `'applyDiscount'`), never the methods object.
|
|
116
|
+
cartSchema.plugin(modelFunctionPlugin, {
|
|
117
|
+
fnName: 'applyDiscount',
|
|
118
|
+
fn: (cart: CartDocument, suffix: string, priceChange: number) => {
|
|
119
|
+
cart.price += priceChange;
|
|
120
|
+
return cart.price;
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
cartSchema.plugin(modelFunctionPlugin, {
|
|
125
|
+
fnName: 'applyDiscountAsync',
|
|
126
|
+
fn: async (cart: CartDocument, suffix: string, priceChange: number) => {
|
|
127
|
+
cart.price += priceChange;
|
|
128
|
+
return cart.price;
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const Cart = mongoose.model<Cart, CartModel>('Cart', cartSchema);
|
|
133
|
+
|
|
134
|
+
const cart = await Cart.create({ name: 'laptop', price: 2000 });
|
|
135
|
+
const syncPrice: number = Cart.applyDiscount(cart, 'premium', 100);
|
|
136
|
+
const instancePrice: number = cart.applyDiscount('premium', 100);
|
|
137
|
+
const byId: number | null = await Cart.applyDiscountById(cart._id.toString(), 'premium', 100);
|
|
138
|
+
const asyncById: number | null = await Cart.applyDiscountAsyncById(cart._id, 'premium', 100);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Each registration adds three typed surfaces: an instance method, a static taking the document first, and a `ById` static that loads the document and returns `null` when it is missing. Wrong argument types fail compilation.
|
|
142
|
+
|
|
143
|
+
## Schema Helpers
|
|
144
|
+
|
|
145
|
+
`uniqueNullableString(field, overrides?)` returns a partial-unique field definition that allows any number of `null`/missing values while rejecting duplicate strings (including `''`): the partial index only covers string-typed values (`{ [field]: { $type: 'string' } }`). `uniqueEmptiableString(field, overrides?)` additionally ignores empty strings (both `null` and `''` repeat; only duplicate non-empty strings conflict) via `{ [field]: { $type: 'string', $gt: '' } }`. Extra `overrides` are spread over the defaults at runtime and reflected in the inferred return type, so overriding `default`, `trim`, or `index` replaces the fixed default type instead of keeping it.
|
|
146
|
+
|
|
147
|
+
`isObjectId(value)` is a strict canonical guard: only 24-character lowercase hex strings and `mongoose.Types.ObjectId` instances from this package's `mongoose` copy pass. Uppercase hex, 12-byte strings, structural impostors with matching `toString()`, foreign BSON copies, buffers, and throwing accessors are rejected without invoking arbitrary coercion.
|
|
148
|
+
|
|
76
149
|
## New Document Plugin
|
|
77
150
|
|
|
78
151
|
```ts
|
|
@@ -92,6 +165,20 @@ userSchema.plugin(newDocumentPlugin, {
|
|
|
92
165
|
|
|
93
166
|
The plugin runs `fn` after the first successful `save()` of a new document. Later saves of the same document do not run it.
|
|
94
167
|
|
|
168
|
+
Supported operations: only document `save()` is observed (a `pre('save')` snapshot of `isNew` plus a `post('save')` invocation). Query inserts, `insertMany()` fast paths that skip document middleware, and updates to existing documents never trigger the callback.
|
|
169
|
+
|
|
170
|
+
Delivery scope: post-save notification, not durable delivery. The callback runs after MongoDB persistence; a throwing callback rejects the post-save hook but cannot roll back the committed write, and there is no outbox, retry, or exactly-once guarantee across transaction retries or reentrant saves. Applications that need transactional delivery should record their own outbox intent inside the MongoDB transaction and process it after commit.
|
|
171
|
+
|
|
172
|
+
## Cascade Delete Plugin
|
|
173
|
+
|
|
174
|
+
Relationship mode (`localField` + `foreignField`) is fail-closed: missing/`null`/empty-string local keys and empty reference arrays resolve to zero dependents and delete nothing, so unrelated records with a missing/`null` foreign key survive. A local field omitted by a projection is distinguished from an intentionally empty relation — when the path is provably deselected the lookup throws instead of silently reporting zero dependents. Supplemental `extraForeignFilter` constraints are composed conjunctively (`{ $and: [relationship, extra] }`), so an extra filter on the relationship field (including `$or`/`$and` payloads) can only narrow, never replace or widen, the deletion set. Explicit full-filter mode (`foreignFilter`) is a separate contract: the resolved filter is used as-is and any `extraForeignFilter` is ignored; resolvers returning `null`/`undefined`/non-objects resolve to zero dependents. Empty full filters (`{}`) are rejected by default at registration and at runtime because they would match the whole dependent collection; there is currently no broad-delete opt-in. Invalid `model`/field combinations and non-object static filters throw at `schema.plugin(...)` time.
|
|
175
|
+
|
|
176
|
+
Deletion always removes fully hydrated dependent documents through their own document `deleteOne()` (never bulk writes), so nested cascades and custom document hooks observe required fields across multi-level custom-`localField` chains. Internal deletion traversal pages dependent `_id`s (`batchSize`, default `100`) and bounds in-flight deletes (`maxConcurrency`, default `8`; forced to `1` inside an active transaction), instead of materializing and deleting the whole set at once. Public `findDependents()` still returns an array. A dependent-hook failure rejects the parent `deleteOne()` after the parent is already removed (fail-fast, remaining batches skipped; abort the transaction to restore everything when in one); already-deleted rows are skipped. Repeated references delete once per level; diamonds/cycles terminate with at-least-once hook delivery.
|
|
177
|
+
|
|
178
|
+
Supported operations and timing: only document `deleteOne()` is intercepted (`pre`/`post('deleteOne', { document: true, query: false })`). Query deletes (`deleteMany()`, `findOneAndDelete()`, query `deleteOne()`) and query updates bypass the cascade. The `pre('deleteOne')` hook validates the execution context before the parent is removed (cross-client sessions and transactions on standalone topologies reject there); the `post('deleteOne')` hook runs after the parent is already removed, so a later dependent failure rejects the parent promise without restoring the parent outside a transaction. Dependent models resolve through the owning model's connection and the effective session (explicit `deleteOne({ session })` option, else the document-bound `$session()`) flows through dependent reads and deletes including nested cascades. `maxConcurrency` and `batchSize` must be integers `>= 1` when provided and are validated at `schema.plugin(...)` time.
|
|
179
|
+
|
|
180
|
+
Typed filters accept MongoDB operators per field (`{ price: { $gt: 5 } }`, `{ price: { $in: [...] } }`, plus `$and`/`$or` payloads through the index signature) and are forwarded to Mongoose unchanged. The no-argument `findDependents()`/`findOrphans()` overloads return `Partial` maps: entries whose lookup is unsupported or resolved to nullish are omitted rather than reported as empty arrays. `findOrphans()` support: scalar `_id` relations and `[{ type: ObjectId, ref }]` arrays are supported; non-`_id` local keys with a hardcoded `distinct('_id')`, dotted foreign paths, `{ type: [ObjectId], ref }` syntax, dynamic `refPath`, and `foreignFilter`-only relationships are unsupported and resolve to `null` (omitted from the map) rather than silently succeeding. Null/missing foreign rows are reported as orphans; per-page `$not/$in` batching is not a correct collection-scale anti-join, so a server-side `$lookup` strategy is deferred to a follow-up.
|
|
181
|
+
|
|
95
182
|
## Keycloak User Sync
|
|
96
183
|
|
|
97
184
|
Install the optional Keycloak peer before using this entrypoint:
|
|
@@ -120,9 +207,26 @@ const userSchema = new Schema({
|
|
|
120
207
|
lastName: String,
|
|
121
208
|
archived: Boolean,
|
|
122
209
|
roles: [String],
|
|
123
|
-
|
|
210
|
+
tier: String,
|
|
211
|
+
tenantId: String,
|
|
212
|
+
subscription: { plan: String },
|
|
213
|
+
// No stored pendingPassword path: the pending credential below is a
|
|
214
|
+
// virtual and is never persisted to MongoDB.
|
|
124
215
|
});
|
|
125
216
|
|
|
217
|
+
// Genuinely non-persisted pending-password input. Virtuals are not stored in
|
|
218
|
+
// MongoDB; the value lives only in memory until the Keycloak reset-password
|
|
219
|
+
// call. Never add a persisted `pendingPassword` schema path holding
|
|
220
|
+
// plaintext, and clear the virtual after sync.
|
|
221
|
+
userSchema
|
|
222
|
+
.virtual('pendingPassword') // pragma: allowlist secret
|
|
223
|
+
.get(function (this: { $locals: Record<string, unknown> }) {
|
|
224
|
+
return this.$locals.pendingPassword as string | undefined;
|
|
225
|
+
})
|
|
226
|
+
.set(function (this: { $locals: Record<string, unknown> }, value: string | undefined) {
|
|
227
|
+
this.$locals.pendingPassword = value;
|
|
228
|
+
});
|
|
229
|
+
|
|
126
230
|
userSchema.plugin(keycloakUserSyncPlugin, {
|
|
127
231
|
client: keycloak,
|
|
128
232
|
realm: 'application',
|
|
@@ -144,7 +248,14 @@ userSchema.plugin(keycloakUserSyncPlugin, {
|
|
|
144
248
|
mapPassword(document) {
|
|
145
249
|
return document.get('pendingPassword') as string | undefined;
|
|
146
250
|
},
|
|
251
|
+
// Declared mapper dependencies: the mapped schema paths above must exist.
|
|
252
|
+
// passwordPaths covers the non-persisted virtual backing input.
|
|
147
253
|
attributePaths: ['tenantId', 'subscription.plan'],
|
|
254
|
+
rolePaths: ['tier'],
|
|
255
|
+
passwordPaths: ['pendingPassword'],
|
|
256
|
+
mapRoles(_roles, document) {
|
|
257
|
+
return document.get('tier') === 'pro' ? ['editor'] : [];
|
|
258
|
+
},
|
|
148
259
|
mapAttributes(document) {
|
|
149
260
|
return {
|
|
150
261
|
tenantId: document.get('tenantId'),
|
|
@@ -170,10 +281,12 @@ The plugin:
|
|
|
170
281
|
- can update the Keycloak password when `syncFields.password` is explicitly enabled
|
|
171
282
|
- reads `archived` as the inverse of Keycloak `enabled`, falling back to an `enabled` field
|
|
172
283
|
|
|
173
|
-
Configuration is validated when `schema.plugin(...)` runs. `realm`, configured paths, managed role/attribute names, and attribute trigger paths are trimmed and must be non-empty. `identifyBy` accepts one identity or a non-empty ordered list containing only `providerId`, `username`, and `email`. Built-in synced field paths must exist in the Mongoose schema; mapper-driven `attributePaths`
|
|
284
|
+
Configuration is validated when `schema.plugin(...)` runs. `realm`, configured paths, managed role/attribute names, and attribute/role/password trigger paths are trimmed and must be non-empty. `identifyBy` accepts one identity or a non-empty ordered list containing only `providerId`, `username`, and `email`. Built-in synced field paths must exist in the Mongoose schema; mapper-driven `attributePaths`/`rolePaths`/`passwordPaths` name the additional Mongoose paths the mapper reads (as in the example above, where `tenantId`, `subscription.plan`, `tier`, and the `pendingPassword` virtual are all declared). Register the plugin only once per schema.
|
|
174
285
|
|
|
175
286
|
The plugin snapshots its options at registration, so later mutation of the caller's options object does not change sync behavior. `providerId` is server-controlled after persistence: applications may set it while creating a new document to link an existing Keycloak user, but changing it later is rejected before any remote call so ordinary document updates cannot redirect synchronization to another Keycloak account.
|
|
176
287
|
|
|
288
|
+
Saves and deletes share one persisted-identity boundary. New local documents perform explicitly authorized initial linking through their current identity values. Existing documents resolve only through their persisted snapshot: a stored `providerId` is authoritative, and a changed username or email that resolves to a different remote user fails closed instead of relinking — the conflicting update, credential reset, role change, or delete is never sent to that other account. A stale persisted `providerId`, a missing persisted local row, or a delete of a never-persisted document is likewise rejected before any destructive remote call. These identity rejections apply independently of `throwOnError`: with `throwOnError: false` a conflicting save still succeeds locally while leaving the other account untouched, and a conflicting delete always blocks local deletion so the verified binding remains retryable. Migration implication: after adopting this contract, rows whose stored `providerId` no longer exists remotely fail closed on sync; clear or re-link the stored binding explicitly rather than changing a profile field and expecting a silent relink.
|
|
289
|
+
|
|
177
290
|
When the realm allows duplicate emails, the plugin always prioritizes configured `providerId` and `username` identities before email. An email lookup proceeds only when it has exactly one match; multiple matches are reported as an error, and no user is changed or deleted.
|
|
178
291
|
|
|
179
292
|
Use `paths` to map different Mongoose path names. Use `syncFields` to disable profile fields, role syncing, or attribute syncing. Use `mapRoles` to translate application roles. Role sync is additive-only by default: desired local roles are assigned, but unrelated existing Keycloak realm roles are preserved. Set `managedRoles` to the exact role names this plugin owns; only those roles may be removed when omitted from an explicit local roles array. An absent or non-array roles value is treated as no role-sync intent. An empty array intentionally removes currently assigned managed roles while preserving unmanaged roles. `ensureRoles` defaults to `true`, so desired missing roles are created before assignment; set it to `false` if typos or insufficient administrative privileges should fail instead of creating roles. `maxRolesPerSync` defaults to `100` and rejects larger desired role arrays before role lookup or mapping requests, bounding caller-controlled remote work.
|
|
@@ -184,9 +297,11 @@ For existing Keycloak users, owned string profile fields (`username`, `email`, `
|
|
|
184
297
|
|
|
185
298
|
Attributes are normalized to Keycloak string arrays. Use `mapAttributes` for dynamic key/value mappings and `attributePaths` to list the Mongoose fields that should trigger an attribute resync. Existing unmanaged Keycloak attributes are preserved, including when a user is resolved by email. Set `managedAttributes` to the keys this plugin owns; managed keys are replaced by the mapper result and removed when omitted, returned as `null`/`undefined`, returned as an empty array, or mapped to unsupported object values. Attribute keys named `__proto__`, `prototype`, or `constructor` are rejected.
|
|
186
299
|
|
|
187
|
-
|
|
300
|
+
Mapper dependencies are explicit: `attributePaths`, `rolePaths`, and `passwordPaths` declare the extra Mongoose paths that trigger the `attributes`/`roles`/`password` operations when `mapAttributes`/`mapRoles`/`mapPassword` read beyond their configured paths (as with the `tier` and virtual `pendingPassword` inputs above). Dependencies are honored only while the corresponding `syncFields` entry is enabled; disabled fields stay fully inert. Dependency arrays are validated and snapshotted at registration. The password mapper is evaluated lazily — only for creation (new remote user, exactly once, with the value reused by the same-save recovery attempt) or when a declared password change indicates actual password-sync intent — so unrelated updates never invoke it and never reset credentials; likewise `mapRoles` runs only inside role sync for creations or `roles` changes.
|
|
301
|
+
|
|
302
|
+
Password sync is disabled by default to avoid sending stored password hashes to Keycloak. Enable it only when the mapped value is a short-lived, non-persisted plaintext input such as the `pendingPassword` virtual above — never an ordinary stored plaintext schema path. Passwords are never included in user-create or profile-update payloads; both newly created users and existing users are updated through Keycloak's reset-password endpoint with the configured `passwordTemporary` value. The plugin stores a newly resolved Keycloak user ID before optional password, role, and verification-email work so a later retry can converge on the same remote user instead of creating a duplicate. A partially provisioned account stays disabled until its required credentials succeed: profile updates never carry `enabled`, and enablement follows the credential reset. The application owns the lifecycle of plaintext password inputs: keep them short-lived and non-persisted, and prevent them from being logged, traced, or sent to error reporters beyond the intended Keycloak operation.
|
|
188
303
|
|
|
189
|
-
Errors are logged to `console.error` and rethrown by default. The
|
|
304
|
+
Errors are logged to `console.error` and rethrown by default. The logger boundary receives only an allowlisted summary — `{ operation, localDocumentId, error: { name, code?, status? } }` with a validated error name and optional machine codes — and never the message, stack, cause, request/response data, or arbitrary error properties, so transport secrets cannot flow into logs. `onError` still receives the original error for private processing with the same safe context by default. Set `includeDocumentInErrorContext: true` only for private handlers that are allowed to receive the full Mongoose document, which can contain plaintext passwords, email addresses, attributes, and arbitrary application fields. Logger and `onError` failures do not replace the original Keycloak sync error; with `throwOnError: false`, those observer failures are best-effort and are swallowed.
|
|
190
305
|
|
|
191
306
|
Only document `save()` and document `deleteOne()` are intercepted. Query operations such as `updateOne()`, `findOneAndUpdate()`, and query `deleteOne()` bypass the plugin. The selected delivery contract is direct, non-atomic hooks: Keycloak work is not part of the MongoDB commit, and the plugin rejects documents saved or deleted with a Mongoose session or transaction. Applications that need transactional delivery should write their own outbox intent in the MongoDB transaction and process it after commit.
|
|
192
307
|
|
package/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { ModelDocument, ModelFunctionInstanceMethods, ModelFunctionPluginOptions, ModelFunctionStaticMethods, modelFunctionPlugin } from './plugins/model-function.mjs';
|
|
2
|
-
export { CascadeDeleteDependencyMap, CascadeDeleteDocumentMethods, CascadeDeleteModelStatics, CascadeDeletePluginOptions, FilterResolver, QueryFilter, cascadeDeletePlugin } from './plugins/cascade-delete.mjs';
|
|
2
|
+
export { CascadeDeleteDependencyMap, CascadeDeleteDocumentMethods, CascadeDeleteModelStatics, CascadeDeletePluginOptions, FilterResolver, QueryFilter, QueryOperators, cascadeDeletePlugin } from './plugins/cascade-delete.mjs';
|
|
3
3
|
export { NewDocumentPluginOptions, newDocumentPlugin } from './plugins/new-document.mjs';
|
|
4
|
-
export { uniqueEmptiableString, uniqueNullableString } from './schema.mjs';
|
|
4
|
+
export { SchemaOptionOverrides, uniqueEmptiableString, uniqueNullableString } from './schema.mjs';
|
|
5
5
|
export { isObjectId } from './is.mjs';
|
|
6
6
|
import 'mongoose';
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { ModelDocument, ModelFunctionInstanceMethods, ModelFunctionPluginOptions, ModelFunctionStaticMethods, modelFunctionPlugin } from './plugins/model-function.js';
|
|
2
|
-
export { CascadeDeleteDependencyMap, CascadeDeleteDocumentMethods, CascadeDeleteModelStatics, CascadeDeletePluginOptions, FilterResolver, QueryFilter, cascadeDeletePlugin } from './plugins/cascade-delete.js';
|
|
2
|
+
export { CascadeDeleteDependencyMap, CascadeDeleteDocumentMethods, CascadeDeleteModelStatics, CascadeDeletePluginOptions, FilterResolver, QueryFilter, QueryOperators, cascadeDeletePlugin } from './plugins/cascade-delete.js';
|
|
3
3
|
export { NewDocumentPluginOptions, newDocumentPlugin } from './plugins/new-document.js';
|
|
4
|
-
export { uniqueEmptiableString, uniqueNullableString } from './schema.js';
|
|
4
|
+
export { SchemaOptionOverrides, uniqueEmptiableString, uniqueNullableString } from './schema.js';
|
|
5
5
|
export { isObjectId } from './is.js';
|
|
6
6
|
import 'mongoose';
|