diff --git a/package.json b/package.json index ff690c6..c739446 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "core-js": "^3.6.5", "dotenv": "^8.2.0", "faker": "^5.5.3", + "jsonapi-serializer": "^3.6.7", "koa": "^2.13.0", "koa-body": "^4.2.0", "koa-ejs": "^4.3.0", diff --git a/src/app.js b/src/app.js index bb62135..3024c18 100644 --- a/src/app.js +++ b/src/app.js @@ -11,6 +11,7 @@ const assets = require('./assets'); const mailer = require('./mailers'); const routes = require('./routes'); const orm = require('./models'); +const api = require('./routes/api'); // App constructor const app = new Koa(); @@ -22,7 +23,7 @@ app.keys = [ 'these secret keys are used to sign HTTP cookies', 'to make sure only this app can generate a valid one', 'and thus preventing someone just writing a cookie', - 'saying he is logged in when it\'s really not', + "saying he is logged in when it's really not", ]; // expose ORM through context's prototype @@ -55,21 +56,31 @@ if (developmentMode) { app.use(koaStatic(path.join(__dirname, '..', 'build'), {})); // expose a session hash to store information across requests from same client -app.use(session({ - maxAge: 14 * 24 * 60 * 60 * 1000, // 2 weeks -}, app)); +app.use( + session( + { + maxAge: 14 * 24 * 60 * 60 * 1000, // 2 weeks + }, + app, + ), +); // flash messages support app.use(koaFlashMessage); // parse request body -app.use(koaBody({ - multipart: true, - keepExtensions: true, -})); +app.use( + koaBody({ + multipart: true, + keepExtensions: true, + }), +); app.use((ctx, next) => { - ctx.request.method = override.call(ctx, ctx.request.body.fields || ctx.request.body); + ctx.request.method = override.call( + ctx, + ctx.request.body.fields || ctx.request.body, + ); return next(); }); @@ -85,5 +96,6 @@ mailer(app); // Routing middleware app.use(routes.routes()); +app.use(api.routes()); module.exports = app; diff --git a/src/routes/api/authors.js b/src/routes/api/authors.js new file mode 100644 index 0000000..935e521 --- /dev/null +++ b/src/routes/api/authors.js @@ -0,0 +1,30 @@ +const KoaRouter = require('koa-router'); +const JSONAPISerializer = require('jsonapi-serializer').Serializer; + +const AuthorSerializer = new JSONAPISerializer('authors', { + attributes: ['firstName', 'lastName', 'birthDate'], + keyForAttribute: 'camelCase', +}); + +const router = new KoaRouter(); + +router.get('api.authors.show', '/:id', async (ctx) => { + const author = await ctx.orm.author.findByPk(ctx.params.id); + if (!author) { + ctx.throw(404, "The author you are looking for doesn't exist"); + } + ctx.body = AuthorSerializer.serialize(author); +}); + +router.post('api.authors.create', '/', async (ctx) => { + try { + const author = ctx.orm.author.build(ctx.request.body); + await author.save({ fields: ['firstName', 'lastName', 'birthDate'] }); + ctx.status = 201; + ctx.body = AuthorSerializer.serialize(author); + } catch (ValidationError) { + ctx.throw(400, 'Bad request'); + } +}); + +module.exports = router; diff --git a/src/routes/api/index.js b/src/routes/api/index.js new file mode 100644 index 0000000..0487e8c --- /dev/null +++ b/src/routes/api/index.js @@ -0,0 +1,8 @@ +const KoaRouter = require('koa-router'); +const authors = require('./authors'); + +const router = new KoaRouter({ prefix: '/api' }); + +router.use('/authors', authors.routes()); + +module.exports = router; diff --git a/yarn.lock b/yarn.lock index 63caace..da8e8dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4573,6 +4573,11 @@ inflation@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/inflation/-/inflation-2.0.0.tgz" +inflected@^1.1.6: + version "1.1.7" + resolved "https://registry.yarnpkg.com/inflected/-/inflected-1.1.7.tgz#c393df6e28472d0d77b3082ec3aa2091f4bc96f9" + integrity sha1-w5PfbihHLQ13swguw6ogkfS8lvk= + inflection@1.12.0: version "1.12.0" resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz" @@ -5539,6 +5544,14 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" +jsonapi-serializer@^3.6.7: + version "3.6.7" + resolved "https://registry.yarnpkg.com/jsonapi-serializer/-/jsonapi-serializer-3.6.7.tgz#18299122e7624d962fadaba16c320da6a7c405c0" + integrity sha512-usScb34T6mB0QK/AxOpXTpE9iB7JW4/CMhREitzeKv9rV5CdZhdVA8F9zIc7Xz9rjbSv98vOXkuO1HRtM0paSg== + dependencies: + inflected "^1.1.6" + lodash "^4.16.3" + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz" @@ -5865,6 +5878,11 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== +lodash@^4.16.3: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + log-symbols@^2.1.0, log-symbols@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz"