New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

nekodb

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nekodb - npm Package Compare versions

Comparing version 1.1.2 to 2.0.0

lib/typeclass/objectid.js

0

lib/clients/cursor.js

@@ -0,0 +0,0 @@ function Cursor (cursor, client, model, projection) {

@@ -0,0 +0,0 @@ // like a cursor, but for single document returning queries

@@ -0,0 +0,0 @@ NeDBClient = require('./nedb')

@@ -0,0 +0,0 @@ const MongoDB = require('mongodb')

@@ -0,0 +0,0 @@ const path = require('path')

@@ -0,0 +0,0 @@ // returns a Mongo update query

18

lib/models/instance.js

@@ -23,2 +23,6 @@ const isRawObject = require('../util').isRawObject

Instance.prototype.isUpdated = function (field) {
return field in this._updates
}
Instance.prototype.save = function () {

@@ -86,6 +90,6 @@ return this._model._save(this)

set (value) {
const coerced = model.coerce(field, value)
if (Array.isArray(value) ||
value instanceof Instance ||
isRawObject(value)) {
this._updates[field] = new UpdateProxy(o, field, value)
this._updates[field] = new UpdateProxy(o, field, coerced, model.schema[field])
Object.defineProperty(this._updates[field], '_replace', {

@@ -97,3 +101,3 @@ value: true,

}
this._updates[field] = value
this._updates[field] = coerced
},

@@ -103,7 +107,5 @@ })

o[field] = processed[field]
}
else if (Array.isArray(processed[field]) ||
processed[field] instanceof Instance ||
} else if (Array.isArray(processed[field]) ||
isRawObject(processed[field])) {
o._values[field] = new UpdateProxy(o, field, processed[field])
o._values[field] = new UpdateProxy(o, field, processed[field], model.schema[field])
} else {

@@ -117,3 +119,3 @@ o._values[field] = processed[field]

if (Array.isArray(reference) || reference instanceof Instance) {
o._values[field] = new UpdateProxy(o, field, reference)
o._values[field] = new UpdateProxy(o, field, reference, model.schema[field])
} else {

@@ -120,0 +122,0 @@ o._values[field] = reference

@@ -7,2 +7,3 @@ const isRawObject = require('../util').isRawObject

prototype.count = function (query) {
this.coerceQuery(query)
return this.client.count(this.name, query)

@@ -29,2 +30,3 @@ }

prototype.deleteMany = function (query) {
this.coerceQuery(query)
if (this._hasDeleteHooks()) {

@@ -36,3 +38,3 @@ let instances

return Promise.all(instances.map(instance => {
return runHooks(this.predelete, instance)
return promisifyHook(this.predelete, instance)
}))

@@ -45,3 +47,3 @@ }).then(() => {

return Promise.all(instances.map(instance => {
return runHooks(this.postdelete, instance)
return promisifyHook(this.postdelete, instance)
}))

@@ -56,2 +58,3 @@ }).then(() => {

prototype.deleteOne = function (query) {
this.coerceQuery(query)
if (this._hasDeleteHooks()) {

@@ -62,3 +65,3 @@ let instance

instance = found
return runHooks(this.predelete, instance)
return promisifyHook(this.predelete, instance)
}).then(() => {

@@ -69,3 +72,3 @@ this.client.deleteOne(this.name, query).then(count => {

}).then(() => {
return runHooks(this.postdelete, instance)
return promisifyHook(this.postdelete, instance)
}).then(() => {

@@ -79,2 +82,3 @@ return deletedCount

prototype.find = function (query, projection) {
this.coerceQuery(query)
return this.client.find(this.name, query, projection, this)

@@ -88,2 +92,3 @@ }

prototype.findOne = function (query, projection) {
this.coerceQuery(query)
return this.client.findOne(this.name, query, projection, this)

@@ -136,20 +141,4 @@ }

if (instance.__original) {
return runHooks(hook, instance)
}
return Promise.resolve()
}
function runHooks (hook, instance) {
if (typeof hook === 'function') {
return promisifyHook(hook, instance)
}
if (typeof hook === 'object') {
const hooks = []
for (const field in hook) {
if (field in instance._updates) {
hooks.push(promisifyHook(hook[field], instance))
}
}
return Promise.all(hooks)
}
return Promise.resolve()

@@ -159,2 +148,5 @@ }

function promisifyHook (hook, instance) {
if (!hook) {
return Promise.resolve()
}
let returnedPromise

@@ -210,9 +202,9 @@ const promisified = new Promise((resolve, reject) => {

return runOncreate(this.oncreate, instance).then(() => {
return runHooks(this.prevalidate, instance)
return promisifyHook(this.prevalidate, instance)
}).then(() => {
return this.validate(instance)
}).then(() => {
return runHooks(this.postvalidate, instance)
return promisifyHook(this.postvalidate, instance)
}).then(() => {
return runHooks(this.presave, instance)
return promisifyHook(this.presave, instance)
}).then(() => {

@@ -228,3 +220,3 @@ return this.client.save(this.name, instance)

}).then(() => {
return runHooks(this.postsave, instance)
return promisifyHook(this.postsave, instance)
}).then(() => {

@@ -231,0 +223,0 @@ // copy _updates values into _values

@@ -1,2 +0,2 @@

const deepEqual = require('deep-equal')
const traverse = require('traverse')

@@ -8,2 +8,3 @@ const Typeclass = require('../typeclass')

const ModelReference = require('./reference')
const isRawObject = require('../util').isRawObject

@@ -49,4 +50,4 @@ const hooks = ['oncreate', 'prevalidate', 'postvalidate', 'presave', 'postsave', 'predelete', 'postdelete']

if (!('_id' in schema)) {
// _id is optional because it might need to be created
o.schema._id = Typeclass([Typeclass.types.String, Typeclass.types.Number, null])
// ObjectID by default. Can be overriden. The typeclass handles the null case directly.
o.schema._id = Typeclass.types.ObjectID(client.ObjectID)
}

@@ -91,2 +92,73 @@ for (const field in schema) {

Model.prototype.coerce = function (field, value) {
if (value === undefined) {
return value
}
return this.schema[field].coerce(value)
}
Model.prototype.coerceQuery = function (query) {
if (Object.keys(query).length === 0) {
return
}
const schema = this.schema
const ObjectID = this.client.ObjectID
// traverse the query and transform only leaf nodes
traverse(query).forEach(function (value) {
if (this.isLeaf) {
const field = this.path.filter(segment => {
if (segment === '$and') return false
if (segment === '$or') return false
if (segment === '$not') return false
if (segment === '$nor') return false
if (String(parseInt(segment)) === segment) return false
return true
})
// ObjectIDs are Objects and their leaf nodes should be ignored
if (this.parent.node instanceof ObjectID) return
if (this.parent.node instanceof Buffer) return
// certain queries should not be coerced
if (field === '$expr') return
if (field === '$text') return
if (field === '$where') return
if (field === '$jsonSchema') return
if (this.key === '$regex') return
if (this.key === '$exists') return
if (this.key === '$type') return
if (this.key === '$size') return this.update(Number(value))
// these are not actually leaf nodes. something else will need to be done,
// but only if users need geospatial queries
if (this.key === '$near') return
if (this.key === '$geoIntersects') return
if (this.key === '$geoWithin') return
if (this.key === '$nearSphere') return
let segments
if (field[0].indexOf('.') > -1) {
segments = field[0].split('.')
} else if (isRawObject(schema[field[0]].type)) {
segments = field
}
if (segments) {
let typeclass = schema[segments.shift()]
for (let i = 0; i < segments.length; i++) {
let segment = segments[i]
// last element is an array index
//if (i === segments.length - 1 && String(parseInt(segment)) === segment)
//segment = 0
if (String(parseInt(segment)) === segment) {
typeclass = typeclass.type[0]
} else {
typeclass = typeclass.type[segment]
}
}
this.update(typeclass.coerce(value))
return
}
this.update(schema[field[0]].coerce(value))
}
})
}
Model.prototype.validate = function (record) {

@@ -93,0 +165,0 @@ return new Promise((resolve, reject) => {

const deepEqual = require('deep-equal')
const traverse = require('traverse')
const ModelReference = require('./reference')
const isRawObject = require('../util').isRawObject
function UpdateProxy (parent, field, target, typeclass) {
if (Array.isArray(target)) {
return ArrayProxy(parent, field, target, typeclass)
}
return ObjectProxy(parent, field, target, typeclass)
}
// if any of these methods are called on an array, the array is modified beyond our ability to

@@ -10,29 +18,7 @@ // use native MongoDB array manipulation. Therefore the whole array must be replaced

function UpdateProxy (parent, field, target) {
function ArrayProxy (parent, field, target, typeclass) {
// each proxy has its own _updates object which is also a proxy so that changes bubble up
defineProp(target, '_updates', new Proxy({}, {
set (target, prop, value) {
parent._updates[field] = parent[field]
target[prop] = value
return true
},
}))
define_updates(parent, field, target)
if (target._proxied) {
// reset all child proxies
// might be better to try and use _updates to do this more efficiently
traverse(target).forEach(function (target) {
if (Array.isArray(target) || isRawObject(target)) {
if (this.key !== undefined) {
const parent = this.parent.node
const field = this.key
defineProp(target, '_updates', new Proxy({}, {
set (target, prop, value) {
parent._updates[field] = parent[field]
target[prop] = value
return true
},
}))
}
}
})
resetChildProxies(target)
return target

@@ -42,5 +28,8 @@ }

for (const field of Object.keys(target)) {
if (Array.isArray(target[field]) || isRawObject(target[field])) {
target[field] = new UpdateProxy(target, field, target[field])
if (Array.isArray(target[field])) {
target[field] = ArrayProxy(target, field, target[field], typeclass.type[0])
}
if (isRawObject(target[field])) {
target[field] = ObjectProxy(target, field, target[field], typeclass.type[0])
}
}

@@ -52,71 +41,89 @@ Object.defineProperty(target, '_proxied', {

get (target, prop) {
if (Array.isArray(target)) {
if (prop === '$push') {
parent._updates[field] = parent[field]
return function (push, options) {
options = options || {}
if (!('_$push' in target)) {
defineProp(target, '_$push', [])
if (prop === '$push') {
parent._updates[field] = parent[field]
return function (push, options) {
push = typeclass.coerce(push)
options = options || {}
if (!('_$push' in target)) {
defineProp(target, '_$push', [])
}
if (options.$slice) {
defineProp(target, '_$slice', options.$slice)
}
if (options.$position) {
defineProp(target, '_$position', options.$position)
}
if (Array.isArray(push)) {
for (const p of push) {
target._$push.push(p)
}
if (options.$slice) {
defineProp(target, '_$slice', options.$slice)
}
if (options.$position) {
defineProp(target, '_$position', options.$position)
}
if (Array.isArray(push)) {
for (const p of push) {
target._$push.push(p)
}
} else {
target._$push.push(push)
}
$push(target, push, options.$slice, options.$position)
} else {
target._$push.push(push)
}
$push(target, push, options.$slice, options.$position)
}
if (prop === '$pop') {
parent._updates[field] = parent[field]
return function (direction) {
defineProp(target, '_$pop', direction)
$pop(target, direction)
}
if (prop === '$pop') {
parent._updates[field] = parent[field]
return function (direction) {
defineProp(target, '_$pop', direction)
$pop(target, direction)
}
}
if (prop === '$addToSet') {
parent._updates[field] = parent[field]
return function (add) {
add = typeclass.coerce(add)
if (!('_$addToSet' in target)) {
defineProp(target, '_$addToSet', [])
}
}
if (prop === '$addToSet') {
parent._updates[field] = parent[field]
return function (add) {
if (!('_$addToSet' in target)) {
defineProp(target, '_$addToSet', [])
if (Array.isArray(add)) {
for (const a of add) {
target._$addToSet.push(a)
}
if (Array.isArray(add)) {
for (const a of add) {
target._$addToSet.push(a)
}
} else {
target._$addToSet.push(add)
}
$addToSet(target, add)
} else {
target._$addToSet.push(add)
}
$addToSet(target, typeclass.coerce(add))
}
if (prop === '$pull') {
parent._updates[field] = parent[field]
return function (filter) {
defineProp(target, '_$pull', filter)
$pull(target, filter)
}
}
if (prop === '$pull') {
parent._updates[field] = parent[field]
return function (filter) {
defineProp(target, '_$pull', filter)
$pull(target, filter)
}
if (arrayModifyingMethods.includes(prop)) {
defineProp(target, '_replace', true)
parent._updates[field] = parent[field]
}
if (arrayModifyingMethods.includes(prop)) {
defineProp(target, '_replace', true)
parent._updates[field] = parent[field]
}
if (prop === 'push') {
return function (...elems) {
return target.push(...typeclass.coerce(elems))
}
}
if (prop === 'unshift') {
return function (...elems) {
return target.unshift(...typeclass.coerce(elems))
}
}
if (prop === 'splice') {
return function (start, numRemoved, ...elems) {
return target.splice(start, numRemoved, ...typeclass.coerce(elems))
}
}
return target[prop]
},
set (target, prop, value) {
if (Array.isArray(value) || isRawObject(value)) {
target[prop] = new UpdateProxy(target, prop, value)
const coerced = typeclass.type[0].coerce(value)
if (Array.isArray(value)) {
target[prop] = ArrayProxy(target, prop, coerced, typeclass.type[0])
} else if (isRawObject(value)) {
target[prop] = ObjectProxy(target, prop, coerced, typeclass.type[0])
} else {
target[prop] = value
target[prop] = coerced
}
// this will cause _updates to bubble up until they hit the instance
target._updates[prop] = value
target._updates[prop] = coerced
return true

@@ -127,2 +134,45 @@ },

function ObjectProxy (parent, field, target, typeclass) {
if (typeclass.type instanceof ModelReference) {
// pretend like it's a normal typeclass
typeclass = {
type: typeclass.type.model.schema,
}
}
// each proxy has its own _updates object which is also a proxy so that changes bubble up
define_updates(parent, field, target)
if (target._proxied) {
resetChildProxies(target)
return target
}
// map any object elements in the target into proxies
for (const field of Object.keys(target)) {
if (Array.isArray(target[field])) {
target[field] = ArrayProxy(target, field, target[field], typeclass.type[field])
}
if (isRawObject(target[field])) {
target[field] = ObjectProxy(target, field, target[field], typeclass.type[field])
}
}
Object.defineProperty(target, '_proxied', {
value: true,
})
// Object proxy
return new Proxy(target, {
set (target, prop, value) {
const coerced = typeclass.type[prop].coerce(value)
if (Array.isArray(value)) {
target[prop] = ArrayProxy(target, prop, coerced, typeclass.type[prop])
} else if (isRawObject(value)) {
target[prop] = ObjectProxy(target, prop, coerced, typeclass.type[prop])
} else {
target[prop] = coerced
}
// this will cause _updates to bubble up until they hit the instance
target._updates[prop] = coerced
return true
},
})
}
function defineProp (obj, key, value) {

@@ -136,2 +186,26 @@ Object.defineProperty(obj, key, {

function define_updates (parent, field, target) {
defineProp(target, '_updates', new Proxy({}, {
set (target, prop, value) {
parent._updates[field] = parent[field]
target[prop] = value
return true
},
}))
}
function resetChildProxies (target) {
// might be better to try and use _updates to do this more efficiently
traverse(target).forEach(function (target) {
if (Array.isArray(target) || isRawObject(target)) {
if (this.key !== undefined) {
const parent = this.parent.node
const field = this.key
define_updates(parent, field, target)
}
}
})
}
// use Array.prototype.method.call to avoid triggering array replacement
function $push (array, toPush, slice, position) {

@@ -142,3 +216,3 @@ toPush = Array.isArray(toPush) ? toPush : [toPush]

if (slice) {
Array.prototype.slice.call(array, 0, slice)
Array.prototype.splice.call(array, slice)
}

@@ -145,0 +219,0 @@ }

@@ -55,7 +55,7 @@ const type = require('./type')

const promises = []
for (const prop in this.type) {
for (const prop of Object.keys(this.type)) {
promises.push(this.type[prop].check(value[prop]))
if (!this.type[prop].check(value[prop])) {
return resolve(false)
}
//if (!this.type[prop].check(value[prop])) {
//return resolve(false)
//}
}

@@ -72,2 +72,56 @@ Promise.all(promises).then(matches => {

Typeclass.prototype.coerce = function (value) {
if (this.type instanceof ModelReference) {
if (this.type.type === 'reference') {
// if it's an object, we're going to saveRefs it, so it should not be coerced now
// or it's an ObjectID in which case we don't need to coerce it anyway
if (typeof value === 'object') {
return value
}
return this.type.model.schema._id.coerce(value)
}
if (this.type.type === 'embed' || this.type.type === 'embedOnly') {
for (const field of Object.keys(value)) {
value[field] = this.type.model.coerce(field, value[field])
}
return value
}
}
if (this.type === Boolean) {
if (value === 'true') {
return true
}
if (value === 'false') {
return false
}
return Boolean(value)
}
if (this.type === String) {
return String(value)
}
if (this.type === Number) {
return Number(value)
}
if (this.type === Date) {
return new Date(value)
}
if (type.isArray(this.type)) {
if (Array.isArray(value)) {
return value.map(val => this.type[0].coerce(val))
}
return this.type[0].coerce(value)
}
// in the interest of keeping coerce synchronous, we will not perform type coersion on Option types
// currently it's impossible to determine which type the value should be coerced to in a synchronous way
if (type.isOption(this.type)) {
return value
}
if (typeof this.type === 'object') {
for (const prop of Object.keys(this.type)) {
value[prop] = this.type[prop].coerce(value[prop])
}
return value
}
}
Typeclass.prototype.__init = function (src) {

@@ -74,0 +128,0 @@ this.type = undefined

@@ -7,2 +7,3 @@ const construction = require('./construction')

const _Date = require('./date')()
const _ObjectID = require('./objectid')
const util = require('./util')

@@ -71,2 +72,3 @@

}),
ObjectID: _ObjectID,
Email: util.Email,

@@ -73,0 +75,0 @@ URL: util.URL,

@@ -0,0 +0,0 @@ // contains utility Typeclasses

{
"name": "nekodb",
"version": "1.1.2",
"version": "2.0.0",
"description": "Tiny ODM for MongoDB/NeDB",
"main": "ko.js",
"scripts": {
"test": "tape ./test/test.js | tap-spec",
"test": "tape ./test/test.js | tap-spec --color",
"coverage": "nyc tape ./test/test.js | tap-spec",

@@ -9,0 +9,0 @@ "coverageHTML": "nyc report --reporter=html"

@@ -193,2 +193,4 @@ # NekoDB

#### You must call ko.connect before creating your models or you will get the error "ko.models is not defined"
## Creating schemas

@@ -826,9 +828,5 @@

Hooks can be a function, which will run regardless of what fields have been updated, or an object
whose keys are fields, and whose values are the hooks to run only when the specified field is
updated. To add a named hook that always runs, use `''` as the field name.
To determine whether a hook should modify a certain field you can use the instance method
`isUpdated` which takes a field name.
For expensive operations, or operations which should not be repeated, you should use a hook
object with named hooks to limit when the hooks are run.
#### oncreate

@@ -865,13 +863,13 @@ Runs immediately after a model is created. Used to asynchronously add default values to a model

$$hooks: {
presave: {
password: (user, next) => {
bcrypt.hash(user.password, saltRounds, function (err, hash) {
if (err) {
return next(err)
}
user.password = hash
next()
})
}
}
presave: (user, next) => {
if (user.isUpdated('password')) {
bcrypt.hash(user.password, saltRounds, function (err, hash) {
if (err) {
return next(err)
}
user.password = hash
next()
})
}
}
}

@@ -923,2 +921,3 @@ })

```
Now an error will be thrown if we attempt to create two users with the same username.

@@ -925,0 +924,0 @@

module.exports = {
testMongo: false,
testMongo: true,
client: 'mongodb',

@@ -4,0 +4,0 @@ username: '',

@@ -11,2 +11,3 @@ const path = require('path')

const joinTests = require('./tests/model.join')
const coerceTests = require('./tests/model.coerce')
const cursorTests = require('./tests/cursor')

@@ -27,8 +28,10 @@ const hooksTests = require('./tests/hooks')

joinTests(ko, () => {
cursorTests(ko, () => {
hooksTests(ko, () => {
indexTests(ko, () => {
arrayOpsTests(ko, () => {
proxySetTests(ko, () => {
next()
coerceTests(ko, () => {
cursorTests(ko, () => {
hooksTests(ko, () => {
indexTests(ko, () => {
arrayOpsTests(ko, () => {
proxySetTests(ko, () => {
next()
})
})

@@ -35,0 +38,0 @@ })

@@ -9,3 +9,5 @@ const test = require('tape')

ko.models({
ko_db_test_cursor: {},
ko_db_test_cursor: {
_id: ko.Number,
},
})

@@ -12,0 +14,0 @@

@@ -10,2 +10,3 @@ const test = require('tape')

name: ko.String,
update: ko.String,
$$hooks: {

@@ -27,2 +28,6 @@ oncreate: function (instance, next) {

instance.name = 'New value'
if (instance.isUpdated('update')) {
instance.update = 'this field was updated'
}
next()

@@ -49,6 +54,7 @@ },

name: 'Old value',
update: 'Old value',
}).save().then(instance => {
t.equal(instance.additionalValue, 'Added', 'Added value in postsave')
}).then(() => {
return HookModel.count({name: 'New value'})
return HookModel.count({name: 'New value', update: 'this field was updated'})
}).then(count => {

@@ -60,2 +66,3 @@ t.equal(count, 1, 'Saved to database with changed value')

name: 'Value',
update: 'Value',
}).save()

@@ -71,45 +78,2 @@ }).then(() => {

test('Named hooks should only run at the appropriate time', function (t) {
const NamedHookModel = ko.Model('NamedHooks', {
field1: ko.String.match(/^[a-z]*$/),
field2: ko.String.match(/^[a-z]*$/),
})
NamedHookModel.presave = {
field1: (instance, next) => {
instance.field1 = '__' + instance.field1
next()
},
field2: (instance, next) => {
instance.field2 = '__' + instance.field2
next()
},
}
NamedHookModel.create({
_id: '0',
field1: 'abc',
field2: 'def',
}).save().then(model => {
t.deepEqual(model, {
_id: '0',
field1: '__abc',
field2: '__def',
}, 'Presave hooks were run when model was created')
model.field1 = 'ghi'
return model.save()
}).then(model => {
t.equal(model.field1, '__ghi', 'Updated field ran presave hook')
t.equal(model.field2, '__def', 'Not updated field did not run presave hook')
return model.save()
}).then(model => {
t.equal(model.field1, '__ghi', 'When no updates occurred, hooks did not run')
t.equal(model.field2, '__def', 'When no updates occurred, hooks did not run')
t.end()
}).catch(err => {
console.log(err)
t.error(err)
t.end()
})
})
test('All done', function (t) {

@@ -116,0 +80,0 @@ t.end()

@@ -0,0 +0,0 @@ const test = require('tape')

@@ -10,7 +10,8 @@ const test = require('tape')

RefModel = ko.Model('ko_db_test_join_ref', {
_id: ko.Number,
field: ko.String,
})
JoinModel = ko.Model('ko_db_test_join', {
_id: ko.Number,
ref: RefModel,

@@ -21,2 +22,3 @@ ref2: RefModel,

JoinArrModel = ko.Model('ko_db_test_join_multi', {
_id: ko.Number,
refs: [RefModel],

@@ -23,0 +25,0 @@ })

@@ -87,3 +87,5 @@ const test = require('tape')

test('Model#findById', function (t) {
const FindByIdModel = ko.Model('ko_db_test_methods_findbyid', {})
const FindByIdModel = ko.Model('ko_db_test_methods_findbyid', {
_id: ko.String,
})

@@ -144,5 +146,5 @@ FindByIdModel.create({

DeleteModel.create({name: 'Barry'}).save(),
DeleteModel.create({_id: 'B0R1S', name: 'Boris'}).save(),
]).then(() => {
return DeleteModel.deleteById('B0R1S')
DeleteModel.create({name: 'Boris'}).save(),
]).then(models => {
return DeleteModel.deleteById(models[4]._id)
}).then(() => {

@@ -149,0 +151,0 @@ return DeleteModel.count({})

@@ -46,6 +46,7 @@ const test = require('tape')

ko_db_test_ref3: {
field: ko.String
_id: ko.String,
field: ko.String,
},
ko_db_test_test3: {
ref: ko.models.ko_db_test_ref3.reference()
ref: ko.models.ko_db_test_ref3.reference(),
}

@@ -55,3 +56,3 @@ })

_id: '0',
field: 'value'
field: 'value',
}).save().then(ref => {

@@ -91,3 +92,3 @@ const model = ko.models.ko_db_test_test3.create({

ko_db_test_ref4: {
field: ko.String
field: ko.Number.max(99)
},

@@ -99,3 +100,3 @@ ko_db_test_test4: {

const model = ko.models.ko_db_test_test4.create({
ref: { field: 'valid' },
ref: { field: 10 },
})

@@ -108,2 +109,5 @@ ko.models.ko_db_test_test4.validate(model).then(() => {

}).saveRefs()
}).then(saved => {
t.fail('Model saved where it should have failed')
t.end()
}).catch(err => {

@@ -110,0 +114,0 @@ // rejected promise means validation failed

@@ -17,6 +17,16 @@ const test = require('tape')

t.equal(count, 1, 'Count incremented after creation')
return SimpleModel.create({_id: 1, string: 'nice'}).save().then(saved => {
return saved
})
}).then(simple => {
t.end()
}).catch(err => {
t.error(err)
t.end()
})
})
test('Saving a new simple model with specified _id type', function (t) {
const SimpleModelNumID = ko.Model('ko_db_test_save_simple_numid', {
_id: ko.Number,
string: ko.String,
})
SimpleModelNumID.create({_id: 1, string: 'nice'}).save().then(simple => {
t.deepEqual(simple, {

@@ -26,5 +36,5 @@ _id: 1,

}, 'Instance uses assigned _id when specified and contains data')
return SimpleModel.count({})
return SimpleModelNumID.count({})
}).then(count => {
t.equal(count, 2, 'Count incremented after creation')
t.equal(count, 1, 'Count incremented after creation')
t.end()

@@ -39,2 +49,3 @@ }).catch(err => {

const SimpleModelFail = ko.Model('ko_db_test_save_simple_fail', {
_id: ko.String,
string: ko.String[5],

@@ -50,2 +61,3 @@ number: ko.Number,

t.deepEqual(fields, {
_id: undefined,
string: undefined,

@@ -59,2 +71,3 @@ number: undefined,

return SimpleModelFail.create({
_id: '101',
string: 'too long string',

@@ -100,2 +113,3 @@ number: 0,

const ArrayModel = ko.Model('ko_db_test_save_array', {
_id: ko.String,
array: [ko.Number],

@@ -147,2 +161,3 @@ })

const DocumentModel = ko.Model('ko_db_test_save_document', {
_id: ko.String,
document: {

@@ -202,2 +217,3 @@ field: ko.String,

const ReferencedModel = ko.Model('ko_db_test_save_referenced', {
_id: ko.String,
string: ko.String,

@@ -207,2 +223,3 @@ })

const ModelWithRef = ko.Model('ko_db_test_save_with_ref', {
_id: ko.String,
field: ko.String,

@@ -283,2 +300,3 @@ ref: ReferencedModel,

}).catch(err => {
console.error(err)
t.error(err)

@@ -340,2 +358,3 @@ t.end()

const EmbedModel = ko.Model('ko_db_test_save_embed_only', {
_id: ko.Number,
ref: EmbeddedModel.embedOnly(),

@@ -372,6 +391,7 @@ })

const EmbeddedModel = ko.Model('ko_db_test_save_invalid_embedded_only', {
string: ko.String,
string: ko.String[5],
})
const EmbedModel = ko.Model('ko_db_test_save_invalid_embed_only', {
_id: ko.Number,
ref: EmbeddedModel,

@@ -382,3 +402,3 @@ })

ref: {
string: 1234,
string: '123456',
},

@@ -390,3 +410,3 @@ }).saveAll().then(() => {

t.deepEqual(err, {
ref: { string: 1234 },
ref: { string: '123456' },
}, 'Returned a correct errors object')

@@ -399,6 +419,7 @@ t.end()

const EmbeddedModel = ko.Model('ko_db_test_save_embedded_only', {
string: ko.String,
string: ko.String[5],
})
const EmbedModel = ko.Model('ko_db_test_save_embed_only', {
_id: ko.Number,
ref: EmbeddedModel.embedOnly(),

@@ -409,3 +430,3 @@ })

ref: {
string: 1234,
string: '123456',
},

@@ -417,3 +438,3 @@ }).saveAll().then(() => {

t.deepEqual(err, {
ref: { string: 1234 },
ref: { string: '123456' },
}, 'Returned a correct errors object')

@@ -426,2 +447,3 @@ t.end()

const ReferencedModel = ko.Model('ko_db_test_save_arr_referenced', {
_id: ko.Number,
string: ko.String,

@@ -525,3 +547,3 @@ })

}).catch(err => {
console.log(err)
console.error(err)
t.error(err)

@@ -534,2 +556,3 @@ t.end()

const EmbeddedModel = ko.Model('ko_db_test_save_arr_embedded', {
_id: ko.Number,
string: ko.String,

@@ -539,2 +562,3 @@ })

const EmbedModel = ko.Model('ko_db_test_save_arr_embed', {
_id: ko.Number,
name: ko.String,

@@ -545,6 +569,9 @@ refs: [EmbeddedModel.embed()],

EmbedModel.create({
_id: 12,
name: 'xyz',
refs: [{
_id: 100,
string: '1',
}, {
_id: 101,
string: '2',

@@ -551,0 +578,0 @@ }],

@@ -37,3 +37,3 @@ const test = require('tape')

const ArrPush = ko.Model('ko_db_test_arrayop_push', {
array: [ko.String],
array: [ko.String[10]],
})

@@ -66,7 +66,7 @@

try {
model.array.$push(100)
model.array.$push('too long of a string')
await model.save()
t.fail('Model saved where it should have failed')
} catch (err) {
console.log(err)
//console.log(err)
t.pass('Threw an error when attempting to $push invalid value')

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

const ArrAddToSet = ko.Model('ko_db_test_arrayop_addtoset', {
array: [ko.String],
array: [ko.String[10]],
})

@@ -147,7 +147,7 @@

try {
model.array.$addToSet(100)
model.array.$addToSet('too long of a string')
await model.save()
t.fail('Model saved where it should have failed')
} catch (err) {
console.log(err)
//console.log(err)
t.pass('Threw an error when attempting to $addToSet invalid value')

@@ -192,3 +192,3 @@ }

} catch (err) {
console.log(err)
//console.log(err)
t.pass('Model would not save an empty array')

@@ -195,0 +195,0 @@ }

@@ -6,4 +6,4 @@ const test = require('tape')

const ArrayModel = ko.Model('ko_db_test_proxyset_arr', {
array: [ko.String],
arraysArray: [[ko.Number]],
array: [ko.String[10]],
arraysArray: [[ko.Number.max(100)]],
})

@@ -41,10 +41,19 @@

try {
model.array[0] = 123
model.array[0] = 'way too long of a string'
await model.save()
t.fail('Model saved where it should have failed')
} catch (err) {
console.log(err)
//console.log(err)
t.pass('Did not save an invalid field')
}
try {
model.arraysArray[0][0] = 100000
await model.save()
t.fail('Model saved where it should have failed')
} catch (err) {
//console.log(err)
t.pass('Did not save an invalid field')
}
t.end()

@@ -51,0 +60,0 @@ })

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc