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

jammin

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jammin - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2

lib/api.js

102

index.js

@@ -1,101 +0,1 @@

var Mongoose = require('mongoose');
var Express = require('express');
var BodyParser = require('body-parser');
var SELECT = '-_id -__v'
var FIELDS = {};
SELECT.split(' ').forEach(function(field) {
if (field.indexOf('-') === 0) {
FIELDS[field.substring(1)] = false;
} else {
FIELDS[field] = true;
}
})
var API = function(options) {
if (typeof options === 'string') options = {databaseURL: options};
this.router = Express.Router();
this.router.use(BodyParser.json());
this.mongoose = Mongoose.createConnection(options.databaseURL);
}
module.exports = API;
var Definition = function(api, label, schema) {
this.api = api;
this.db = api.mongoose.model(label, schema);
}
API.Schema = Mongoose.Schema;
API.prototype.define = function(label, schema) {
// TODO: add schema to swagger
if (Object.keys(this).indexOf(label) !== -1) {
throw new Error("Invalid label " + label + "\nLabel is restricted or already defined")
}
this[label] = new Definition(this, label, schema);
}
var getRouteFunction = function(method, many) {
return function() {
var self = this;
arguments = Array.prototype.slice.call(arguments);
var path = arguments[0];
var expressPath = path.replace(/{(.*)}/g, ':$1');
var middleware = arguments.splice(1, arguments.length);
var options = typeof middleware[0] === 'object' ? middleware.shift() : {};
// TODO: add endpoint to swagger
var dbAction = function(req, res, next) {
var query = req.query;
for (key in req.params) {
query[key] = req.params[key];
}
if (method === 'get') {
var find = many ? self.db.find : self.db.findOne;
find.apply(self.db, [query, SELECT]).exec(function(err, thing) {
if (err) res.status(500).json({error: err.toString()})
else if (!thing) res.status(404).json({error: 'Not Found'})
else res.json(thing);
})
} else if (method === 'post') {
var docs = many ? req.body : [req.body];
self.db.collection.insert(docs, function(err, docs) {
if (err) res.status(500).json({error: err.toString()})
else res.json({success: true})
})
} else if (method === 'put') {
if (many) {
self.db.update(query, req.body, {multi: true}).select(SELECT).exec(function(err) {
if (err) res.status(500).json({error: err.toString()});
else res.json({success: true});
})
} else {
self.db.findOneAndUpdate(query, req.body, {new: true}).select(SELECT).exec(function(err, thing) {
if (err) res.status(500).json({error: err.toString()});
else if (!thing) res.status(404).json({error: 'Not Found'});
else res.json(thing);
});
}
} else if (method === 'delete') {
var remove = many ? self.db.remove : self.db.findOneAndRemove;
remove.apply(self.db, [query]).exec(function(err, thing) {
if (err) res.status(500).json({error: err.toString()});
else if (!thing) res.status(404).json({error: 'Not Found'});
else res.json({success: true});
})
}
}
var firstAction = function(req, res, next) {
next();
}
middleware.push(dbAction);
middleware.unshift(firstAction);
middleware.unshift(expressPath);
this.api.router[method].apply(this.api.router, middleware);
}
}
var methods = ['get', 'put', 'post', 'delete'];
methods.forEach(function(method) {
Definition.prototype[method] = getRouteFunction(method);
Definition.prototype[method + 'Many'] = getRouteFunction(method, true)
})
module.exports = require('./lib/api.js');
{
"name": "jammin",
"version": "0.0.1",
"version": "0.0.2",
"description": "REST API Generator using Express and Mongoose",
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/lucybot/jammin.git"
},
"dependencies": {
"async": "^0.9.0",
"body-parser": "^1.12.3",

@@ -12,2 +17,3 @@ "express": "^4.12.3",

"devDependencies": {
"async": "^0.9.0",
"chai": "^2.2.0"

@@ -14,0 +20,0 @@ },

## Installation
```npm install jammin```
**Note: Jammin is still in alpha. Not all features have been implemented.**
**Note: Jammin is still in alpha. The API is not stable.**
*Unimplemented features are tagged with ```TODO```*
## About

@@ -23,5 +21,5 @@ Jammin is the fastest way (that I know of) to build a JSON REST API with Node, Express, and MongoDB. It consists of a light-weight wrapper around [Mongoose](http://mongoosejs.com/) for database operations and an [Express](http://expressjs.com/) router to expose HTTP methods. It is fully extensible via middleware to support things like authentication, resource ownership, and complex queries.

API.define('pet', PetSchema);
API.pet.get('/pets/{name}');
API.pet.post('/pets');
API.define('Pet', PetSchema);
API.Pet.get('/pets/{name}');
API.Pet.post('/pets');

@@ -59,10 +57,10 @@ App.use('/api', API);

### PUT
### PATCH
Jammin will use ```req.params``` and ```req.query``` to find an item in the database, and use ```req.body``` to **update that item**.
```js
API.pet.put('/pets/{name}');
API.pet.patch('/pets/{name}');
```
Use ```putMany``` to update every matching item in the database.
Use ```patchMany``` to update every matching item in the database.
```js
API.pet.putMany('/pets');
API.pet.patchMany('/pets');
```

@@ -92,3 +90,3 @@

### Swagger ```TODO```
### Swagger
Serve a [Swagger specification](http://swagger.io) for your API at the specified path. You can use this to document your API via [Swagger UI](https://github.com/swagger-api/swagger-ui) or a [LucyBot portal](https://lucybot.com)

@@ -113,8 +111,7 @@ ```js

```js
var Hash = require('password-hash');
var App = require('express')();
var Jammin = require('jammin');
var DatabaseURL = 'mongodb://<username>:<password>@<mongodb_host>';
var Jammin = require('jammin')
var API = new Jammin({

@@ -129,3 +126,2 @@ databaseURL: DatabaseURL,

// Jammin.Schema is an alias for Mongoose.Schema
var UserSchema = new Jammin.Schema({

@@ -135,37 +131,10 @@ username: {type: String, required: true, unique: true, match: /^\w+$/},

})
var PetSchema = new Jammin.Schema({
id: {type: Number, required: true, unique: true},
name: String,
owner: {type: Jammin.Schema.ObjectId, ref: 'User'},
animalType: String,
imageURLs: [String]
owner: String,
animalType: {type: String, default: 'unknown'}
})
// define is an alias for Mongoose.model
API.define('pet', PetSchema);
API.define('user', UserSchema);
// Gets a pet by id
API.pet.get('/pets/{id}');
// Creates a new user
API.user.post('/user', function(req, res, next) {
req.body.password_hash = Hash.generate(req.body.password);
next();
});
// Searches pets by name
API.pet.getMany('/search/pets', {
swagger: {
parameters: [{name: 'q', in: 'query', type: 'string'}]
}
}, function(req, res, next) {
var userQuery = Util._extend({}, req.query);
req.query = {
name: { "$regex": new RegExp(userQuery.q) }
};
next();
})
// Middleware for authenticating the request
var authenticateUser = function(req, res, next) {

@@ -189,17 +158,60 @@ var query = {

// Creates a new pet
API.pet.post('/pets', authenticateUser, function(req, res, next) {
req.body.owner = req.user._id;
API.define('pet', PetSchema);
API.define('user', UserSchema);
// Creates a new user.
API.user.post('/user', function(req, res, next) {
req.body.password_hash = Hash.generate(req.body.password);
next();
});
// Deletes a pet.
API.pet.delete('/pets/{id}', authenticateUser, function(req, res, next) {
// Gets a pet by id.
API.pet.get('/pets/{id}');
// Gets an array of pets that match the query.
API.pet.getMany('/pets');
// Searches pets by name
API.pet.getMany('/search/pets', {
swagger: {
description: "Search all pets by name",
parameters: [
{name: 'q', in: 'query', type: 'string', description: 'Any regex'}
]
}
}, function(req, res, next) {
req.query = {
id: req.params.id,
// By setting 'owner', we ensure the user can only delete his own pets.
owner: req.user._id
name: { "$regex": new RegExp(req.query.q) }
};
next();
})
// Creates one or more new pets.
API.pet.postMany('/pets', authenticateUser, function(req, res, next) {
if (!Array.isArray(req.body)) req.body = [req.body];
req.body.forEach(function(pet) {
pet.owner = req.user.username;
});
next();
});
// Setting req.query.owner will ensure that DB calls only return
// documents owned by the user.
var ensureOwnership = function(req, res, next) {
req.query.owner = req.user.username;
next();
}
// Changes a pet.
API.pet.put('/pets/{id}', authenticateUser, ensureOwnership)
// Changes every pet that matches the query.
API.pet.putMany('/pets', authenticateUser, ensureOwnership)
// Deletes a pet by ID.
API.pet.delete('/pets/{id}', authenticateUser, ensureOwnership);
// Deletes every pet that matches the query.
API.pet.deleteMany('/pets', authenticateUser, ensureOwnership)
App.use('/api', API.router);

@@ -206,0 +218,0 @@ App.listen(3000);

var FS = require('fs');
var Hash = require('password-hash');
var App = require('express')();
App.use(require('cors')());

@@ -10,4 +11,4 @@ module.exports.listen = function(port) {

module.exports.dropAllEntries = function(callback) {
API.pet.db.remove({}, function(err) {
API.user.db.remove({}, function(err) {
API.Pet.db.remove({}, function(err) {
API.User.db.remove({}, function(err) {
callback();

@@ -23,14 +24,25 @@ })

swagger: {
info: {title: 'Pet Store'},
info: {title: 'Pet Store', version: '0.1'},
host: 'api.example.com',
basePath: '/api'
basePath: '/api',
securityDefinitions: {
username: { name: 'username', in: 'header', type: 'string'},
password: { name: 'password', in: 'header', type: 'string'}
},
definitions: {
User: {
properties: {
username: {type: 'string'},
}
},
}
}
});
var UserSchema = new Jammin.Schema({
var UserSchema = {
username: {type: String, required: true, unique: true, match: /^\w+$/},
password_hash: {type: String, required: true},
})
}
var PetSchema = new Jammin.Schema({
var PetSchema = {
id: {type: Number, required: true, unique: true},

@@ -40,3 +52,3 @@ name: String,

animalType: {type: String, default: 'unknown'}
})
}

@@ -47,3 +59,3 @@ var authenticateUser = function(req, res, next) {

};
API.user.db.findOne(query, function(err, user) {
API.User.db.findOne(query, function(err, user) {
if (err) {

@@ -62,7 +74,26 @@ res.status(500).json({error: err.toString()})

API.define('pet', PetSchema);
API.define('user', UserSchema);
var SwaggerLogin = {
swagger: {
security: {username: [], password: []},
}
}
API.define('Pet', PetSchema);
API.define('User', UserSchema);
// Creates a new user.
API.user.post('/user', function(req, res, next) {
API.User.post('/user', {
swagger: {
parameters: [{
name: 'body',
in: 'body',
schema: {
properties: {
username: {type: 'string'},
password: {type: 'string'}
}
}
}]
}
}, function(req, res, next) {
req.body.password_hash = Hash.generate(req.body.password);

@@ -73,9 +104,9 @@ next();

// Gets a pet by id.
API.pet.get('/pets/{id}');
API.Pet.get('/pets/{id}');
// Gets an array of pets that match the query.
API.pet.getMany('/pets');
API.Pet.getMany('/pets');
// Searches pets by name
API.pet.getMany('/search/pets', {
API.Pet.getMany('/search/pets', {
swagger: {

@@ -94,4 +125,10 @@ description: "Search all pets by name",

API.Pet.post('/pets/{id}', SwaggerLogin, authenticateUser, function(req, res, next) {
req.body.owner = req.user.username;
req.body.id = req.params.id;
next();
})
// Creates one or more new pets.
API.pet.postMany('/pets', authenticateUser, function(req, res, next) {
API.Pet.postMany('/pets', SwaggerLogin, authenticateUser, function(req, res, next) {
if (!Array.isArray(req.body)) req.body = [req.body];

@@ -104,27 +141,23 @@ req.body.forEach(function(pet) {

// Changes a pet.
API.pet.put('/pets/{id}', authenticateUser, function(req, res, next) {
// Setting req.query.owner ensures that only the logged-in user's
// pets will be returned by any queries Jammin makes to the DB.
var enforceOwnership = function(req, res, next) {
req.query.owner = req.user.username;
next();
})
}
// Changes a pet.
API.Pet.patch('/pets/{id}', SwaggerLogin, authenticateUser, enforceOwnership);
// Changes every pet that matches the query.
API.pet.putMany('/pets', authenticateUser, function(req, res, next) {
req.query.owner = req.user.username;
next();
})
API.Pet.patchMany('/pets', SwaggerLogin, authenticateUser, enforceOwnership);
// Deletes a pet by ID.
API.pet.delete('/pets/{id}', authenticateUser, function(req, res, next) {
req.query.owner = req.user.username;
next();
});
API.Pet.delete('/pets/{id}', SwaggerLogin, authenticateUser, enforceOwnership);
// Deletes every pet that matches the query.
API.pet.deleteMany('/pets', authenticateUser, function(req, res, next) {
req.query.owner = req.user.username;
next();
})
API.Pet.deleteMany('/pets', SwaggerLogin, authenticateUser, enforceOwnership);
API.swagger('/swagger.json');
App.use('/api', API.router);

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

var FS = require('fs');
var Request = require('request');

@@ -5,2 +6,3 @@ var Expect = require('chai').expect;

var SWAGGER_GOLDEN_FILE = __dirname + '/golden/petstore.swagger.json';
var BASE_URL = 'http://127.0.0.1:3000/api';

@@ -20,3 +22,8 @@

} else {
Expect(body).to.deep.equal(expectedBody);
if (Array.isArray(expectedBody)) {
Expect(body).to.deep.have.members(expectedBody);
Expect(expectedBody).to.deep.have.members(body);
} else {
Expect(body).to.deep.equal(expectedBody);
}
}

@@ -39,9 +46,5 @@ done();

Petstore.listen(3000);
done();
Petstore.dropAllEntries(done);
});
after(function(done) {
Petstore.dropAllEntries(done);
})
it('should allow new users', function(done) {

@@ -91,3 +94,3 @@ Request.post({

Request({
method: 'put',
method: 'patch',
url: BASE_URL + '/pets/42',

@@ -101,3 +104,3 @@ headers: USER_2,

Request({
method: 'put',
method: 'patch',
url: BASE_URL + '/pets/42',

@@ -204,3 +207,3 @@ headers: USER_1,

Request({
method: 'put',
method: 'patch',
url: BASE_URL + '/pets',

@@ -243,2 +246,19 @@ headers: USER_1,

})
it('should serve swagger docs', function(done) {
Request.get({
url: BASE_URL + '/swagger.json',
json: true
}, function(err, res, body) {
Expect(err).to.equal(null);
if (process.env.WRITE_GOLDEN) {
console.log("Writing new golden file!");
FS.writeFileSync(SWAGGER_GOLDEN_FILE, JSON.stringify(body, null, 2));
} else {
var golden = JSON.parse(FS.readFileSync(SWAGGER_GOLDEN_FILE, 'utf8'));
Expect(body).to.deep.equal(golden);
}
done();
})
})
})

Sorry, the diff of this file is not supported yet

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