webserv
Version:
a quick, flexible, fully typed development server
142 lines • 6.64 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "../guards/method", "../guards/path", "../HttpError", "../processors/before/body.processor", "../transforms/json.transform", "../util/request"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const method_1 = require("../guards/method");
const path_1 = require("../guards/path");
const HttpError_1 = require("../HttpError");
const body_processor_1 = require("../processors/before/body.processor");
const json_transform_1 = require("../transforms/json.transform");
const request_1 = require("../util/request");
function isRecord(value) {
return value && typeof value === 'object' && typeof value.id === 'string';
}
exports.isRecord = isRecord;
const DELETED = Symbol();
function defaultLoader(id) {
if (id) {
return undefined;
}
return [];
}
/**
* The CRUD service provides basic in-memory Create Read Update Delete and List support on a record
* centered around the provided path.
*
* - supported operations may be defined in properties
* - a set of records may be provided to initialize the store
* - a loader function can be used to load in records from another source (e.g. disk)
*
* List: GET {path}/
* Returns a list of all records
*
* Create: POST {path}/
* Create a new record to be stored in-memory
*
* Read: GET {path}/{id}
* Returns a record if found; or returns a 404 status
*
* Update: PUT {path}/
* Updates a record if found; or returns a 404 status
*
* Delete: DELETE {path}/{id}
* Deletes a record from the in-memory store
*/
function crudService(props) {
const { route = '/', data = [], operations = ['list', 'create', 'read', 'update', 'delete'], dataLoader = defaultLoader } = props;
const expandedRoute = route.charAt(route.length - 1) === '*' ? route : `${route}*`;
const store = new Map(data.map((data) => [data.id, data]));
const getRecord = (id) => (store.has(id) ? store.get(id) : dataLoader(id));
const middlewares = {
create: {
guards: [method_1.method.post()],
middleware: (request) => {
const { body } = request_1.getParams(request, 'body');
if (isRecord(body)) {
store.set(body.id, body);
}
else {
throw new HttpError_1.HttpError(400 /* BadRequest */);
}
}
},
read: {
guards: [method_1.method.get('/:id')],
middleware: (request) => __awaiter(this, void 0, void 0, function* () {
const { params } = request_1.getParams(request, 'params');
if (params.id) {
const record = yield getRecord(params.id);
if (isRecord(record)) {
store.set(record.id, record);
return record;
}
}
throw new HttpError_1.HttpError(404 /* NotFound */);
})
},
delete: {
guards: [method_1.method.delete('/:id')],
middleware: (request) => __awaiter(this, void 0, void 0, function* () {
const { params } = request_1.getParams(request, 'params');
if (params.id) {
const record = yield getRecord(params.id);
if (isRecord(record)) {
store.set(record.id, DELETED);
return record;
}
}
throw new HttpError_1.HttpError(404 /* NotFound */);
})
},
update: {
guards: [method_1.method.put()],
middleware: (request) => __awaiter(this, void 0, void 0, function* () {
const { body } = request_1.getParams(request, 'body');
if (isRecord(body)) {
const record = yield getRecord(body.id);
if (isRecord(record)) {
store.set(body.id, Object.assign(Object.assign({}, record), body));
return store.get(body.id);
}
}
throw new HttpError_1.HttpError(404 /* NotFound */);
})
},
list: {
guards: [method_1.method.get('/')],
middleware: () => __awaiter(this, void 0, void 0, function* () {
const fileData = yield dataLoader();
return [...fileData.filter((record) => !store.has(record.id)), ...store.values()].filter(isRecord);
})
}
};
return {
route: {
guards: [path_1.pathGuard({ match: expandedRoute })],
before: [body_processor_1.body({})],
transforms: [json_transform_1.jsonTransform],
middleware: Object.entries(middlewares)
.filter(([op]) => operations.includes(op))
.map(([, desc]) => desc)
}
};
}
exports.crudService = crudService;
});
//# sourceMappingURL=crud.service.js.map