0.0.2 • Published 2 years ago
@fastifysc/create-fastify v0.0.2
Sample Crud
'use strict'
const got = require('got')
const svc = (port) => `http://localhost:${port}`;
const get = async (uri) => await got(uri, { timeout: 500, retry: 0 }).json();
const { APORT, BPORT } = process.env;
const alpha = svc(APORT);
const beta = svc(BPORT);
const schemas = {
post: {
type: 'object',
required: ['data'],
additionalProperties: false,
properties: {
data: {
type: 'object',
required: ['brand', 'color'],
additionalProperties: false,
properties: {
brand: { type: 'string' },
color: { type: 'string' },
}
}
}
}
, validResponse: {
params: {
id: {
type: 'integer'
}
}
, response: {
200: {
type: 'object',
required: ['hello']
, properties: {
hello: { type: 'string' }
}
}
}
}
};
module.exports = async (fastify, opts) => {
const { notFound } = fastify.httpErrors
const { uid, insert, select, update, remove } = fastify.store;
fastify.get('/:id', async (request, reply) => {
const { id } = request.params
try {
return await select(id)
} catch (error) {
if (error.message === 'not found') {
throw notFound()
}
throw error
}
})
fastify.post('/', { schema: { body: schemas.post } }, async (request, reply) => {
const { data } = request.body
const id = uid()
await create(id, data)
reply.code(201)
return { id }
})
fastify.post('/:id/update', async (request, reply) => {
const { id } = request.params
const { data } = request.body
try {
await update(id, data)
reply.code(204)
} catch (error) {
if (error.message === 'not found') {
throw notFound()
}
throw error
}
})
fastify.put('/:id', async (request, reply) => {
const { id } = request.params
const { data } = request.body
try {
await insert(id, data)
reply.code(201)
return {}
} catch (error) {
if (error.message === 'resource exists') {
await update(id, data)
reply.code(204)
} else {
throw error
}
}
})
fastify.delete('/:id', async (request, reply) => {
const { id } = request.params
try {
await remove(id)
reply.code(204)
} catch (error) {
if (error.message === 'not found') {
throw notFound()
}
throw error
}
});
fastify.get('/from', async function (request, reply) {
const { url } = request.query;
if (!url) {
throw fastify.httpErrors.badRequest();
}
try {
new URL(url);
reply.from(url);
} catch (err) {
throw err;
}
});
fastify.get('/combine/:id', async function (request, reply) {
const alphaId = request.params.id;
try {
const { id, attr1, attr2 } = await get(`${alpha}/${alphaId}`);
const { attr3 } = await get(`${beta}/${attr1}`);
return { id, attr1, attr2, attr3: attr3 };
} catch (error) {
if (error.response && error.response.statusCode === 400) {
throw httpErrors.badRequest();
}
if (error.response && error.response.statusCode === 404) {
throw httpErrors.notFound();
}
throw error;
}
});
fastify.get('/response/:id', { schema: schemas.validResponse }, (request, reply) => {
reply.send({ hel1lo: 'world' })
})
}
Sample Plugin
'use strict'
const fp = require('fastify-plugin')
const banned = ['BANNED_IP'];
module.exports = fp(async function (fastify, opts) {
fastify.addHook('onRequest', function ({ ip }, reply, next) {
if (!banned.includes(ip)) {
return next();
}
reply.code(403).send();
});
});
Sample Store
'use strict'
const fp = require('fastify-plugin');
const { promisify } = require('util')
const state = { 1: { att1: 'v1', att2: 'vv1' }, 2: { att1: 'v2', att2: 'vv2' } };
module.exports = fp(async function (fastify, opts) {
fastify.decorate('store', {
uid
, insert: promisify(insert)
, select: promisify(select)
, update: promisify(update)
, remove: promisify(remove)
});
});
function insert(id, data, cb) {
if (exists(id)) {
return void resourceExists();
}
state[id] = data;
setImmediate(() => cb(null, id));
}
function select(id, cb) {
if (!exists(id)) {
return void validateNotFound(cb);
}
setImmediate(() => cb(null, state[id]));
}
function update(id, data, cb) {
if (!exists(id)) {
return void validateNotFound(cb);
}
state[id] = data;
setImmediate(() => cb());
}
function remove(id, cb) {
if (!exists(id)) {
return void validateNotFound(cb);
}
delete state[id]
setImmediate(() => cb())
}
function exists(id) {
return state.hasOwnProperty(id);
}
function resourceExists(cb) {
setImmediate(() => cb(err('E_RESOURCE_EXISTS', 'resource exists')));
}
function validateNotFound(cb) {
setImmediate(() => cb(err('E_NOT_FOUND', 'not found')));
}
function err(code, message) {
const err = Error(message);
err.code = code;
return err;
}
function uid() {
return Object.keys(state)
.sort((a, b) => a - b)
.map(Number)
.filter(n => !isNaN(n))
.pop()++;
}
Dependencies
"fastify": "^3.0.0",
"fastify-autoload": "^3.3.1",
"fastify-cli": "^2.14.0",
"fastify-http-proxy": "^6.2.1",
"fastify-plugin": "^3.0.0",
"fastify-reply-from": "^6.4.1",
"fastify-sensible": "^3.1.0",
"got": "^11.8.2"