diff --git a/.gitignore b/.gitignore index 9dab88aa..e4573598 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ node_modules npm-debug.log /.nyc_output/ /coverage/ +.idea/ diff --git a/CHANGELOG.md b/CHANGELOG.md index dfda203f..5bef6aa7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +- 2017-11-02 - v3.3.0 +- 2017-11-02 - support generateId type - 2017-10-21 - v3.2.2 - 2017-10-21 - Report coverage with Coveralls. - 2017-10-21 - Modernise script. diff --git a/documentation/resources.md b/documentation/resources.md index 3e32d3a8..ab75a722 100644 --- a/documentation/resources.md +++ b/documentation/resources.md @@ -97,3 +97,6 @@ url: jsonApi.Joi.string().uri().meta("readonly").description("This attribute can ``` If you look through the example json:api resources in the `/example/resources` folder things should become clearer. + +#### generateId +By default, the server autogenerates a UUID for resources which are created without specifying an ID. To disable this behavior (for example, if the database generates an ID by auto-incrementing), set `generateId` to `false`. If the resource's ID is not a UUID, it is also necessary to specify an `id` attribute with the correct type. See `/examples/resorces/autoincrement.js` for an example of such a resource. diff --git a/example/handlers/autoincrementHandler.js b/example/handlers/autoincrementHandler.js new file mode 100644 index 00000000..5fc73bd1 --- /dev/null +++ b/example/handlers/autoincrementHandler.js @@ -0,0 +1,15 @@ +'use strict' + +const jsonApi = require('../..') + +const chainHandler = new jsonApi.ChainHandler() + +let i = 2 // 1 is used by the example in resources/autoincrement.js +chainHandler.beforeCreate = (request, newResource, callback) => { + // Autoincrement the ID. + // In practice this would actually be handled by the underlying database. + newResource.id = (i++).toString() + callback(null, request, newResource) +} + +module.exports = chainHandler.chain(new jsonApi.MemoryHandler()) diff --git a/example/resources/autoincrement.js b/example/resources/autoincrement.js new file mode 100644 index 00000000..81028bc8 --- /dev/null +++ b/example/resources/autoincrement.js @@ -0,0 +1,26 @@ +'use strict' + +const jsonApi = require('../../.') +const autoincrementHandler = require('../handlers/autoincrementHandler.js') + +jsonApi.define({ + namespace: 'json:api', + resource: 'autoincrement', + description: 'Demonstration of a resource with an auto-incrementing ID', + handlers: autoincrementHandler, + searchParams: { }, + generateId: false, + attributes: { + id: jsonApi.Joi.string(), + name: jsonApi.Joi.string() + .description('The name of the item') + .example('Hello') + }, + examples: [ + { + id: '1', + type: 'autoincrement', + name: 'Foo' + } + ] +}) diff --git a/lib/routes/create.js b/lib/routes/create.js index 5bf51f24..c88fa890 100644 --- a/lib/routes/create.js +++ b/lib/routes/create.js @@ -33,10 +33,8 @@ createRoute.register = () => { callback => { const theirs = request.params.data theirResource = _.assign( - { - id: uuid.v4(), - type: request.params.type - }, + { type: request.params.type }, + (request.resourceConfig.generateId !== false) && { id: uuid.v4() }, theirs.id && { id: theirs.id }, theirs.attributes, { meta: theirs.meta } diff --git a/package-lock.json b/package-lock.json index 8ca7ad86..530f5c57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "jsonapi-server", - "version": "3.2.1", + "version": "3.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 46cca552..dc45a7db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "jsonapi-server", - "version": "3.2.2", + "name": "jsonapi-graphql-server", + "version": "3.3.0", "description": "A config driven NodeJS framework implementing json:api", "keywords": [ "jsonapi", diff --git a/test/post-resource.js b/test/post-resource.js index 5ca18331..f3e8c735 100644 --- a/test/post-resource.js +++ b/test/post-resource.js @@ -201,6 +201,53 @@ describe('Testing jsonapi-server', () => { done() }) }) + describe('creates a resource with non-UUID ID', () => { + let id + + it('works', done => { + const data = { + method: 'post', + url: 'http://localhost:16006/rest/autoincrement', + headers: { + 'Content-Type': 'application/vnd.api+json' + }, + body: JSON.stringify({ + 'data': { + 'type': 'autoincrement', + 'attributes': { + 'name': 'bar' + } + } + }) + } + helpers.request(data, (err, res, json) => { + assert.equal(err, null) + json = helpers.validateJson(json) + + assert.equal(json.data.id, '2') + assert.equal(res.headers.location, `http://localhost:16006/rest/autoincrement/${json.data.id}`) + assert.equal(res.statusCode, '201', 'Expecting 201') + assert.equal(json.data.type, 'autoincrement', 'Should be a autoincrement resource') + id = json.data.id + + done() + }) + }) + + it('new resource is retrievable', done => { + const url = `http://localhost:16006/rest/autoincrement/${id}` + helpers.request({ + method: 'GET', + url + }, (err, res, json) => { + assert.equal(err, null) + json = helpers.validateJson(json) + assert.equal(res.statusCode, '200', 'Expecting 200 OK') + assert.equal(json.included.length, 0, 'Should be no included resources') + done() + }) + }) + }) }) })