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

multicolour-hapi-jsonapi

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

multicolour-hapi-jsonapi - npm Package Compare versions

Comparing version 0.1.3 to 0.2.1

.travis.yml

109

index.js

@@ -6,2 +6,3 @@ "use strict"

const waterline_joi = require("waterline-joi")
const handlers = require("multicolour/lib/handlers")

@@ -67,2 +68,97 @@ /**

generate_related_resource_routes(server, multicolour) {
// Get the collections.
const collections = multicolour.get("database").get("models")
// Get the models that have associations.
const models = Object.keys(collections)
.filter(model_name => !collections[model_name].meta.junctionTable)
.map(model_name => collections[model_name])
// Get the headers.
const headers = joi.object(multicolour.request("header_validator").get())
.options({ allowUnknown: true })
models.forEach(model => {
// Clone the attributes to prevent
// any accidental overriding/side affects.
const attributes = clone_attributes(model._attributes)
// Save typing later.
const name = model.adapter.identity
// Get any relationships this model has.
const model_relationships = Object.keys(attributes)
.filter(attribute_name => model._attributes[attribute_name].model || model._attributes[attribute_name].collection)
// Maps the relationship name back to the relevant
// model in the collections array.
const relationship_to = {}
model_relationships.forEach(relationship_name => {
const related_model = collections[model._attributes[relationship_name].model || model._attributes[relationship_name].collection]
relationship_to[relationship_name] = related_model
})
// Route those relationships.
server.route(
model_relationships.map(relationship_name => {
let query_key = model._attributes[relationship_name].model ? "id" : name
return {
method: "GET",
path: `/${name}/{${query_key}}/relationships/${relationship_name}`,
config: {
// auth: this.get_auth_config(),
handler: (request, reply) => {
// Merge the params into the query string params.
request.url.query = require("util")._extend(request.url.query, request.params)
// Call the handler.
if (query_key === "id") {
return handlers.GET.call(model, request, (err, models) => {
if (err) {
/* istanbul ignore next */
reply[this.get("decorator_name")](err, model)
}
else {
// Get the ids of the related models.
const ids = models.map(model => model[relationship_name] && model[relationship_name].id)
// Get them.
relationship_to[relationship_name]
.find({ id: ids })
.populateAll()
.exec((err, models) =>
reply[this.get("decorator_name")](models.map(model => model.toJSON()), relationship_to[relationship_name]))
}
})
}
else {
return handlers.GET.call(relationship_to[relationship_name], request, (err, models) =>
reply[this.get("decorator_name")](err || models, relationship_to[relationship_name])
)
}
},
description: `Get ${relationship_name} related to ${name}.`,
notes: `Get ${relationship_name} related to ${name}.`,
tags: ["api", "relationships"],
validate: {
headers,
params: joi.object({
[query_key]: joi.string().required()
})
},
response: {
schema: this.get_response_schema(relationship_to[relationship_name]).meta({
className: `related_${relationship_name}`
})
}
}
}
})
)
})
}
/**

@@ -176,3 +272,6 @@ * Get the read only schema for a collection.

const name = this.get("decorator_name")
const multicolour = generator.request("host")
handlers.set_host(multicolour)
// Register with the server some properties it requires.

@@ -200,2 +299,12 @@ Multicolour_Server_Hapi

// Register related resource endpoints
// once the database has been started
// and before the http server is started.
multicolour.on("server_starting", () =>
this.generate_related_resource_routes(
server,
multicolour
)
)
// Listen for replies so we can transform any boom

@@ -202,0 +311,0 @@ // responses to be JSON API compliant.

9

package.json
{
"name": "multicolour-hapi-jsonapi",
"version": "0.1.3",
"version": "0.2.1",
"description": "JSON API reply decorator built on Waterline and waterline-jsonapi",

@@ -33,9 +33,10 @@ "main": "index.js",

"eslint": "^1.5.1",
"istanbul": "^0.3.22",
"istanbul": "^0.4.2",
"joi": "^7.0.0",
"multicolour": "^0.2.9",
"multicolour-seed": "0.0.4",
"multicolour-server-hapi": "^1.0.12",
"sails-memory": "^0.10.5",
"tap-spec": "^4.1.0",
"tape": "^4.2.0",
"multicolour": "^0.1.8"
"tape": "^4.2.0"
},

@@ -42,0 +43,0 @@ "dependencies": {

# multicolour-hapi-jsonapi
JSON API reply decorator built on Waterline and waterline-jsonapi
[![Join the chat at https://gitter.im/newworldcode/multicolour](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/newworldcode/multicolour?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Coverage Status](https://coveralls.io/repos/github/Multicolour/multicolour-hapi-jsonapi/badge.svg?branch=master)](https://coveralls.io/github/Multicolour/multicolour-hapi-jsonapi?branch=master)
[![Build Status](https://travis-ci.org/Multicolour/multicolour-hapi-jsonapi.svg?branch=master)](https://travis-ci.org/Multicolour/multicolour-hapi-jsonapi)
[![Code Climate](https://codeclimate.com/github/Multicolour/multicolour-hapi-jsonapi/badges/gpa.svg)](https://codeclimate.com/github/Multicolour/multicolour-hapi-jsonapi)
`npm i --save multicolour-hapi-jsonapi`
JSON API reply decorator built on Waterline and waterline-jsonapi to make all responses JSONAPI compliant.
MIT license
[Contributing](./CONTRIBUTING.md)

@@ -9,2 +9,8 @@ "use strict"

const relations = {
pet: [ "owners" ],
collar: [ "pet" ],
person: [ "user" ]
}
// Set up a dummy service.

@@ -42,3 +48,13 @@ const service = new Multicolour({

service.get("server").generate_routes()
service.trigger("server_starting")
// Run the test with a helpful name.
tape(`Error "generate_payload" functional tests.`, test => {
const entity = service.get("server").get("validator")
test.throws(entity.generate_payload, TypeError, "Throws when incorrectly called without data or collection.")
test.throws(() => entity.generate_payload({ isBoom: true }, ontology.user), TypeError, "Throws when incorrectly called without data or collection.")
test.throws(() => entity.generate_payload({ isBoom: false, is_error: false }), TypeError, "Throws when incorrectly called without error payload or collection.")
test.end()
})
// Loop over the payloads.

@@ -53,4 +69,3 @@ Object.keys(reply_payloads).forEach(test_name => {

// Run the test with a helpful name.
tape(`GET /${test_name} test collection.`, test => {
// Create a request to the server without starting it.
tape(`GET /${test_name}.`, test => {
hapi.inject(options, response => {

@@ -63,4 +78,19 @@ test.equal(response.statusCode, 200, "Response code should be 200")

if (relations[test_name].length > 0) {
tape(`GET /${test_name}/1/relationships tests`, test => {
test.plan(relations[test_name].length)
relations[test_name].forEach(relation => {
hapi.inject({
url: `/${test_name}/1/relationships/${relation}`,
method: "GET",
headers
}, response => {
test.equal(response.statusCode, 200, `GET /${test_name}/1/relationships/${relation}: Response code should be 200`)
// test.equal(joi.validate(JSON.parse(response.payload), reply_payloads[test_name]).error, null, "Payload validation should have no errors.")
})
})
})
}
tape("Test error response", test => {
// Create a request to the server without starting it.
hapi.inject(`/${test_name}`, response => {

@@ -67,0 +97,0 @@ test.equal(response.statusCode, 400, "Response code should be 400")

@@ -8,13 +8,6 @@ "use strict"

name: "string",
// Add a reference to User.
owner: {
collection: "user"
},
// Add a reference to Collar.
collar: {
model: "collar"
owners: {
collection: "person"
}
}
}

@@ -10,18 +10,41 @@ "use strict"

.then(() => {
ontology.collections.pet.create([
ontology.collections.person.create([
{
breed: "beagle",
type: "dog",
name: "Astro",
owner: 1
name: "Nikola Tesla",
age: 27,
user: 1
},
{
breed: "beagle",
type: "dog",
name: "Cosmo",
owner: 1
name: "Marconi",
age: 27,
user: 1
}
])
.then(callback)
.then(() => {
ontology.collections.pet.create([
{
breed: "beagle",
type: "dog",
name: "Astro"
},
{
breed: "beagle",
type: "dog",
name: "Cosmo"
}
])
.then(() => {
ontology.collections.pet
.find({})
.exec((err, pets) => {
pets.forEach(pet => {
pet.owners.add(1)
pet.owners.add(2)
pet.save(() => {})
})
})
})
.then(callback)
})
})
}

@@ -13,2 +13,3 @@ "use strict"

// USER
const user_schema = joi.object({

@@ -22,2 +23,3 @@ id: joi.string().required(),

requires_email: joi.boolean(),
role: joi.string(),
createdAt: joi.date(),

@@ -28,9 +30,10 @@ updatedAt: joi.date()

const pet_schema = joi.object({
// PERSON
const person_schema = joi.object({
id: joi.string().required(),
type: joi.string().required(),
attributes: joi.object({
breed: joi.string().required(),
type: joi.string().required(),
name: joi.string().required(),
age: joi.number().required(),
user: joi.number(),
createdAt: joi.date(),

@@ -40,3 +43,3 @@ updatedAt: joi.date()

relationships: joi.object({
owner: joi.object({
user: joi.object({
data: joi.object({

@@ -50,15 +53,42 @@ type: joi.string().required(),

// Export schemas.
// PET
const pet_schema = joi.object({
id: joi.string().required(),
type: joi.string().required(),
attributes: joi.object({
breed: joi.string().required(),
type: joi.string().required(),
name: joi.string().required(),
createdAt: joi.date(),
updatedAt: joi.date()
}),
relationships: joi.object({
owners: joi.object({
data: joi.alternatives().try(
joi.object({
type: joi.string().required(),
id: joi.string().required()
}),
joi.array().items(joi.object({
type: joi.string().required(),
id: joi.string().required()
}))
)
})
})
})
// EXPORT SCHEMAS.
module.exports = {
pet: joi.alternatives().try(
joi.object({
data: joi.array().items(pet_schema),
included: joi.array().items(user_schema)
data: joi.alternatives().try(pet_schema, joi.array().items(pet_schema)),
included: joi.array().items(person_schema)
}),
errors
),
user: joi.alternatives().try(
person: joi.alternatives().try(
joi.object({
data: user_schema,
included: joi.array()
data: joi.alternatives().try(person_schema, joi.array().items(person_schema)),
included: joi.array().items(user_schema)
}),

@@ -65,0 +95,0 @@ errors

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