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

shelf

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

shelf - npm Package Compare versions

Comparing version 0.1.2 to 2.0.0

.travis.yml

194

index.js

@@ -1,184 +0,52 @@

// Dependencies
var Model = require('./lib/model')
var callsite = require('callsite')
var util = require('./lib/util')
var Metadata = require('./lib/metadata')
var Storage = require('./lib/client')
var redis = require('redis')
'use strict'
// Supported types, minus object and array
// object and arrays have a special check
var supportedTypes = ['string', 'boolean', 'number', 'any']
const Schema = require('./lib/schema')
const Storage = require('./lib/storage')
var shelf
function Shelf (appName, options) {
// TODO handle more options
// options: {
// auth stuff,
// everything you can use on createClient
// }
options = options || {}
var supportedOptions = {
host: options.host || undefined,
port: options.port || undefined
}
this.appName = appName
this.storage = new Storage(supportedOptions)
// Switch the default extend and make
// this extend method public
// exports.extend = this.extend.bind(this)
}
let storage = Storage(options)
Shelf.prototype.extend = function (options) {
options = options || {}
options.prefix = this.appName
function extend (options) {
options = options || {}
options.prefix = appName
options.storage = storage
// Support 'props' and 'properties' naming to define properties for a model
options.props = options.props || options.properties
// Same thing for model's key/keys
options.keys = options.keys || options.key
// Same thing for model's default values
options.defaultValues = options.def || options.defaultValues || {}
options.props = options.props || options.properties
options.keys = options.keys || options.key
// Sane checks
var nameCheck = (!options.name || typeof options.name !== 'string')
var propertiesCheck = (!options.props || Object.keys(options.props).length <= 0)
var keyCheck = (!options.keys || options.keys.length <= 0)
if (nameCheck) {
var stack = callsite()
throw new Error('You need to define a valid name for the model in ' + stack[1].getFileName())
}
if (propertiesCheck) {
throw new Error('Model ' + options.name + ': must have at least one property defined')
}
if (keyCheck) {
throw new Error('Model ' + options.name + ': must have at least one key defined')
}
options.strict = typeof options.strict !== 'undefined' ? options.strict : true
// check if all properties types are supported
for (var k in options.props) {
if (options.props.hasOwnProperty(k)) {
var t
options.props[k] = options.props[k].toLowerCase()
// If its an object or an array
if (util.isObject(options.props[k]) || util.isArray(options.props[k])) {
t = 1
} else {
t = supportedTypes.indexOf(options.props[k].toLowerCase())
}
var type = options.props[k]
if (typeof type !== 'string') {
type = Object.prototype.toString.call(type)
}
// Check if type is supported
if (t < 0) {
throw new Error('Model ' + options.name + ': The type of ' + k + ' property isn\'t supported -> ' + type)
}
if (!options.prefix || typeof options.prefix !== 'string') {
throw new Error('You need to define a valid prefix for the app')
}
}
// Keys check
options.keys.forEach(function (key) {
// keys can only be root properties
if (key.indexOf('.') > 0) {
throw new Error('Model ' + options.name + ': The model\'s keys need to be root properties')
if (!options.name || typeof options.name !== 'string') {
throw new Error('You need to define a valid name for the model')
}
if (!options.props[key]) {
throw new Error('Model ' + options.name + ': The model\'s keys need to be a defined property in Shelf.extend')
if (!options.props.isJoi || options.props._type !== 'object') {
throw new Error('Model ' + options.name + ': must have props defined as a Joi Object Schema')
}
})
options.storage = this.storage
return new Model(options)
}
Shelf.prototype.loadMetadata = function () {
var self = this
var selectDatabase = function (meta) {
self.metadata = meta
// Select the database the app uses
self.storage.select(meta.dbIndex, function () {
// Set ready to true and process the offline queue
self.storage.__client__.on_ready()
})
// Push everything from mountQueue to the
// redis module internal offline_queue
while (self.storage.mountQueue.length > 0) {
self.storage.__client__.offline_queue.push(self.storage.mountQueue.shift())
if (options.props._inner.children.length === 0) {
throw new Error('Model ' + options.name + ': must have at least one property defined')
}
if (!options.keys || options.keys.length <= 0) {
throw new Error('Model ' + options.name + ': must have at least one key defined')
}
// Fire ready event again and
// iterate over offline_queue
// to send all commands that were
// queued
self.storage.__client__.on_ready()
self.storage.mountQueue = null
}
this.storage.once('ready', function () {
// node_redis module secret flags. shhhh!
self.storage.__client__.ready = false
self.storage.__client__.send_anyway = false
var connectionClient = redis.createClient()
// Select database 0 and then get the metadata we need
connectionClient.get(self.appName + ':metadata', function (err, metadata) {
if (err) {
throw err
options.keys.forEach((key) => {
if (key.indexOf('.') > 0) {
throw new Error('Model ' + options.name + ': The model\'s keys need to be root properties')
}
if (!metadata) {
metadata = new Metadata(self.storage)
metadata.build(selectDatabase)
if (!options.props._inner.children.find((child) => child.key === key)) {
throw new Error('Model ' + options.name + ': The model\'s key ' + key + ' need to be a defined property in Shelf.extend')
}
try {
metadata = JSON.parse(metadata)
} catch (e) {
throw e
}
return selectDatabase(metadata)
})
})
}
function appRegister (appName, options) {
shelf = new Shelf(appName, options)
// TODO review the name of this option and
// which state is deafult
options.deploy = options.deploy || 'dedicated'
if (options.deploy === 'dedicated') {
shelf.storage.mountQueue = null
} else {
shelf.loadMetadata()
return Schema(options)
}
return shelf
return {
extend
}
}
// u mad homie?
function defaultExtend () {
throw new Error('First you need to mount the shelf on the wall. Otherwise how would you put books on the shelf?')
}
// Public API
exports.mount = appRegister
exports.extend = defaultExtend
// Export api
module.exports = exports
module.exports = Shelf

@@ -1,13 +0,41 @@

// Dependecies
var nodeUtil = require('util')
var extend = require('xtend')
'use strict'
var util = extend({}, nodeUtil)
const _ = require('lodash')
util.isObject = function (item) {
return Object.prototype.toString.call(item) === '[object Object]'
function Util () {
function keyFn (prefix, name, keys) {
if (!prefix || typeof prefix !== 'string') {
throw new Error('Prefix must be a string')
}
if (!name || typeof name !== 'string') {
throw new Error('Name must be a string')
}
if (!keys || !_.isArray(keys)) {
throw new Error('Keys must be an array')
}
if (keys.length === 0) {
throw new Error('Keys must have values')
}
return function (obj) {
if (!obj || !_.isObject(obj)) {
throw new Error('Invalid object to extract key')
}
let finalKey = prefix + ':' + name + ':'
keys.forEach((key) => {
if (obj[key]) {
finalKey += obj[key] + ':'
} else {
throw new Error('Missing the key ' + key + ' from the keys object')
}
})
return finalKey.slice(0, -1)
}
}
return {
keyFn
}
}
util.generator = require('./util/generator')
module.exports = util
module.exports = Util()
{
"name": "shelf",
"version": "0.1.2",
"version": "2.0.0",
"description": "Redis Object Document Mapper (ODM)",

@@ -8,2 +8,3 @@ "main": "index.js",

"test": "./node_modules/lab/bin/lab --verbose",
"test-cov": "./node_modules/lab/bin/lab --verbose -c",
"lint": "standard --verbose | snazzy"

@@ -13,3 +14,4 @@ },

"pre-commit": [
"lint"
"lint",
"test"
],

@@ -33,2 +35,6 @@ "keywords": [

"email": "j.goncalo.antunes@gmail.com"
},
{
"name": "Pedro Carvalho",
"email": "pedromatosdecarvalho@gmail.com"
}

@@ -38,16 +44,14 @@ ],

"devDependencies": {
"code": "^2.0.1",
"lab": "^7.3.0",
"mocha": "^2.2.5",
"pre-commit": "^1.1.1",
"code": "^2.1.0",
"lab": "^8.2.0",
"pre-commit": "^1.1.2",
"proxyquire": "^1.7.4",
"snazzy": "^2.0.1",
"standard": "^5.2.2"
"standard": "^6.0.4"
},
"dependencies": {
"callsite": "^1.0.0",
"hiredis": "^0.4.1",
"lodash": "^3.10.1",
"redis": "^1.0.0",
"xtend": "^4.0.0"
"joi": "^7.2.3",
"lodash": "^4.3.0",
"redis": "^2.4.2"
}
}

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

# Shelf [WIP]
Shelf is a Object Document Mapper (ODM) for node.js who uses Redis as its store.
![shelf Logo](https://avatars1.githubusercontent.com/u/14891842?v=3&s=200)
Object Document Mapper (ODM) for Node.js who uses Redis as its store.
[![Build Status](https://travis-ci.org/shelf-js/shelf.svg?branch=master)](https://travis-ci.org/shelf-js/shelf)
[![npm version](https://img.shields.io/npm/v/shelf.svg)](https://www.npmjs.com/package/shelf)
# Introduction
If you need to store complex objects do Redis, but don't want to go through the trouble of translating your objects to a key, value store, then Shelf is for you.
Shelf gives you CRUD operation on your objects over Redis, so you can create complex schemas and validate models.
Shelf uses [joi](https://github.com/hapijs/joi) for schema validation.
> If you're using 0.10 or 0.12 node version, please use `shelf@1`. You can also look at the code at the `1.x.x` branch.
# Example
```javascript
const Shelf = require('shelf')
const Joi = require('joi')
const Storage = Shelf('MyApp', {
port: 6379,
host: '127.0.0.1'
})
const MyModel = Storage.extend({
name: 'MySchema',
props: Joi.object().keys({
prop1: Joi.string(),
prop2: Joi.string()
}),
keys: ['prop1']
})
let myModel = MyModel({prop1: 'Hello'})
myModel.save()
```
You can (and should) move your DB connection (Shelf) and Schema (returned by the extend method) to different files to get better readability.
Check the examples for further information.
# Contributing
We use [standard js](https://github.com/feross/standard).
In order to run the tests you should have an Redis instance running locally.

@@ -1,13 +0,158 @@

var Lab = require('lab')
var Code = require('code')
var lab = exports.lab = Lab.script()
var TestSchema = require('./testSchema')
'use strict'
lab.experiment('Model creation', function () {
lab.test('Default values', function (done) {
var test = new TestSchema({prop1: 'Hello'})
Code.expect(test.prop1).to.equal('Hello')
Code.expect(test.prop2).to.equal('World')
const Lab = require('lab')
const Code = require('code')
const lab = exports.lab = Lab.script()
const Shelf = require('../index')
const Joi = require('joi')
lab.experiment('Shelf Init', () => {
lab.test('Empty prefix', (done) => {
let shelfInstance = Shelf(null, {
host: '127.0.0.1',
port: 6379
})
Code.expect(
() => shelfInstance.extend()
).to.throw(Error, 'You need to define a valid prefix for the app')
done()
})
lab.test('Invalid prefix', (done) => {
let shelfInstance = Shelf(123, {
host: '127.0.0.1',
port: 6379
})
Code.expect(
() => shelfInstance.extend()
).to.throw(Error, 'You need to define a valid prefix for the app')
done()
})
lab.test('Empty name', (done) => {
let shelfInstance = Shelf('Test', {
host: '127.0.0.1',
port: 6379
})
Code.expect(
() => shelfInstance.extend({name: null})
).to.throw(Error, 'You need to define a valid name for the model')
done()
})
lab.test('Invalid name', (done) => {
let shelfInstance = Shelf('Test', {
host: '127.0.0.1',
port: 6379
})
Code.expect(
() => shelfInstance.extend({name: 123})
).to.throw(Error, 'You need to define a valid name for the model')
done()
})
lab.test('Invalid Props', (done) => {
let shelfInstance = Shelf('Test', {
host: '127.0.0.1',
port: 6379
})
Code.expect(
() => shelfInstance.extend({name: '123', props: {isJoi: false}})
).to.throw(Error, 'Model 123: must have props defined as a Joi Object Schema')
done()
})
lab.test('Invalid Props', (done) => {
let shelfInstance = Shelf('Test', {
host: '127.0.0.1',
port: 6379
})
Code.expect(
() => shelfInstance.extend({name: '123', props: {isJoi: true, _type: 'array'}})
).to.throw(Error, 'Model 123: must have props defined as a Joi Object Schema')
done()
})
lab.test('Invalid Props', (done) => {
let shelfInstance = Shelf('Test', {
host: '127.0.0.1',
port: 6379
})
Code.expect(
() => shelfInstance.extend({name: '123', props: Joi.object().keys({})})
).to.throw(Error, 'Model 123: must have at least one property defined')
done()
})
lab.test('Invalid Props', (done) => {
let shelfInstance = Shelf('Test', {
host: '127.0.0.1',
port: 6379
})
Code.expect(
() => shelfInstance.extend({name: '123', props: Joi.object().keys({prop1: Joi.string()})})
).to.throw(Error, 'Model 123: must have at least one key defined')
done()
})
lab.test('Invalid Props', (done) => {
let shelfInstance = Shelf('Test', {
host: '127.0.0.1',
port: 6379
})
Code.expect(
() => shelfInstance.extend({
name: '123',
props: Joi.object().keys({prop1: Joi.string()}),
keys: ['prop1.name2']
})
).to.throw(Error, 'Model 123: The model\'s keys need to be root properties')
done()
})
lab.test('Invalid Props', (done) => {
let shelfInstance = Shelf('Test', {
host: '127.0.0.1',
port: 6379
})
Code.expect(
() => shelfInstance.extend({
name: '123',
props: Joi.object().keys({prop1: Joi.string()}),
keys: ['prop2']
})
).to.throw(Error, 'Model 123: The model\'s key prop2 need to be a defined property in Shelf.extend')
done()
})
lab.test('OK', (done) => {
let shelfInstance = Shelf('Test')
shelfInstance.extend({
name: '123',
props: Joi.object().keys({prop1: Joi.string()}),
keys: ['prop1']
})
done()
})
})
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