Socket
Socket
Sign inDemoInstall

monastery-js

Package Overview
Dependencies
42
Maintainers
1
Versions
62
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.10.7 to 1.10.8

5

docs/rules.md

@@ -12,4 +12,3 @@ ---

- | -
required | boolean
type | string - 'string', 'boolean', 'number', 'integer', 'date', 'id', 'any', '[image](#image-type)'
enum | array of strings (for the 'string' type only)
isAfter | see validator.isAfter

@@ -30,2 +29,4 @@ isBefore | see validator.isBefore

regex | see validator.matches
required | boolean
type | string - 'string', 'boolean', 'number', 'integer', 'date', 'id', 'any', '[image](#image-type)'

@@ -32,0 +33,0 @@ *See [validator](https://github.com/validatorjs/validator.js#validators) for their validator logic*

30

docs/schema.md

@@ -112,3 +112,3 @@ ---

// below for more information
index: true|1|-1|'2dsphere'|'text'|'unique'|Object
index: true|1|-1|'text'|'unique'|Object
}

@@ -130,6 +130,2 @@ ```

// This will create an ascending 2dsphere index which translates:
// { key: { [fieldName]: '2dsphere' }}
index: '2dsphere',
// Text indexes are handled a little differently in which all the fields on the model

@@ -147,2 +143,26 @@ // schema that have a `index: 'text` set are collated into one index, e.g.

And here's how you would use a 2dsphere index, e.g.
```js
schema.fields = {
name: {
type: 'string',
required: true
},
location: {
index: '2dsphere',
type: { type: 'string', default: 'Point' },
coordinates: [{ type: 'number' }] // lng, lat
}
}
// Inserting a 2dsphere point
await db.user.insert({
data: {
location: { coordinates: [170.2628528648167, -43.59467883784971] }
}
}
```
### Custom validation rules

@@ -149,0 +169,0 @@

@@ -9,2 +9,3 @@ let crud = require('./model-crud')

* Setup a model (aka monk collection)
* Todo: convert into a promise
* @param {string} name

@@ -98,6 +99,8 @@ * @param {object} opts - see mongodb colleciton documentation

// Ensure field indexes exist in mongodb
this._setupIndexes().catch(err => {
let errHandler = err => {
if (err.type == 'info') this.info(err.detail)
else this.error(err)
})
}
if (opts.promise) return this._setupIndexes().catch(errHandler)
else this._setupIndexes().catch(errHandler)
}

@@ -137,3 +140,2 @@

let isType = 'is' + util.ucFirst(field.type)
//if (field.index == '2dspehere') return

@@ -179,3 +181,9 @@ // No type defined

let nullObject = this.manager.nullObjects
field.schema = { type: 'object', isObject: true, default: objectDefault, nullObject: nullObject, ...(field.schema || {}) }
let index2dsphere = util.isSubdocument2dsphere(field)
field.schema = field.schema || {}
if (index2dsphere) {
field.schema.index = index2dsphere
delete field.index
}
field.schema = { type: 'object', isObject: true, default: objectDefault, nullObject: nullObject, ...field.schema }
this._setupFields(field)

@@ -233,3 +241,2 @@ }

// Create indexes
// console.log(indexes)
return (model.manager._state == 'open'? Promise.resolve() : model.manager)

@@ -247,3 +254,3 @@ .then(data => {

.then(indexes1 => {
// Remove existing text index that has different options otherwise createIndexes will throw an error
// Remove any existing text index that has different options as createIndexes will throws error about this
let indexNames = []

@@ -279,18 +286,21 @@ if (!indexes1.length) return Promise.resolve()

util.forEach(fields, (field, name) => {
if (util.isSubdocument(field)) recurseFields(field, parentPath + name + '.')
if (!field.index/* || util.isObject(field.index)*/) return // commented out for future options
let index = field.index
if (index) {
let path = name == 'schema'? parentPath.slice(0, -1) : parentPath + name
let options = util.isObject(index)? util.omit(index, ['type']) : {}
let type = util.isObject(index)? index.type : index
if (type === true) type = 1
let path = parentPath + name
let options = util.isObject(field.index)? field.index.filter((o, k) => k !== 'type') : {}
let type = util.isObject(field.index)? field.index.type : field.index
if (type === true) type = 1
if (type == 'text') {
hasTextIndex = textIndex.key[path] = 'text'
Object.assign(textIndex, options)
} else if (type == '1' || type == '-1' || type == '2dsphere') {
indexes.push({ name: `${path}_${type}`, key: { [path]: type }, ...options })
} else if (type == 'unique') {
indexes.push({ name: `${path}_1`, key: { [path]: 1 }, unique: true, ...options })
if (type == 'text') {
hasTextIndex = textIndex.key[path] = 'text'
Object.assign(textIndex, options)
} else if (type == '1' || type == '-1' || type == '2dsphere') {
indexes.push({ name: `${path}_${type}`, key: { [path]: type }, ...options })
} else if (type == 'unique') {
indexes.push({ name: `${path}_1`, key: { [path]: 1 }, unique: true, ...options })
}
}
if (util.isSubdocument(field)) {
recurseFields(field, parentPath + name + '.')
}
})

@@ -297,0 +307,0 @@ }

@@ -135,2 +135,10 @@ let id = require('monk').id

},
'enum': {
message: (x, arg) => 'Invalid enum value',
fn: function(x, arg) {
for (let item of arg) {
if (x === item + '') return true
}
}
},

@@ -137,0 +145,0 @@ // Rules below ignore null & empty strings

@@ -98,3 +98,3 @@ module.exports = {

isSchema: function(value) {
return !this.isSubdocument(value) && !this.isArray(value)
return !this.isSubdocument(value) && !this.isArray(value) && typeof value !== 'string'
},

@@ -109,3 +109,2 @@

* Is the value a subdocument which contains more fields? Or a just a field definition?
* Note: Passing { index: '2dsphere' } as a subdocument as this is used to denote a 2dsphere object index
* @param {object} value - object to check

@@ -119,4 +118,5 @@ * E.g. isSubdocument = {

for (let key in value) {
if (key == 'index' && value[key] == '2dsphere') continue
if (this.isObject(value[key]) || this.isArray(value[key])) continue
let v = value[key]
if (key == 'index' && this.isSubdocument2dsphere({ index: v })) continue
if (this.isObject(v) || this.isArray(v)) continue
return false

@@ -127,2 +127,12 @@ }

isSubdocument2dsphere: function(value) {
/**
* Index 2dsphere implies that the parent object is a subdocument
* @return index value
*/
if (value.index == '2dsphere') return '2dsphere'
else if (this.isObject(value.index) && value.index.type == '2dsphere') return value.index
else return false
},
isUndefined: function(value) {

@@ -129,0 +139,0 @@ return typeof value === 'undefined'

@@ -5,3 +5,3 @@ {

"author": "Ricky Boyce",
"version": "1.10.7",
"version": "1.10.8",
"license": "MIT",

@@ -8,0 +8,0 @@ "repository": "github:boycce/monastery",

@@ -106,3 +106,3 @@ module.exports = function(monastery, db) {

let user = db.model('user', {})
let zuser = db.model('zuser', {})
let user2 = db.model('user2', {})

@@ -121,3 +121,3 @@ // Text index setup

// Text index on a different model
await expect(zuser._setupIndexes({
await expect(user2._setupIndexes({
name: { type: 'string', index: 'text' }

@@ -130,2 +130,66 @@ })).resolves.toEqual(undefined)

test('Model 2dsphere indexes', async (done) => {
// Setup. The tested model needs to be unique as race condition issue arises when the same model
// with text indexes are setup at the same time
let db = monastery('localhost/monastery', { serverSelectionTimeoutMS: 2000 })
await db.model('user3', {
promise: true,
fields: {
location: {
index: '2dsphere',
type: { type: 'string', default: 'Point' },
coordinates: [{ type: 'number' }] // lat, lng
},
location2: {
index: { type: '2dsphere' }, // opts...
type: { type: 'string', default: 'Point' },
coordinates: [{ type: 'number' }] // lat, lng
}
}
})
// Schema check
expect(db.user3.fields.location).toEqual({
type: { type: 'string', default: 'Point', isString: true },
coordinates: expect.any(Array),
schema: {
default: undefined,
index: "2dsphere",
isObject: true,
nullObject: undefined,
type: "object"
}
})
expect(db.user3.fields.location2).toEqual({
type: { type: 'string', default: 'Point', isString: true },
coordinates: expect.any(Array),
schema: {
default: undefined,
index: { type: "2dsphere" },
isObject: true,
nullObject: undefined,
type: "object"
}
})
// Insert 2dsphere point data
await expect(db.user3.insert({
data: {
location: { coordinates: [172.5880385, -43.3311608] }
}
})).resolves.toEqual({
_id: expect.any(Object),
createdAt: expect.any(Number),
location: {
coordinates: [172.5880385, -43.3311608],
type: "Point"
},
updatedAt: expect.any(Number),
})
db.close()
done()
})
test('Model findWL, findBLProject', async (done) => {

@@ -132,0 +196,0 @@ let db = monastery('localhost/monastery', {

@@ -320,3 +320,4 @@ module.exports = function(monastery, db) {

name: { type: 'string', minLength: 7 },
email: { type: 'string', isEmail: true }
email: { type: 'string', isEmail: true },
names: { type: 'string', enum: ['Martin', 'Luther'] }
}})

@@ -349,2 +350,15 @@

})
// Enum
await expect(user.validate({ names: 'Martin' })).resolves.toEqual({ "names": "Martin" })
await expect(user.validate({ names: 'bad name' })).rejects.toContainEqual({
detail: "Invalid enum value",
status: "400",
title: "names",
meta: {
model: "user",
field: "names",
rule: "enum"
}
})
})

@@ -351,0 +365,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc