monastery 3.5.6 → 3.5.8
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/changelog.md +4 -0
- package/docs/definition/index.md +17 -3
- package/docs/model/find.md +3 -6
- package/docs/model/insert.md +1 -1
- package/docs/model/update.md +3 -3
- package/docs/readme.md +1 -0
- package/lib/manager.js +3 -2
- package/lib/rules.js +1 -1
- package/lib/util.js +13 -7
- package/package.json +1 -1
- package/test/collection.js +2 -2
- package/test/manager.js +4 -4
- package/types/lib/manager.d.ts +1 -1
- package/types/lib/manager.d.ts.map +1 -1
package/changelog.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [3.5.8](https://github.com/boycce/monastery/compare/3.5.6...3.5.8) (2025-12-23)
|
|
6
|
+
|
|
7
|
+
### [3.5.7](https://github.com/boycce/monastery/compare/3.5.6...3.5.7) (2025-09-16)
|
|
8
|
+
|
|
5
9
|
### [3.5.6](https://github.com/boycce/monastery/compare/3.5.5...3.5.6) (2025-06-15)
|
|
6
10
|
|
|
7
11
|
### [3.5.5](https://github.com/boycce/monastery/compare/3.5.4...3.5.5) (2025-06-14)
|
package/docs/definition/index.md
CHANGED
|
@@ -147,7 +147,7 @@ fieldType: {
|
|
|
147
147
|
|
|
148
148
|
### MongoDB indexes
|
|
149
149
|
|
|
150
|
-
You are able to
|
|
150
|
+
You are able to define MongoDB indexes via the `index` field option, these are automatically on initialisation. **Note, Monastery doesn't delete old indexes**.
|
|
151
151
|
|
|
152
152
|
```js
|
|
153
153
|
fieldType: {
|
|
@@ -304,7 +304,7 @@ You are able to define custom error messages for each field rule.
|
|
|
304
304
|
|
|
305
305
|
### Operation hooks
|
|
306
306
|
|
|
307
|
-
You are able provide an array of promises to the following model operation hooks.
|
|
307
|
+
You are able provide an array of promises to the following model operation hooks.
|
|
308
308
|
|
|
309
309
|
```js
|
|
310
310
|
{
|
|
@@ -318,7 +318,7 @@ You are able provide an array of promises to the following model operation hooks
|
|
|
318
318
|
beforeInsertUpdate: [await function(data) {}],
|
|
319
319
|
beforeUpdate: [await function(data) {}],
|
|
320
320
|
beforeRemove: [await function() {}],
|
|
321
|
-
beforeValidate: [await function(data) {}],
|
|
321
|
+
beforeValidate: [await function(data) {}], // runs prior to beforeInsert/Update
|
|
322
322
|
|
|
323
323
|
// You can also return an object which will be passed to the next hook in the chain, or if it's the last hook, returned as the result:
|
|
324
324
|
afterFind: [await function(data) {
|
|
@@ -328,6 +328,20 @@ You are able provide an array of promises to the following model operation hooks
|
|
|
328
328
|
}
|
|
329
329
|
```
|
|
330
330
|
|
|
331
|
+
The context (`this`) inside each hook will contain extra information relating to the operation, for an example, a basic update operation may contain the following fields:
|
|
332
|
+
```js
|
|
333
|
+
{
|
|
334
|
+
query: { _id: new ObjectId("68d66a33ae584af64197c971") },
|
|
335
|
+
data: { name: 'John Doe' },
|
|
336
|
+
limit: 1,
|
|
337
|
+
sort: { createdAt: -1 },
|
|
338
|
+
type: 'update',
|
|
339
|
+
model: {...}, // Model reference,
|
|
340
|
+
skipValidation: [],
|
|
341
|
+
// ...
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
331
345
|
### Methods
|
|
332
346
|
|
|
333
347
|
You are able define reusable methods in the definition which is handy for storing related functions.
|
package/docs/model/find.md
CHANGED
|
@@ -123,12 +123,9 @@ user.find({
|
|
|
123
123
|
as: 'myBooks',
|
|
124
124
|
from: 'book',
|
|
125
125
|
let: { userId: '$_id' },
|
|
126
|
-
pipeline: [
|
|
127
|
-
$match: {
|
|
128
|
-
|
|
129
|
-
$eq: ['$bookOwnerId', '$$userId']
|
|
130
|
-
}
|
|
131
|
-
}
|
|
126
|
+
pipeline: [
|
|
127
|
+
{ $match: { $expr: { $eq: ['$bookOwnerId', '$$userId'] } } },
|
|
128
|
+
{ $project: { '_id': 1, 'bookTitle': 1 }}, // <-- optional line to make responses smaller.
|
|
132
129
|
}]
|
|
133
130
|
}]
|
|
134
131
|
})
|
package/docs/model/insert.md
CHANGED
|
@@ -5,7 +5,7 @@ parent: Model
|
|
|
5
5
|
|
|
6
6
|
# `model.insert`
|
|
7
7
|
|
|
8
|
-
Validate and insert document(s) in a collection and calls model hooks: `beforeInsert`,
|
|
8
|
+
Validate and insert document(s) in a collection and calls model hooks: `beforeValidate`, `beforeInsert`, `afterInsert`
|
|
9
9
|
|
|
10
10
|
### Arguments
|
|
11
11
|
|
package/docs/model/update.md
CHANGED
|
@@ -5,14 +5,14 @@ parent: Model
|
|
|
5
5
|
|
|
6
6
|
# `model.update`
|
|
7
7
|
|
|
8
|
-
Update document(s) in a collection and calls model hooks: `beforeUpdate`, `afterUpdate`. By default this method method updates a single document. Set the `multi` mongodb option to update all documents that match the query criteria.
|
|
8
|
+
Update document(s) in a collection and calls model hooks: `beforeValidate`, `beforeUpdate`, `afterUpdate`. By default this method method updates a single document. Set the `multi` mongodb option to update all documents that match the query criteria.
|
|
9
9
|
|
|
10
10
|
### Arguments
|
|
11
11
|
|
|
12
12
|
`options` *(object)*
|
|
13
13
|
|
|
14
14
|
- `query` *(object\|id)*: [`MongoDB query document`](https://www.mongodb.com/docs/v5.0/tutorial/query-documents/), or id
|
|
15
|
-
- [`data`](#data) *(object)* - data that's validated against the model fields
|
|
15
|
+
- [`data`](#data) *(object)* - data that's validated against the model fields, which eventually gets wrapped in `{ $set: .. }`
|
|
16
16
|
- [[`blacklist`](#blacklisting)]*(array\|string\|false)*: augment `definition.updateBL`. `false` will remove all blacklisting
|
|
17
17
|
- [`project`] *(string\|array\|object)*: project these fields, ignores blacklisting
|
|
18
18
|
- [`skipValidation`] *(string\|array\|boolean)*: skip validation for these fields, or pass `true` to skip all fields and validation hooks
|
|
@@ -42,7 +42,7 @@ await user.update({ query: { name: 'foo' }, data: { name: 'bar' }})
|
|
|
42
42
|
|
|
43
43
|
### Data
|
|
44
44
|
|
|
45
|
-
Data that's validated against the model fields
|
|
45
|
+
Data that's validated against the model fields, which eventually gets wrapped in `{ $set: .. }`. Key names can be in dot or bracket notation which is handy for HTML FormData.
|
|
46
46
|
|
|
47
47
|
You can also pass `options.$set` or any other mongodb update operation instead of `options.data`, which bypasses validation, e.g.
|
|
48
48
|
|
package/docs/readme.md
CHANGED
|
@@ -138,6 +138,7 @@ You can view MongoDB's [compatibility table here](https://www.mongodb.com/docs/d
|
|
|
138
138
|
- Add soft remove plugin
|
|
139
139
|
- ~~Added deep path validation support for updates~~
|
|
140
140
|
- ~~Added option skipHooks~~
|
|
141
|
+
- beforeValidate should pass the document rather than the whole array of documents
|
|
141
142
|
|
|
142
143
|
## Debugging
|
|
143
144
|
|
package/lib/manager.js
CHANGED
|
@@ -100,7 +100,8 @@ function Manager(uri, opts, parent) {
|
|
|
100
100
|
// Update the parent manager with the new manager
|
|
101
101
|
if (!hasDefaultManager && parent) hasDefaultManager = true
|
|
102
102
|
if (opts.promise) return that.open()
|
|
103
|
-
|
|
103
|
+
that.open()
|
|
104
|
+
return that // return that since it may be a different context
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
Manager.prototype.manager = function(uri, opts) {
|
|
@@ -134,7 +135,7 @@ Manager.prototype.close = async function() {
|
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
137
|
|
|
137
|
-
Manager.prototype.
|
|
138
|
+
Manager.prototype.rawCommand = function(...args) {
|
|
138
139
|
/**
|
|
139
140
|
* Run a raw MongoDB command
|
|
140
141
|
*/
|
package/lib/rules.js
CHANGED
package/lib/util.js
CHANGED
|
@@ -71,22 +71,28 @@ module.exports = {
|
|
|
71
71
|
forceArray: function(value) {
|
|
72
72
|
return this.isArray(value)? value : [value]
|
|
73
73
|
},
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @typedef {string} HexString
|
|
77
|
+
* @description A hex string of 24 characters
|
|
78
|
+
*/
|
|
74
79
|
|
|
75
80
|
/**
|
|
76
81
|
* Casts to ObjectId
|
|
77
|
-
* @param {
|
|
78
|
-
* @return {ObjectId}
|
|
82
|
+
* @param {HexString|ObjectId} [value] - empty string = new ObjectId('')
|
|
79
83
|
*/
|
|
80
|
-
id: function(
|
|
81
|
-
if (
|
|
82
|
-
|
|
84
|
+
id: function(value) {
|
|
85
|
+
if (value === undefined) return new ObjectId()
|
|
86
|
+
else if (typeof value === 'string') return ObjectId.createFromHexString(value)
|
|
87
|
+
else if (value instanceof ObjectId) return value
|
|
88
|
+
else throw new Error(`Monastery: invalid value "${value}" passed to id(value?: HexString|ObjectId).`)
|
|
83
89
|
},
|
|
84
90
|
|
|
85
91
|
inArray: (array, key, value) => {
|
|
86
92
|
/**
|
|
87
93
|
* Property match inside an array of objects
|
|
88
94
|
* (For a string/number value check just use [].includes(x))
|
|
89
|
-
* @param {string}
|
|
95
|
+
* @param {string} [key] - optional to match across on a colleciton of objects
|
|
90
96
|
* @param {any} value
|
|
91
97
|
*/
|
|
92
98
|
if (!array || typeof key == 'undefined') return false
|
|
@@ -361,7 +367,7 @@ module.exports = {
|
|
|
361
367
|
/**
|
|
362
368
|
* Runs functions in series
|
|
363
369
|
*
|
|
364
|
-
* @param {
|
|
370
|
+
* @param {((err: any, result: any) => any)[]} tasks - array of functions
|
|
365
371
|
* @param {string} hookName - e.g. 'afterFind'
|
|
366
372
|
* @param {any} data - data to pass to the first function
|
|
367
373
|
*
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "monastery",
|
|
3
3
|
"description": "⛪ A simple, straightforward MongoDB ODM",
|
|
4
4
|
"author": "Ricky Boyce",
|
|
5
|
-
"version": "3.5.
|
|
5
|
+
"version": "3.5.8",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": "github:boycce/monastery",
|
|
8
8
|
"homepage": "https://boycce.github.io/monastery/",
|
package/test/collection.js
CHANGED
|
@@ -425,8 +425,8 @@ test('bulkWrite', async () => {
|
|
|
425
425
|
})
|
|
426
426
|
|
|
427
427
|
test('drop > should not throw when dropping an empty db', async () => {
|
|
428
|
-
|
|
429
|
-
expect(result).
|
|
428
|
+
await db.get('dropDB-' + Date.now()).drop().catch(() => false)
|
|
429
|
+
// expect(result).toBeUndefined()
|
|
430
430
|
})
|
|
431
431
|
|
|
432
432
|
test('caching collections', () => {
|
package/test/manager.js
CHANGED
|
@@ -8,12 +8,12 @@ test('manager > basics', async () => {
|
|
|
8
8
|
// Basic find command
|
|
9
9
|
expect(await db.db.collection('non-collection').findOne({})).toEqual(null)
|
|
10
10
|
// Raw MongoDB ping command
|
|
11
|
-
expect(await db.
|
|
11
|
+
expect(await db.rawCommand({ ping: 1 })).toMatchObject({ ok: 1 }) // cluster connections return extra fields
|
|
12
12
|
db.close()
|
|
13
13
|
})
|
|
14
14
|
|
|
15
15
|
test('manager > uri error', async () => {
|
|
16
|
-
expect(() => monastery.manager('', {})).toThrow('No connection URI provided.')
|
|
16
|
+
expect(() => monastery.manager('', {})).toThrow('No monastery connection URI provided.')
|
|
17
17
|
})
|
|
18
18
|
|
|
19
19
|
test('manager > onError', async () => {
|
|
@@ -21,7 +21,7 @@ test('manager > onError', async () => {
|
|
|
21
21
|
const db = monastery.manager('localhost:1234/monastery', { serverSelectionTimeoutMS: 500 })
|
|
22
22
|
let error, isAPromise
|
|
23
23
|
await db.onError((res) => { error = res.message }).then(() => { isAPromise = true })
|
|
24
|
-
expect(error).
|
|
24
|
+
expect(error).toContain('connect ECONNREFUSED 127.0.0.1:1234')
|
|
25
25
|
expect(isAPromise).toEqual(true)
|
|
26
26
|
db.close()
|
|
27
27
|
})
|
|
@@ -67,7 +67,7 @@ test('manager > return a promise', async () => {
|
|
|
67
67
|
|
|
68
68
|
test('manager > return a promise with uri error', async () => {
|
|
69
69
|
await expect(monastery.manager('badlocalhost/monastery', { serverSelectionTimeoutMS: 500, promise: true }))
|
|
70
|
-
.rejects.toThrow(
|
|
70
|
+
.rejects.toThrow(/getaddrinfo ENOTFOUND badlocalhost/)
|
|
71
71
|
})
|
|
72
72
|
|
|
73
73
|
test('manager > reuse MongoDB Client', async () => {
|
package/types/lib/manager.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ declare class Manager {
|
|
|
6
6
|
arrayWithSchema(array: any, schema: any): any;
|
|
7
7
|
close(): Promise<any>;
|
|
8
8
|
_state: string;
|
|
9
|
-
|
|
9
|
+
rawCommand(...args: any[]): any;
|
|
10
10
|
connectionString(uri: any, databaseName: any): any;
|
|
11
11
|
get(name: any, options: any): any;
|
|
12
12
|
id(str: any): import("bson").ObjectId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../lib/manager.js"],"names":[],"mappings":";AAYA,
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../lib/manager.js"],"names":[],"mappings":";AAYA,gEA4FC;;IA5FD,8CA4FC;IAED,sCAEC;IAED,8CAGC;IAED,sBAoBC;IAfqB,eAAuB;IAiB7C,gCAKC;IAED,mDA2BC;IAED,kCAYC;IAED,sCAEC;IAED,0BAEC;IAED,8CAsCC;IAED,+BAiBC;IAED,8BAuBC;IAED,sBAsBC;IAfG,QAA0B;IAiB9B,gFAEC;IAED,oBAAuB;IAEvB,2EAA8B;IAE9B,uBAEC"}
|