Comparing version 0.2.2 to 0.2.3
## 0.2.x | ||
### 0.2.3 | ||
> Note: API change is non-breaking as original call format still works - older version is no longer documented in README. | ||
* Bug fix - hyped should include route level url and api prefix settings | ||
* Improvement - allow specification of default content-type if accept header is "*/*" | ||
* Changed content-type for errors to "text/plain" | ||
### 0.2.2 | ||
@@ -4,0 +12,0 @@ * Improvement - support empty or undefined apiPrefix |
@@ -1,25 +0,2 @@ | ||
var gulp = require( 'gulp' ); | ||
var bg = require( 'biggulp' )( gulp ); | ||
gulp.task( 'coverage', bg.withCoverage() ); | ||
gulp.task( 'coverage-watch', function() { | ||
bg.watch( [ 'coverage' ] ); | ||
} ); | ||
gulp.task( 'show-coverage', bg.showCoverage() ); | ||
gulp.task( 'continuous-test', function() { | ||
return bg.test(); | ||
} ); | ||
gulp.task( 'test-watch', function() { | ||
bg.watch( [ 'continuous-test' ] ); | ||
} ); | ||
gulp.task( 'test', function() { | ||
return bg.testOnce(); | ||
} ); | ||
gulp.task( 'default', [ 'coverage', 'coverage-watch' ], function() {} ); | ||
gulp.task( 'ci', [ 'continuous-test', 'test-watch' ], function() {} ); | ||
var gulp = require( "gulp" ); | ||
require( "biggulp/common-gulp" )( gulp ); |
{ | ||
"name": "hyped", | ||
"version": "0.2.2", | ||
"version": "0.2.3", | ||
"description": "Hypermedia response generation engine", | ||
@@ -15,4 +15,4 @@ "main": "src/index.js", | ||
"devDependencies": { | ||
"autohost": "git://github.com/arobson/autohost.git#next", | ||
"biggulp": "0.*.*", | ||
"autohost": "0.4.x", | ||
"biggulp": "0.2.x", | ||
"chai": "^2.2.0", | ||
@@ -37,4 +37,13 @@ "chai-as-promised": "^5.0.0", | ||
], | ||
"author": "Alex Robson", | ||
"license": "MIT License - http://opensource.org/licenses/MIT", | ||
"author": "LeanKit", | ||
"contributors": [ | ||
{ | ||
"name": "Alex Robson", | ||
"url": "http://nerdventure.io" | ||
} | ||
], | ||
"publishConfig": { | ||
"registry": "https://registry.npmjs.org/" | ||
}, | ||
"license": "MIT", | ||
"bugs": { | ||
@@ -41,0 +50,0 @@ "url": "https://github.com/LeanKit-Labs/hyped/issues" |
@@ -396,8 +396,23 @@ ## hyped | ||
### require( "hyped" )( [resourceList], [defaultToNewest], [includeChildrenInOptions] ) | ||
You can skip passing resource list at all and provide the two booleans in the order specified. | ||
### require( "hyped" )( [resourceList], [config] ) | ||
You can skip passing resource list at all and provide the optional configuration to change default behavior. | ||
__defaultToNewest__: causes hyped to default to the newest available version when one isn't specified | ||
__includeChildrenInOptions__: include child resource actions in the OPTIONS response | ||
The configuration hash can have the following properties: | ||
* __defaultContentType__: which rendering engine to use if the client passes "*/*" in the accept header | ||
* __defaultToNewest__: causes hyped to default to the newest available version when one isn't specified | ||
* __includeChildrenInOptions__: include child resource actions in the OPTIONS response | ||
Here's an example of the config block with defaults shown: | ||
```json | ||
{ | ||
"defaultContentType": "application/json", | ||
"defaultToNewest": false, | ||
"includeChildrenInOptions": false | ||
} | ||
``` | ||
> Note: the defaults in place were selected so that consumers unaware of hypermedia or your APIs versioning strategy can use your API like any other HTTP API they have likely encountered. | ||
### addResource( resource, resourceName ) | ||
@@ -404,0 +419,0 @@ Adds the metadata for a particular resource. |
var model = require( "../../model.js" ); | ||
var _ = require( "lodash" ); | ||
@@ -4,0 +3,0 @@ module.exports = function( host ) { |
var model = require( "../../model.js" ); | ||
var _ = require( "lodash" ); | ||
@@ -4,0 +3,0 @@ module.exports = function( host ) { |
var model = require( "../../model.js" ); | ||
var _ = require( "lodash" ); | ||
@@ -4,0 +3,0 @@ module.exports = function( host ) { |
@@ -60,2 +60,2 @@ module.exports = { | ||
} | ||
}; | ||
}; |
@@ -21,3 +21,3 @@ require( "../setup" ); | ||
links: { | ||
"shouldGetOmitted": "/board/:id?WAT" | ||
shouldGetOmitted: "/board/:id?WAT" | ||
} | ||
@@ -24,0 +24,0 @@ } |
@@ -98,3 +98,3 @@ require( "../setup" ); | ||
it( "should be 'quick'", function() { | ||
it( "should be \"quick\"", function() { | ||
elapsed1.should.be.below( limit ); | ||
@@ -101,0 +101,0 @@ elapsed2.should.be.below( limit ); |
@@ -38,3 +38,3 @@ require( "../setup" ); | ||
move: { href: "/card/301/board/{boardId}/lane/{laneId}", method: "PUT", templated: true }, | ||
block: { href: "/card/301/block", method: "PUT" }, | ||
block: { href: "/card/301/block", method: "PUT" } | ||
} | ||
@@ -49,3 +49,3 @@ }, | ||
move: { href: "/card/302/board/{boardId}/lane/{laneId}", method: "PUT", templated: true }, | ||
block: { href: "/card/302/block", method: "PUT" }, | ||
block: { href: "/card/302/block", method: "PUT" } | ||
} | ||
@@ -60,3 +60,3 @@ }, | ||
move: { href: "/card/303/board/{boardId}/lane/{laneId}", method: "PUT", templated: true }, | ||
block: { href: "/card/303/block", method: "PUT" }, | ||
block: { href: "/card/303/block", method: "PUT" } | ||
} | ||
@@ -85,3 +85,3 @@ } | ||
move: { href: "/card/304/board/{boardId}/lane/{laneId}", method: "PUT", templated: true }, | ||
block: { href: "/card/304/block", method: "PUT" }, | ||
block: { href: "/card/304/block", method: "PUT" } | ||
} | ||
@@ -110,3 +110,3 @@ } | ||
move: { href: "/card/305/board/{boardId}/lane/{laneId}", method: "PUT", templated: true }, | ||
block: { href: "/card/305/block", method: "PUT" }, | ||
block: { href: "/card/305/block", method: "PUT" } | ||
} | ||
@@ -121,3 +121,3 @@ }, | ||
move: { href: "/card/306/board/{boardId}/lane/{laneId}", method: "PUT", templated: true }, | ||
block: { href: "/card/306/block", method: "PUT" }, | ||
block: { href: "/card/306/block", method: "PUT" } | ||
} | ||
@@ -124,0 +124,0 @@ } |
@@ -10,3 +10,2 @@ require( "../setup" ); | ||
describe( "Action links", function() { | ||
describe( "With an inheritence hierarchy greater than 2", function() { | ||
@@ -22,4 +21,4 @@ describe( "when creating parentUrls", function() { | ||
}; | ||
var fn = HyperResource.parentFn( resources ); | ||
urlCache = HyperResource.urlCache( resources ); | ||
var fn = HyperResource.parentFn( resources, { urlPrefix: "/test", apiPrefix: "/api" } ); | ||
urlCache = HyperResource.urlCache( resources, { urlPrefix: "/test", apiPrefix: "/api" } ); | ||
parent = fn( "parent", model ); | ||
@@ -103,3 +102,3 @@ child = fn( "child", model ); | ||
}; | ||
var fn = HyperResource.urlFn( resources, "/test/api" ); | ||
var fn = HyperResource.urlFn( resources, { urlPrefix: "/test", apiPrefix: "/api" } ); | ||
parent = fn( "parent", "self", { id: 1 } ); | ||
@@ -135,3 +134,2 @@ children = fn( "parent", "children", { id: 1 } ); | ||
describe( "When getting versions", function() { | ||
var parentVersions, childVersions; | ||
@@ -158,4 +156,3 @@ | ||
describe( "When rendering links from different actions", function() { | ||
describe( "when rendering an 'plain' action", function() { | ||
describe( "when rendering an \"plain\" action", function() { | ||
var expected = { self: { href: "/parent/1", method: "GET" } }; | ||
@@ -243,3 +240,3 @@ var links; | ||
children: { href: "/parent/1/child", method: "GET", parameters: parameters }, | ||
"next-child-page": { href: "/parent/1/child?page=2&size=5", method: "GET", parameters: parameters }, | ||
"next-child-page": { href: "/parent/1/child?page=2&size=5", method: "GET", parameters: parameters } | ||
}; | ||
@@ -277,3 +274,3 @@ var links; | ||
children: { href: "/parent/1/child", method: "GET", parameters: parameters }, | ||
"next-child-page": { href: "/parent/1/child?page=2&size=5", method: "GET", parameters: parameters }, | ||
"next-child-page": { href: "/parent/1/child?page=2&size=5", method: "GET", parameters: parameters } | ||
} | ||
@@ -320,3 +317,3 @@ }; | ||
children: { href: "/parent/1/child", method: "GET", parameters: parameters }, | ||
"next-child-page": { href: "/parent/1/child?page=2&size=5", method: "GET", parameters: parameters }, | ||
"next-child-page": { href: "/parent/1/child?page=2&size=5", method: "GET", parameters: parameters } | ||
} | ||
@@ -358,3 +355,3 @@ }; | ||
before( function() { | ||
var fn1 = HyperResource.resourceFn( resources, "/test/api" ); | ||
var fn1 = HyperResource.resourceFn( resources, { urlPrefix: "/test", apiPrefix: "/api" } ); | ||
@@ -370,3 +367,3 @@ var start = Date.now(); | ||
it( "new should be 'quick'", function() { | ||
it( "new should be \"quick\"", function() { | ||
elapsed.should.be.below( limit ); | ||
@@ -460,3 +457,3 @@ } ); | ||
it( "new should be 'quick'", function() { | ||
it( "new should be \"quick\"", function() { | ||
elapsed.should.be.below( limit ); | ||
@@ -496,3 +493,3 @@ } ); | ||
it( "new should be 'quick'", function() { | ||
it( "new should be \"quick\"", function() { | ||
elapsed.should.be.below( limit ); | ||
@@ -512,4 +509,3 @@ } ); | ||
var halUrl = url.forHal( testUrl ); | ||
for (var i = 0; i < 1000; i++) { | ||
for ( var i = 0; i < 1000; i++ ) { | ||
urls.push( url.process( _.clone( tokens ), halUrl, { id: 1, childId: 2 }, "parent" ) ); | ||
@@ -524,3 +520,3 @@ } | ||
it( "should be 'quick'", function() { | ||
it( "should be \"quick\"", function() { | ||
elapsed.should.be.below( 40 ); | ||
@@ -527,0 +523,0 @@ } ); |
@@ -33,3 +33,3 @@ require( "../setup" ); | ||
move: { href: "/card/301/board/{boardId}/lane/{laneId}", method: "PUT", templated: true }, | ||
block: { href: "/card/301/block", method: "PUT" }, | ||
block: { href: "/card/301/block", method: "PUT" } | ||
} | ||
@@ -42,3 +42,3 @@ }, | ||
move: { href: "/card/302/board/{boardId}/lane/{laneId}", method: "PUT", templated: true }, | ||
block: { href: "/card/302/block", method: "PUT" }, | ||
block: { href: "/card/302/block", method: "PUT" } | ||
} | ||
@@ -51,3 +51,3 @@ }, | ||
move: { href: "/card/303/board/{boardId}/lane/{laneId}", method: "PUT", templated: true }, | ||
block: { href: "/card/303/block", method: "PUT" }, | ||
block: { href: "/card/303/block", method: "PUT" } | ||
} | ||
@@ -72,3 +72,3 @@ } | ||
move: { href: "/card/304/board/{boardId}/lane/{laneId}", method: "PUT", templated: true }, | ||
block: { href: "/card/304/block", method: "PUT" }, | ||
block: { href: "/card/304/block", method: "PUT" } | ||
} | ||
@@ -93,3 +93,3 @@ } | ||
move: { href: "/card/305/board/{boardId}/lane/{laneId}", method: "PUT", templated: true }, | ||
block: { href: "/card/305/block", method: "PUT" }, | ||
block: { href: "/card/305/block", method: "PUT" } | ||
} | ||
@@ -102,3 +102,3 @@ }, | ||
move: { href: "/card/306/board/{boardId}/lane/{laneId}", method: "PUT", templated: true }, | ||
block: { href: "/card/306/block", method: "PUT" }, | ||
block: { href: "/card/306/block", method: "PUT" } | ||
} | ||
@@ -105,0 +105,0 @@ } |
@@ -18,4 +18,4 @@ require( "../setup" ); | ||
links: { | ||
"favstarred": "/board/:id?favstarred=true", | ||
"worstever": "/board/:id?h8=true", | ||
favstarred: "/board/:id?favstarred=true", | ||
worstever: "/board/:id?h8=true", | ||
"next-page": function( data, context ) { | ||
@@ -77,3 +77,3 @@ return "/board/:id?page=" + ( context.page + 1 ) + "&size=" + context.size; | ||
it( "should be 'quick'", function() { | ||
it( "should be \"quick\"", function() { | ||
elapsedMs.should.be.below( limit ); | ||
@@ -83,7 +83,8 @@ } ); | ||
describe( "with resource prefix", function() { | ||
describe( "with resource prefixes", function() { | ||
var elapsedMs; | ||
var resource = { | ||
name: "board", | ||
urlPrefix: "/prefix", | ||
urlPrefix: "/prefix1", | ||
apiPrefix: "/prefix2", | ||
actions: { | ||
@@ -95,4 +96,4 @@ self: { | ||
links: { | ||
"favstarred": "/board/:id?favstarred=true", | ||
"worstever": "/board/:id?h8=true", | ||
favstarred: "/board/:id?favstarred=true", | ||
worstever: "/board/:id?h8=true", | ||
"next-page": function( data, context ) { | ||
@@ -115,10 +116,10 @@ return "/board/:id?page=" + ( context.page + 1 ) + "&size=" + context.size; | ||
title: "Test Board", | ||
_origin: { href: "/prefix/board/100", method: "GET" }, | ||
_origin: { href: "/prefix1/prefix2/board/100", method: "GET" }, | ||
_resource: "board", | ||
_action: "self", | ||
_links: { | ||
self: { href: "/prefix/board/100", method: "GET" }, | ||
favstarred: { href: "/prefix/board/100?favstarred=true", method: "GET" }, | ||
worstever: { href: "/prefix/board/100?h8=true", method: "GET" }, | ||
"next-page": { href: "/prefix/board/100?page=2&size=10", method: "GET" } | ||
self: { href: "/prefix1/prefix2/board/100", method: "GET" }, | ||
favstarred: { href: "/prefix1/prefix2/board/100?favstarred=true", method: "GET" }, | ||
worstever: { href: "/prefix1/prefix2/board/100?h8=true", method: "GET" }, | ||
"next-page": { href: "/prefix1/prefix2/board/100?page=2&size=10", method: "GET" } | ||
} | ||
@@ -130,11 +131,11 @@ }; | ||
title: "Test Board", | ||
_origin: { href: "/prefix/board/100", method: "GET" }, | ||
_origin: { href: "/prefix1/prefix2/board/100", method: "GET" }, | ||
_resource: "board", | ||
_action: "self", | ||
_links: { | ||
self: { href: "/prefix/board/100", method: "GET" }, | ||
favstarred: { href: "/prefix/board/100?favstarred=true", method: "GET" }, | ||
worstever: { href: "/prefix/board/100?h8=true", method: "GET" }, | ||
"next-page": { href: "/prefix/board/100?page=3&size=10", method: "GET" }, | ||
"prev-page": { href: "/prefix/board/100?page=1&size=10", method: "GET" } | ||
self: { href: "/prefix1/prefix2/board/100", method: "GET" }, | ||
favstarred: { href: "/prefix1/prefix2/board/100?favstarred=true", method: "GET" }, | ||
worstever: { href: "/prefix1/prefix2/board/100?h8=true", method: "GET" }, | ||
"next-page": { href: "/prefix1/prefix2/board/100?page=3&size=10", method: "GET" }, | ||
"prev-page": { href: "/prefix1/prefix2/board/100?page=1&size=10", method: "GET" } | ||
} | ||
@@ -144,4 +145,4 @@ }; | ||
before( function() { | ||
var fn = HyperResource.renderFn( { board: resource }, { urlPrefix: "/badUrl", apiPrefix: "/badUrl" } ); | ||
var start = Date.now(); | ||
var fn = HyperResource.renderFn( { board: resource } ); | ||
self1 = fn( "board", "self", board1, "", { page: 1, size: 10 } ); | ||
@@ -152,10 +153,13 @@ self2 = fn( "board", "self", board1, "", { page: 2, size: 10 } ); | ||
it( "should generate links correctly", function() { | ||
it( "should generate links correctly for page 1", function() { | ||
self1.should.eql( expectedSelf1 ); | ||
} ); | ||
it( "should generate links correctly for page 2", function() { | ||
self2.should.eql( expectedSelf2 ); | ||
} ); | ||
it( "should be 'quick'", function() { | ||
it( "should be \"quick\"", function() { | ||
elapsedMs.should.be.below( limit ); | ||
} ); | ||
} ); |
@@ -13,3 +13,3 @@ module.exports = { | ||
_links: { | ||
self: { href: "/parent/1/child/1", method: "GET" }, | ||
self: { href: "/parent/1/child/1", method: "GET" } | ||
} | ||
@@ -26,3 +26,3 @@ }, | ||
_links: { | ||
self: { href: "/parent/1/child/2", method: "GET" }, | ||
self: { href: "/parent/1/child/2", method: "GET" } | ||
} | ||
@@ -29,0 +29,0 @@ } |
var resources = { | ||
"parent": { | ||
parent: { | ||
actions: { | ||
@@ -22,6 +22,3 @@ self: { | ||
if ( context && context.page ) { | ||
return "/parent/:id/child?page=" + | ||
( context.page + 1 ) + | ||
"&size=" + | ||
( context.size ); | ||
return "/parent/:id/child?page=" + ( context.page + 1 ) + "&size=" + ( context.size ); | ||
} | ||
@@ -31,3 +28,3 @@ } | ||
parameters: { | ||
"page": function( data, context ) { | ||
page: function( data, context ) { | ||
var limit = 1; | ||
@@ -39,3 +36,3 @@ if ( data && data.children && context ) { | ||
}, | ||
"size": { range: [ 1, 100 ] } | ||
size: { range: [ 1, 100 ] } | ||
} | ||
@@ -52,3 +49,3 @@ } | ||
}, | ||
"child": { | ||
child: { | ||
parent: "parent", | ||
@@ -60,3 +57,3 @@ actions: { | ||
embed: { | ||
"grandChildren": { | ||
grandChildren: { | ||
resource: "grandChild", | ||
@@ -70,3 +67,3 @@ render: "self", | ||
}, | ||
"grandChild": { | ||
grandChild: { | ||
parent: "child", | ||
@@ -73,0 +70,0 @@ resourcePrefix: false, |
@@ -49,3 +49,2 @@ require( "../setup" ); | ||
describe( "when a token has no corresponding model property", function() { | ||
@@ -52,0 +51,0 @@ var template = "/this/is/{derp}/of.stuff"; |
@@ -8,3 +8,2 @@ require( "../setup" ); | ||
describe( "Autohost Integration", function() { | ||
describe( "with oldest version as default", function() { | ||
@@ -23,8 +22,7 @@ var hyped, host; | ||
describe( "when requesting board with no media type", function() { | ||
describe( "when requesting board with any media type", function() { | ||
var body, contentType; | ||
before( function( done ) { | ||
request( "http://localhost:8800/test/api/board/100", function( err, res ) { | ||
request( "http://localhost:8800/test/api/board/100", { headers: { accept: "*/*" } }, function( err, res ) { | ||
body = JSON.parse( res.body ); | ||
@@ -36,5 +34,5 @@ contentType = res.headers[ "content-type" ].split( ";" )[ 0 ]; | ||
it( "should get JSON version 1", function() { | ||
it( "should get JSON version 1 (default content type and version)", function() { | ||
contentType.should.equal( "application/json" ); | ||
body.should.eql( { "id": 100, "title": "Test Board", "lanes": [ { "id": 200, "title": "To Do", "wip": 0, "cards": [ { "id": 301, "title": "Card 1", "description": "This is card 1" }, { "id": 302, "title": "Card 2", "description": "This is card 2" }, { "id": 303, "title": "Card 3", "description": "This is card 3" } ] }, { "id": 201, "title": "Doing", "wip": 0, "cards": [ { "id": 304, "title": "Card 4", "description": "This is card 4" } ] }, { "id": 202, "title": "Done", "wip": 0, "cards": [ { "id": 305, "title": "Card 5", "description": "This is card 5" }, { "id": 306, "title": "Card 6", "description": "This is card 6" } ] } ] } ); | ||
body.should.eql( { id: 100, title: "Test Board", lanes: [ { id: 200, title: "To Do", wip: 0, cards: [ { id: 301, title: "Card 1", description: "This is card 1" }, { id: 302, title: "Card 2", description: "This is card 2" }, { id: 303, title: "Card 3", description: "This is card 3" } ] }, { id: 201, title: "Doing", wip: 0, cards: [ { id: 304, title: "Card 4", description: "This is card 4" } ] }, { id: 202, title: "Done", wip: 0, cards: [ { id: 305, title: "Card 5", description: "This is card 5" }, { id: 306, title: "Card 6", description: "This is card 6" } ] } ] } ); | ||
} ); | ||
@@ -44,5 +42,3 @@ } ); | ||
describe( "when requesting board hal version 2", function() { | ||
var body, contentType, elapsedMs; | ||
var expectedJson = require( "./halBoard2.json" ); | ||
@@ -88,5 +84,3 @@ | ||
describe( "when requesting board hal with no version specifier", function() { | ||
var body, contentType, elapsedMs; | ||
var expectedJson = require( "./halBoard.json" ); | ||
@@ -127,3 +121,3 @@ | ||
status.should.equal( 415 ); | ||
contentType.should.equal( "text/html" ); | ||
contentType.should.equal( "text/plain" ); | ||
body.should.equal( "The requested media type 'application/vnd.baconated+json' is not supported. Please see the OPTIONS at the api root to get a list of supported types." ); | ||
@@ -184,5 +178,3 @@ } ); | ||
describe( "when rendering related list of resources as hal", function() { | ||
var body, contentType, elapsedMs; | ||
var expected = require( "./halCards.json" ); | ||
@@ -209,3 +201,2 @@ | ||
var body, contentType, elapsedMs; | ||
var expectedOptions = require( "./halOptions.json" ); | ||
@@ -264,5 +255,63 @@ | ||
} ); | ||
} ); | ||
after( function() { | ||
host.stop(); | ||
} ); | ||
} ); | ||
describe( "with hal as default content type", function() { | ||
var hyped, host; | ||
before( function( done ) { | ||
hyped = require( "../../src/index.js" )( { | ||
defaultContentType: "application/hal+json" | ||
} ); | ||
host = hyped.createHost( autohost, { | ||
urlPrefix: "/test", | ||
resources: "./spec/ah" | ||
}, function() { | ||
host.start(); | ||
done(); | ||
} ); | ||
} ); | ||
describe( "when requesting board with any media type", function() { | ||
var body, contentType; | ||
var expectedJson = require( "./halBoard.json" ); | ||
before( function( done ) { | ||
request( "http://localhost:8800/test/api/board/100", { headers: { accept: "*/*" } }, function( err, res ) { | ||
body = JSON.parse( res.body ); | ||
contentType = res.headers[ "content-type" ].split( ";" )[ 0 ]; | ||
done(); | ||
} ); | ||
} ); | ||
it( "should get HAL version 1 (default content type and version)", function() { | ||
contentType.should.equal( "application/hal+json" ); | ||
body.should.eql( expectedJson ); | ||
} ); | ||
} ); | ||
describe( "when requesting an unsupported media type", function() { | ||
var body, contentType, elapsedMs, status; | ||
before( function( done ) { | ||
var start = Date.now(); | ||
elapsedMs = ( Date.now() - start ); | ||
request.get( "http://localhost:8800/test/api/board/100", { headers: { accept: "application/vnd.baconated+json" } }, function( err, res ) { | ||
body = res.body; | ||
status = res.statusCode; | ||
contentType = res.headers[ "content-type" ].split( ";" )[ 0 ]; | ||
done(); | ||
} ); | ||
} ); | ||
it( "should get 415", function() { | ||
status.should.equal( 415 ); | ||
contentType.should.equal( "text/plain" ); | ||
body.should.equal( "The requested media type 'application/vnd.baconated+json' is not supported. Please see the OPTIONS at the api root to get a list of supported types." ); | ||
} ); | ||
} ); | ||
after( function() { | ||
@@ -302,3 +351,2 @@ host.stop(); | ||
} ); | ||
} ); | ||
@@ -363,3 +411,2 @@ | ||
} ); | ||
} ); | ||
@@ -394,3 +441,2 @@ | ||
} ); | ||
} ); |
@@ -30,8 +30,2 @@ require( "./setup" ); | ||
function compare( a, b ) { | ||
var diff = []; | ||
deepCompare( a, b, undefined, diff ); | ||
diff.should.eql( [] ); | ||
} | ||
function deepCompare( a, b, k, l ) { | ||
@@ -46,3 +40,3 @@ l = l || []; | ||
} else { | ||
result = a == b; // jshint ignore:line | ||
var result = a == b; // jshint ignore:line | ||
if ( !result ) { | ||
@@ -55,2 +49,8 @@ l.push( k + ": " + a + "!==" + b ); | ||
function compare( a, b ) { | ||
var diff = []; | ||
deepCompare( a, b, undefined, diff ); | ||
diff.should.eql( [] ); | ||
} | ||
module.exports = { | ||
@@ -57,0 +57,0 @@ board1: board1, |
@@ -1,13 +0,13 @@ | ||
var chai = require( 'chai' ); | ||
chai.use( require( 'chai-as-promised' ) ); | ||
var chai = require( "chai" ); | ||
chai.use( require( "chai-as-promised" ) ); | ||
global.should = chai.should(); | ||
global.expect = chai.expect; | ||
var _ = global._ = require( 'lodash' ); | ||
global.when = require( 'when' ); | ||
global.lift = require( 'when/node' ).lift; | ||
global.seq = require( 'when/sequence' ); | ||
global.fs = require( 'fs' ); | ||
global.sinon = require( 'sinon' ); | ||
global.proxyquire = require( 'proxyquire' ).noPreserveCache(); | ||
var sinonChai = require( 'sinon-chai' ); | ||
global._ = require( "lodash" ); | ||
global.when = require( "when" ); | ||
global.lift = require( "when/node" ).lift; | ||
global.seq = require( "when/sequence" ); | ||
global.fs = require( "fs" ); | ||
global.sinon = require( "sinon" ); | ||
global.proxyquire = require( "proxyquire" ).noPreserveCache(); | ||
var sinonChai = require( "sinon-chai" ); | ||
chai.use( sinonChai ); | ||
@@ -17,3 +17,3 @@ | ||
console.log = function() { | ||
if ( typeof arguments[ 0 ] === 'string' && /^[a-zA-Z]/.test( arguments[ 0 ] ) ) { | ||
if ( typeof arguments[ 0 ] === "string" && /^[a-zA-Z]/.test( arguments[ 0 ] ) ) { | ||
return; // swallow this message | ||
@@ -20,0 +20,0 @@ } else { |
@@ -61,2 +61,30 @@ var _ = require( "lodash" ); | ||
function getPrefix( resources, prefix, resource ) { | ||
var urlPrefix = prefix ? prefix.urlPrefix : ""; | ||
var apiPrefix = prefix ? prefix.apiPrefix : ""; | ||
var parentPrefix = {}; | ||
if ( resource.parent ) { | ||
var parentResource = resources[ resource.parent ]; | ||
parentPrefix = getPrefix( resources, prefix, parentResource ); | ||
} | ||
if ( resource.urlPrefix === undefined ) { | ||
urlPrefix = parentPrefix.urlPrefix === undefined ? urlPrefix : parentPrefix.urlPrefix; | ||
} else { | ||
urlPrefix = resource.urlPrefix; | ||
} | ||
if ( resource.apiPrefix === undefined ) { | ||
apiPrefix = parentPrefix.apiPrefix === undefined ? apiPrefix : parentPrefix.apiPrefix; | ||
} else { | ||
apiPrefix = resource.apiPrefix; | ||
} | ||
return { | ||
urlPrefix: urlPrefix, | ||
apiPrefix: apiPrefix | ||
}; | ||
} | ||
function buildParametersFn( action ) { | ||
@@ -98,3 +126,4 @@ // get static parameters | ||
var cache = {}; | ||
var parentUrlFn = getParentUrlFn( resources, prefix, version ); | ||
var parentUrlFn = getParentUrlFn( resources, version ); | ||
var prefixFn = getPrefix.bind( undefined, resources, prefix ); | ||
@@ -106,3 +135,3 @@ _.reduce( resources, function( rAcc, resource, resourceName ) { | ||
var resourceSegment = getResourcePrefix( actionSegment, resource, resourceName ); | ||
var actionUrl = [ resource.urlPrefix, resourceSegment, actionSegment ].join( "" ).replace( "//", "/" ); | ||
var actionUrl = [ resourceSegment, actionSegment ].join( "" ).replace( "//", "/" ); | ||
var templated = isTemplated( actionUrl ); | ||
@@ -121,9 +150,13 @@ var getActionUrl = function() { | ||
function getPrefix( parentUrl, data ) { | ||
return ( parentUrl || parentUrlFn( resourceName, data ) ) || prefix; | ||
function getParentUrl( parentUrl, data ) { | ||
return ( parentUrl || parentUrlFn( resourceName, data ) ) || ""; | ||
} | ||
var resourcePrefix = prefixFn( resource ); | ||
acc[ actionName ] = function( data, parentUrl ) { | ||
var href = [ | ||
getPrefix( parentUrl, data ), | ||
resourcePrefix.urlPrefix, | ||
resourcePrefix.apiPrefix, | ||
getParentUrl( parentUrl, data ), | ||
getActionUrl( data ) | ||
@@ -137,7 +170,14 @@ ].join( "" ).replace( "//", "/" ); | ||
acc[ linkName ] = function( data, parentUrl, context ) { | ||
var href = [ | ||
getPrefix( parentUrl, data ), | ||
linkFn( data, context ) | ||
].join( "" ).replace( "//", "/" ); | ||
return href; | ||
var linkUrl = linkFn( data, context ); | ||
if ( linkUrl ) { | ||
var href = [ | ||
resourcePrefix.urlPrefix, | ||
resourcePrefix.apiPrefix, | ||
getParentUrl( parentUrl, data ), | ||
linkFn( data, context ) | ||
].join( "" ).replace( "//", "/" ); | ||
return href; | ||
} else { | ||
return ""; | ||
} | ||
}; | ||
@@ -257,3 +297,3 @@ } ); | ||
if ( linkUrl ) { | ||
linkUrl = [ resource.urlPrefix, linkUrl ].join( "" ).replace( "//", "/" ); | ||
linkUrl = linkUrl.replace( "//", "/" ); | ||
return isTemplated( linkUrl ) ? | ||
@@ -267,3 +307,3 @@ url.create( linkUrl, data, resourceName ) : | ||
} else { | ||
var halUrl = url.forHal( [ resource.urlPrefix, link ].join( "" ).replace( "//", "/" ) ); | ||
var halUrl = url.forHal( link.replace( "//", "/" ) ); | ||
var templated = isTemplated( halUrl ); | ||
@@ -322,3 +362,3 @@ if ( templated ) { | ||
var method = action.method.toUpperCase(); | ||
acc[ actionName ] = function( data, parentUrl, context, auth ) { | ||
acc[ actionName ] = function( data, parentUrl, context /*, auth */ ) { | ||
var actionUrl = urlFn( resourceName, actionName, data, parentUrl, context ); | ||
@@ -360,4 +400,4 @@ return { href: actionUrl, method: method }; | ||
var parentName = resources[ name ].parent; | ||
var tokens = [], | ||
segments = []; | ||
var tokens = []; | ||
var segments = []; | ||
if ( parentName ) { | ||
@@ -398,3 +438,3 @@ var parent = resources[ parentName ]; | ||
function getParentUrlFn( resources, prefix, version ) { // jshint ignore:line | ||
function getParentUrlFn( resources, version ) { // jshint ignore:line | ||
var cache = getParentUrlCache( resources ); | ||
@@ -406,3 +446,3 @@ return function( resourceName, data ) { | ||
var resourceSegment = getResourcePrefix( meta.url, resources[ parent ], parent ); | ||
var parentUrl = [ prefix, resourceSegment, meta.url ].join( "" ).replace( "//", "/" ); | ||
var parentUrl = [ resourceSegment, meta.url ].join( "" ).replace( "//", "/" ); | ||
var values = _.reduce( tokens, function( acc, token ) { | ||
@@ -434,5 +474,11 @@ var val = url.readToken( resourceName, data, token ); | ||
var linkFn = getLinksFn( resources, prefix, version ); | ||
var prefixFn = getPrefix.bind( undefined, resources, prefix ); | ||
_.reduce( resources, function( rAcc, resource, resourceName ) { | ||
resource = getVersion( resource, version ); | ||
var prefixes = prefixFn( resource ); | ||
var urlPrefix = [ | ||
prefixes.urlPrefix, | ||
prefixes.apiPrefix | ||
].join( "" ).replace( "//", "/" ); | ||
rAcc[ resourceName ] = _.reduce( resource.actions, function( acc, action, actionName ) { | ||
@@ -457,2 +503,3 @@ acc[ actionName ] = function( data, parentUrl, context, originUrl, originMethod, auth ) { | ||
var inheritedUrl = resources[ child.resource ].parent ? body._links.self.href : ""; | ||
inheritedUrl = inheritedUrl.replace( urlPrefix, "" ); | ||
if ( _.isArray( childVal ) ) { | ||
@@ -501,3 +548,3 @@ embed = _.map( childVal, function( x ) { | ||
return function( resourceName, actionName, data, parentUrl, context, originUrl, originMethod, auth ) { | ||
return function( resourceName, actionName, data, parentUrl, context, originUrl, originMethod /*, auth */ ) { | ||
var body = {}; | ||
@@ -533,3 +580,2 @@ var resource = getVersion( resources[ resourceName ], version ); | ||
function getVersion( resource, version ) { // jshint ignore:line | ||
@@ -577,3 +623,5 @@ if ( version === undefined ) { | ||
return function( data, context, auth ) { | ||
return ( canRender( data, context ) && auth( authName, data, context ) ); | ||
var can = canRender( data, context ); | ||
var should = auth( authName, data, context ); | ||
return ( can && should ); | ||
}; | ||
@@ -580,0 +628,0 @@ } |
@@ -93,3 +93,3 @@ var _ = require( "lodash" ); | ||
headers: { | ||
"Content-Type": "text/html" | ||
"Content-Type": "text/plain" | ||
}, | ||
@@ -96,0 +96,0 @@ data: "The requested media type '" + this._contentType + "' is not supported. Please see the OPTIONS at the api root to get a list of supported types." |
@@ -20,8 +20,8 @@ var _ = require( "lodash" ); | ||
if ( host.use ) { | ||
state.prefix = apiPrefix; | ||
host.use( state.apiPrefix, state.optionsMiddleware ); | ||
host.use( state.apiPrefix, state.hyperMiddleware ); | ||
state.prefix = { urlPrefix: "", apiPrefix: apiPrefix }; | ||
host.use( apiPrefix, state.optionsMiddleware ); | ||
host.use( apiPrefix, state.hyperMiddleware ); | ||
} else { | ||
var urlPrefix = host.config.urlPrefix; | ||
if( _.has( host.config, "apiPrefix" ) ) { | ||
if ( _.has( host.config, "apiPrefix" ) ) { | ||
apiPrefix = host.config.apiPrefix === undefined ? "/" : host.config.apiPrefix; | ||
@@ -31,5 +31,12 @@ } else { | ||
} | ||
state.prefix = [ urlPrefix, apiPrefix ].join( "" ).replace( "//", "/" ); | ||
host.http.middleware( state.prefix, state.optionsMiddleware, "options" ); | ||
host.http.middleware( state.prefix, state.hyperMiddleware, "hyped" ); | ||
state.prefix = { | ||
urlPrefix: urlPrefix, | ||
apiPrefix: apiPrefix | ||
}; | ||
var prefixUrl = [ | ||
urlPrefix, | ||
apiPrefix | ||
].join( "" ).replace( "//", "/" ); | ||
host.http.middleware( prefixUrl, state.optionsMiddleware, "options" ); | ||
host.http.middleware( prefixUrl, state.hyperMiddleware, "hyped" ); | ||
} | ||
@@ -142,2 +149,5 @@ } | ||
var contentType = getContentType( req ); | ||
if ( contentType === "*/*" || contentType === undefined ) { | ||
contentType = state.defaultContentType; | ||
} | ||
var engine = getEngine( state, contentType ); | ||
@@ -188,3 +198,4 @@ var hyperModel = getHyperModel( state, req ); | ||
preferLatest: false, | ||
excludeChildren: undefined | ||
excludeChildren: undefined, | ||
defaultContentType: "application/json" | ||
}; | ||
@@ -205,13 +216,27 @@ | ||
urlStrategy: urlStrategy.bind( undefined, state ), | ||
versionWith: setVersioningStrategy.bind( undefined, state ), | ||
versionWith: setVersioningStrategy.bind( undefined, state ) | ||
} ); | ||
if ( resourceList === true || resourceList === false ) { | ||
var config; | ||
if ( _.isBoolean( resourceList ) ) { | ||
state.preferLatest = resourceList; | ||
state.excludeChildren = defaultToNewest === undefined ? true : !defaultToNewest; | ||
} else if ( !_.isArray( resourceList ) ) { | ||
config = resourceList; | ||
} else { | ||
addResources( state, resourceList ); | ||
state.preferLatest = defaultToNewest; | ||
state.excludeChildren = includeChildrenInOptions === undefined ? true : !includeChildrenInOptions; | ||
if ( _.isBoolean( defaultToNewest ) ) { | ||
state.preferLatest = defaultToNewest; | ||
state.excludeChildren = includeChildrenInOptions === undefined ? true : !includeChildrenInOptions; | ||
} else { | ||
config = defaultToNewest; | ||
} | ||
} | ||
if ( config ) { | ||
state.preferLatest = config.defaultToNewest === undefined ? false : config.defaultToNewest; | ||
state.excludeChildren = config.includeChildrenInOptions === undefined ? true : !config.includeChildrenInOptions; | ||
state.defaultContentType = config.defaultContentType || "application/json"; | ||
} | ||
addEngine( state, jsonEngine, "application/json" ); | ||
@@ -218,0 +243,0 @@ addEngine( state, halEngine, "application/hal+json" ); |
@@ -33,3 +33,3 @@ var _ = require( "lodash" ); | ||
var expressUrl = url; | ||
while (( match = braceFind.exec( url ) )) { | ||
while ( ( match = braceFind.exec( url ) ) ) { | ||
expressUrl = expressUrl.replace( match[ 0 ], ":" + match[ 1 ] ); | ||
@@ -43,3 +43,3 @@ } | ||
var expressUrl = url; | ||
while (( match = expressFind.exec( url ) )) { | ||
while ( ( match = expressFind.exec( url ) ) ) { | ||
expressUrl = expressUrl.replace( match[ 0 ], "{" + match[ 1 ] + "}" ); | ||
@@ -54,3 +54,3 @@ } | ||
var pattern = isExpressStyle( url ) ? expressFind : braceFind; | ||
while (( match = pattern.exec( url ) )) { | ||
while ( ( match = pattern.exec( url ) ) ) { | ||
tokenName = match[ 1 ]; | ||
@@ -88,5 +88,5 @@ tokens.push( parseToken( tokenName ) ); | ||
if ( data ) { | ||
value = data[ camel ] | ||
|| ( data[ token.resource ] ? data[ token.resource ][ token.property ] : undefined ) | ||
|| ( resource === token.resource ? data[ token.property ] : undefined ); | ||
value = data[ camel ] || | ||
( data[ token.resource ] ? data[ token.resource ][ token.property ] : undefined ) || | ||
( resource === token.resource ? data[ token.property ] : undefined ); | ||
} | ||
@@ -93,0 +93,0 @@ var empty = value === undefined || value === {}; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
157183
40
3595
636