Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

jsonapi-server

Package Overview
Dependencies
Maintainers
5
Versions
69
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jsonapi-server - npm Package Compare versions

Comparing version 2.1.0 to 2.2.0

example/handlers/tupleHandler.js

4

CHANGELOG.md

@@ -0,1 +1,5 @@

- 2016-11-07 - v2.2.0
- 2016-11-07 - Adding polymorphic relationships
- 2016-11-07 - Correctly handle validation errors when including non-existant resources
- 2016-11-07 - Added Array Joi type for GraphQL
- 2016-09-29 - v2.1.0

@@ -2,0 +6,0 @@ - 2016-09-29 - Enable injection of an Express Router

@@ -27,2 +27,4 @@ const jsonApi = require('../../.')

.example(false),
tags: jsonApi.Joi.array().items(jsonApi.Joi.string())
.description('Tags for the photo'),
photographer: jsonApi.Joi.one('people')

@@ -44,2 +46,3 @@ .description('The person who took the photo'),

raw: true,
tags: ['neo', 'morpheus'],
photographer: { type: 'people', id: 'ad3aa89e-9c5b-4ac9-a652-6670f9f27587' }

@@ -54,2 +57,3 @@ },

width: 60,
tags: ['galapagos', 'emperor'],
photographer: { type: 'people', id: 'd850ea75-4427-4f81-8595-039990aeede5' }

@@ -64,2 +68,3 @@ },

width: 350,
tags: ['black', 'green'],
photographer: { type: 'people', id: 'ad3aa89e-9c5b-4ac9-a652-6670f9f27587' }

@@ -66,0 +71,0 @@ }

@@ -5,2 +5,3 @@ 'use strict'

const graphQl = require('graphql')
const readTypes = require('./readTypes.js')

@@ -20,2 +21,16 @@ joiConverter.simpleAttribute = joiScheme => {

if (type === 'array') {
if (joiScheme._inner.items.length === 1) {
let joinSubType = joiConverter.simpleAttribute(joiScheme._inner.items[0])
if (!joinSubType) {
throw new Error('Unable to parse Joi type, got ' + JSON.stringify(joiScheme))
}
return new graphQl.GraphQLList(graphQl.GraphQLString)
} else {
throw new Error('Joi arrays must contain a single type')
}
}
const uType = type[0].toUpperCase() + type.substring(1)

@@ -35,3 +50,4 @@ type = graphQl[`GraphQL${uType}`]

} else {
const otherType = joiScheme._settings.__one || joiScheme._settings.__many
let otherType = joiScheme._settings.__one || joiScheme._settings.__many
otherType = otherType.join(readTypes.UNION_JOIN_CONST)
type = graphQlResources[otherType]

@@ -38,0 +54,0 @@

@@ -8,12 +8,18 @@ 'use strict'

const filterArgs = require('./filterArgs.js')
const UNION_JOIN_CONST = '_PluS_'
readTypes.UNION_JOIN_CONST = UNION_JOIN_CONST
readTypes.generate = allResourceConfig => {
const allReadTypes = { }
const allUnionTypes = [ ]
Object.keys(allResourceConfig).forEach(resource => {
allReadTypes[resource] = readTypes.createReadType(allResourceConfig[resource], allReadTypes)
allReadTypes[resource] = readTypes.createReadType(allResourceConfig[resource], allReadTypes, allUnionTypes)
})
allUnionTypes.forEach(unionType => {
allReadTypes[unionType] = readTypes.createUnionType(unionType, allReadTypes)
})
return allReadTypes
}
readTypes.createReadType = (resourceConfig, otherTypes) => {
readTypes.createReadType = (resourceConfig, otherTypes, allUnionTypes) => {
const someType = {

@@ -42,3 +48,5 @@ name: resourceConfig.resource,

const otherResource = joiScheme._settings.__one || joiScheme._settings.__many
fields[attribute].args = filterArgs.generate(otherResource)
if (otherResource.length === 1) {
fields[attribute].args = filterArgs.generate(otherResource)
}
}

@@ -50,3 +58,24 @@ })

Object.keys(resourceConfig.attributes).forEach(attribute => {
const joiScheme = resourceConfig.attributes[attribute]
if (!joiScheme._settings) return
const otherResource = joiScheme._settings.__one || joiScheme._settings.__many
if (otherResource.length <= 1) return
const unionType = otherResource.join(UNION_JOIN_CONST)
if (allUnionTypes.indexOf(unionType) !== -1) return
allUnionTypes.push(unionType)
})
return new graphQl.GraphQLObjectType(someType)
}
readTypes.createUnionType = (unionType, allReadTypes) => {
let graphQlTypes = unionType.split(UNION_JOIN_CONST).map(a => allReadTypes[a])
return new graphQl.GraphQLUnionType({
name: unionType,
types: graphQlTypes,
resolveType: function (value) {
return graphQlTypes[unionType.split(UNION_JOIN_CONST).indexOf(value.type)]
}
})
}

4

lib/graphQl/resolvers.js

@@ -87,3 +87,3 @@ 'use strict'

[].concat(data.relationships[attribute].data).forEach(relation => {
relation.type = joiSchema._settings.__one || joiSchema._settings.__many
relation.type = (joiSchema._settings.__one || joiSchema._settings.__many)[0]
})

@@ -99,3 +99,3 @@ }

const combined = [].concat.apply([], arrays)
let fields = combined.map(thing => thing.name.value)
let fields = combined.map(thing => (thing.name || { }).value).filter(a => a)
fields = fields.join(',')

@@ -102,0 +102,0 @@ return fields

@@ -14,18 +14,23 @@ 'use strict'

}
Joi.one = resource => {
if (typeof resource !== 'string') throw new Error('Expected a string when defining a primary relation via .one()')
const obj = Joi.alternatives().try(
Joi.any().valid(null), // null
ourJoi._joiBase(resource)
)
Joi.one = function () {
const resources = Array.prototype.slice.call(arguments)
resources.forEach(resource => {
if (typeof resource !== 'string') throw new Error('Expected a string when defining a primary relation via .one()')
})
const obj = Joi.alternatives().try([
Joi.any().valid(null) // null
].concat(resources.map(ourJoi._joiBase)))
obj._settings = {
__one: resource
__one: resources
}
return obj
}
Joi.many = resource => {
if (typeof resource !== 'string') throw new Error('Expected a string when defining a primary relation via .many()')
const obj = Joi.array().items(ourJoi._joiBase(resource))
Joi.many = function () {
const resources = Array.prototype.slice.call(arguments)
resources.forEach(resource => {
if (typeof resource !== 'string') throw new Error('Expected a string when defining a primary relation via .one()')
})
const obj = Joi.array().items(resources.map(ourJoi._joiBase))
obj._settings = {
__many: resource
__many: resources
}

@@ -45,3 +50,3 @@ return obj

obj._settings = {
__one: config.resource,
__one: [ config.resource ],
__as: config.as

@@ -55,3 +60,3 @@ }

obj._settings = {
__many: config.resource,
__many: [ config.resource ],
__as: config.as

@@ -58,0 +63,0 @@ }

@@ -39,5 +39,6 @@ 'use strict'

includePP._arrayToTree = (request, includes, filters, callback) => {
const validationErrors = [ ]
const tree = {
_dataItems: null,
_resourceConfig: request.resourceConfig
_resourceConfig: [ ].concat(request.resourceConfig)
}

@@ -51,5 +52,7 @@

let resourceAttribute = node._resourceConfig.attributes[first]
let resourceAttribute = node._resourceConfig.map(resourceConfig => {
return resourceConfig.attributes[first]
}).filter(a => a).pop()
if (!resourceAttribute) {
return callback({
return validationErrors.push({
status: '403',

@@ -63,3 +66,3 @@ code: 'EFORBIDDEN',

if (!resourceAttribute) {
return callback({
return validationErrors.push({
status: '403',

@@ -80,3 +83,3 @@ code: 'EFORBIDDEN',

_dataItems: [ ],
_resourceConfig: jsonApi._resources[resourceAttribute],
_resourceConfig: resourceAttribute.map(a => jsonApi._resources[a]),
_filter: [ ]

@@ -98,2 +101,3 @@ }

if (validationErrors.length > 0) return callback(validationErrors)
return callback(null, tree)

@@ -100,0 +104,0 @@ }

@@ -130,3 +130,3 @@ 'use strict'

if (schemaProperty._settings.__as) {
const relatedResource = schemaProperty._settings.__one || schemaProperty._settings.__many
const relatedResource = (schemaProperty._settings.__one || schemaProperty._settings.__many)[0]
// get information about the linkage - list of ids and types

@@ -133,0 +133,0 @@ // /rest/bookings/relationships/?customer=26aa8a92-2845-4e40-999f-1fa006ec8c63

@@ -57,3 +57,5 @@ 'use strict'

}
request.resourceConfig = jsonApi._resources[relation._settings.__one || relation._settings.__many]
request.resourceConfig = (relation._settings.__one || relation._settings.__many).map(resourceName => {
return jsonApi._resources[resourceName]
})
response = responseHelper._generateResponse(request, resourceConfig, relatedResources)

@@ -60,0 +62,0 @@ if (relatedResources !== null) {

@@ -46,3 +46,3 @@ 'use strict'

for (let i = 0; i < theirs.length; i++) {
if (theirs[i].type !== relationType) {
if (relationType.indexOf(theirs[i].type) === -1) {
return callback({

@@ -49,0 +49,0 @@ status: '403',

@@ -29,7 +29,7 @@ 'use strict'

if (!relation || relation.__as) return false
relation = relation.__many || relation.__one
relation = (relation.__many || relation.__one)[0]
return (jsonApi._resources[relation] && jsonApi._resources[relation].handlers.find)
}).forEach(relationName => {
let relation = resourceConfig.attributes[relationName]
relation = relation._settings.__one || relation._settings.__many
relation = (relation._settings.__one || relation._settings.__many)[0]

@@ -36,0 +36,0 @@ swaggerPaths._addDeepPaths(paths, resourceName, resourceConfig, relationName, relation)

{
"name": "jsonapi-server",
"version": "2.1.0",
"version": "2.2.0",
"description": "A config driven NodeJS framework implementing json:api",

@@ -26,2 +26,3 @@ "keywords": [

"debug": "^2.2.0",
"eslint-plugin-promise": "^3.3.0",
"express": "^4.13.4",

@@ -28,0 +29,0 @@ "express-graphql": "^0.5.4",

@@ -656,2 +656,18 @@ const assert = require('assert')

})
it('should give clean validation errors', done => {
const url = 'http://localhost:16006/rest/articles?include=fdfdds,sdf'
helpers.request({
method: 'GET',
url
}, (err, res, json) => {
assert.equal(err, null)
json = helpers.validateError(json)
assert.equal(res.statusCode, '403', 'Expecting 403 EFORBIDDEN')
assert.equal(json.errors.length, 2, 'Should be 2 errors')
done()
})
})
})

@@ -658,0 +674,0 @@ })

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

describe('Testing jsonapi-server graphql', () => {

@@ -19,2 +18,3 @@ describe('read operations', () => {

width
tags
photographer(firstname: "Rahul") {

@@ -31,2 +31,3 @@ firstname

'width': 60,
'tags': ['galapagos', 'emperor'],
'photographer': null

@@ -37,2 +38,3 @@ },

'width': 350,
'tags': ['black', 'green'],
'photographer': {

@@ -39,0 +41,0 @@ 'firstname': 'Rahul'

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