miter
Version:
A typescript web framework based on ExpressJs based loosely on SailsJs
512 lines • 21.6 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const routes_1 = require("../decorators/router/routes");
const pluralize_1 = require("../util/pluralize");
const http_status_type_1 = require("../util/http-status-type");
class CrudController {
constructor(staticModel, modelName, pluralName, singularName) {
this.staticModel = staticModel;
this.modelName = modelName;
this._singularName = singularName || this.getSingularPath(modelName);
this._pluralName = pluralName || this.getPluralPath(modelName);
}
*splitOnWords(name) {
let currentWord = '';
for (let q = 0; q < name.length; q++) {
let chr = name[q];
if (chr.match(/[A-Z]/)) {
if (currentWord)
yield currentWord;
currentWord = chr;
}
else if (chr == '_') {
if (currentWord)
yield currentWord;
currentWord = '';
}
else
currentWord += chr;
}
if (currentWord)
yield currentWord;
}
getSingularPath(name) {
let parts = [...this.splitOnWords(name)].filter(Boolean);
if (!parts.length)
return name;
parts[parts.length - 1] = pluralize_1.pluralize(parts[parts.length - 1], false);
return parts.map(pt => pt.toLowerCase()).join('-');
}
getPluralPath(name) {
let parts = [...this.splitOnWords(name)].filter(Boolean);
if (!parts.length)
return name;
parts[parts.length - 1] = pluralize_1.pluralize(parts[parts.length - 1]);
return parts.map(pt => pt.toLowerCase()).join('-');
}
get singularName() {
return this._singularName;
}
get pluralName() {
return this._pluralName;
}
transformPathPart(routeFnName, part) {
return part.replace(/%%PLURAL_NAME%%/g, this._pluralName).replace(/%%SINGULAR_NAME%%/g, this._singularName);
}
transformRoutePolicies(routeFnName, fullPath, policies) {
switch (routeFnName) {
case 'destroy':
return [...policies, ...this.getDestroyPolicies()];
case 'create':
return [...policies, ...this.getCreatePolicies()];
case 'update':
return [...policies, ...this.getMutatePolicies()];
case 'get':
return [...policies, ...this.getReadPolicies()];
case 'find':
case 'count':
return [...policies, ...this.getQueryPolicies()];
default:
return policies;
}
}
getReadPolicies() {
return [];
}
getQueryPolicies() {
return [];
}
getCreatePolicies() {
return [];
}
getMutatePolicies() {
return [];
}
getDestroyPolicies() {
return [];
}
transformInclude(req, res, include) {
return __awaiter(this, void 0, void 0, function* () {
});
}
transformQuery(req, res, query) {
return __awaiter(this, void 0, void 0, function* () {
return query;
});
}
performQuery(req, res, query) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.staticModel.db.findAndCountAll(query);
});
}
performFindOneQuery(req, res, query) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.staticModel.db.findOne(query);
});
}
transformQueryResults(req, res, results) {
return __awaiter(this, void 0, void 0, function* () {
let initialStatusCode = res.statusCode;
let oldResults = results.results;
let newResults = [];
let filteredCount = 0;
for (let q = 0; q < oldResults.length; q++) {
let transformed = yield this.transformResult(req, res, oldResults[q]);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
if (transformed)
newResults.push(transformed);
else
filteredCount++;
}
let count = (typeof results.count === 'number' ? results.count :
typeof results.total === 'number' ? results.total :
oldResults.length);
count -= filteredCount;
return {
results: newResults,
count: count,
page: results.page,
perPage: results.perPage
};
});
}
transformResult(req, res, result) {
return __awaiter(this, void 0, void 0, function* () {
return result;
});
}
transformCreateQuery(req, res, query) {
return __awaiter(this, void 0, void 0, function* () {
return query;
});
}
performCreate(req, res, data) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.staticModel.db.create(data);
});
}
transformCreateResult(req, res, result) {
return __awaiter(this, void 0, void 0, function* () {
return result;
});
}
transformUpdateQuery(req, res, query) {
return __awaiter(this, void 0, void 0, function* () {
return query;
});
}
performUpdate(req, res, id, data, returning) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.staticModel.db.update(id, data, returning);
});
}
transformUpdateResult(req, res, result) {
return __awaiter(this, void 0, void 0, function* () {
return result;
});
}
performDestroy(req, res, id) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.staticModel.db.destroy(id);
});
}
beforeCreate(req, res, data) {
return __awaiter(this, void 0, void 0, function* () {
});
}
afterCreate(req, res, result) {
return __awaiter(this, void 0, void 0, function* () {
});
}
beforeUpdate(req, res, updateId, data) {
return __awaiter(this, void 0, void 0, function* () {
});
}
afterUpdate(req, res, updateId, result) {
return __awaiter(this, void 0, void 0, function* () {
});
}
beforeDestroy(req, res, destroyId) {
return __awaiter(this, void 0, void 0, function* () {
});
}
afterDestroy(req, res, destroyId) {
return __awaiter(this, void 0, void 0, function* () {
});
}
create(req, res) {
return __awaiter(this, void 0, void 0, function* () {
let initialStatusCode = res.statusCode;
let data = (yield this.transformCreateQuery(req, res, req.body)) || req.body;
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
if (!data) {
res.status(http_status_type_1.HTTP_STATUS_ERROR).send(`You haven't sent any data to create the ${this.modelName} with!`);
return;
}
if (data.constructor == Array) {
throw new Error("createMany not supported");
}
yield this.beforeCreate(req, res, data);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
let result = yield this.performCreate(req, res, data);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
result = yield this.transformCreateResult(req, res, result);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
yield this.afterCreate(req, res, result);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
res.status(http_status_type_1.HTTP_STATUS_OK).json(result);
});
}
find(req, res) {
return __awaiter(this, void 0, void 0, function* () {
let query = {};
let include = [];
let order = [];
try {
if (req.query['query']) {
if (typeof req.query['query'] === 'string')
query = JSON.parse(req.query['query'] || '{}');
else
query = req.query['query'];
}
if (req.query['include']) {
if (typeof req.query['include'] === 'string')
include = JSON.parse(req.query['include'] || '[]');
else
include = req.query['include'];
}
if (req.query['order']) {
if (typeof req.query['order'] === 'string')
order = JSON.parse(req.query['order'] || '[]');
else
order = req.query['order'];
}
}
catch (e) {
res.status(http_status_type_1.HTTP_STATUS_ERROR).send(`Could not parse request parameters.`);
return;
}
if ((!include || !include.length) && query.include) {
include = query.include;
delete query.include;
}
if ((!order || !order.length) && query.order) {
order = query.order;
delete query.order;
}
let initialStatusCode = res.statusCode;
query = (yield this.transformQuery(req, res, query)) || query;
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
include = include || [];
include = (yield this.transformInclude(req, res, include)) || include;
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
let findOne = req.path.endsWith('find-one');
if (findOne) {
let result = yield this.performFindOneQuery(req, res, {
where: query,
include: include,
order: order
});
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
result = yield this.transformResult(req, res, result);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
res.status(http_status_type_1.HTTP_STATUS_OK).json(result);
}
else {
let perPage = req.query['perPage'];
if (!perPage || !(perPage = parseInt('' + perPage, 10)) || isNaN(perPage) || perPage <= 0)
perPage = 10;
let page = req.query['page'];
if (!page || !(page = parseInt('' + page, 10)) || isNaN(page) || page < 0)
page = 0;
let results = yield this.performQuery(req, res, {
where: query,
include: include,
order: order,
offset: page * perPage,
limit: perPage
});
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
results = (yield this.transformQueryResults(req, res, results));
if (res.statusCode !== initialStatusCode || res.headersSent || !results)
return;
res.status(http_status_type_1.HTTP_STATUS_OK).json({
results: results.results,
page: results.page || page,
perPage: results.perPage || perPage,
total: results.count
});
}
});
}
count(req, res) {
return __awaiter(this, void 0, void 0, function* () {
let query = {};
try {
if (req.query['query']) {
if (typeof req.query['query'] === 'string')
query = JSON.parse(req.query['query'] || '{}');
else
query = req.query['query'];
}
}
catch (e) {
res.status(http_status_type_1.HTTP_STATUS_ERROR).send(`Could not parse query parameters`);
return;
}
let initialStatusCode = res.statusCode;
query = (yield this.transformQuery(req, res, query)) || query;
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
let count = yield this.staticModel.db.count({
where: query
});
res.status(http_status_type_1.HTTP_STATUS_OK).send(`${count}`);
});
}
get(req, res) {
return __awaiter(this, void 0, void 0, function* () {
let id = parseInt(req.params['id'], 10);
if (!id || isNaN(id)) {
res.status(http_status_type_1.HTTP_STATUS_ERROR).send(`Invalid ${this.modelName} id: ${req.params['id']}`);
return;
}
let include = [];
try {
if (req.query['include']) {
if (typeof req.query['include'] === 'string')
include = JSON.parse(req.query['include'] || '[]');
else
include = req.query['include'];
}
}
catch (e) {
res.status(http_status_type_1.HTTP_STATUS_ERROR).send(`Could not parse request parameters.`);
return;
}
let initialStatusCode = res.statusCode;
include = include || [];
include = (yield this.transformInclude(req, res, include)) || include;
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
let result = yield this.staticModel.db.findById(id, { include: include });
result = yield this.transformResult(req, res, result);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
res.status(http_status_type_1.HTTP_STATUS_OK).json(result);
});
}
update(req, res) {
return __awaiter(this, void 0, void 0, function* () {
let id = parseInt(req.params['id'], 10);
if (!id || isNaN(id)) {
res.status(http_status_type_1.HTTP_STATUS_ERROR).send(`Invalid ${this.modelName} id: ${req.params['id']}`);
return;
}
let initialStatusCode = res.statusCode;
let data = (yield this.transformUpdateQuery(req, res, req.body)) || req.body;
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
if (!data) {
res.status(http_status_type_1.HTTP_STATUS_ERROR).send(`You haven't sent any data to update the ${this.modelName} with!`);
return;
}
let returning = false;
let returningParam = req.query['returning'];
if (returningParam) {
if (returningParam === true || returningParam === 'true')
returning = true;
else if (returningParam === false || returningParam === 'false')
returning = false;
else {
res.status(http_status_type_1.HTTP_STATUS_ERROR).send(`Invalid ${this.modelName} returning parameter: ${returningParam}; must be boolean`);
return;
}
}
yield this.beforeUpdate(req, res, id, data);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
let performUpdateResults = yield this.performUpdate(req, res, id, data, returning);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
let [updated, results] = performUpdateResults;
if (results && results.length > 1)
throw new Error(`performUpdate returned multiple results`);
if (updated) {
results = yield Promise.all(results.map((result) => this.transformUpdateResult(req, res, result)));
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
let result;
if (returning) {
result = results[0];
if (result) {
result = (yield this.transformResult(req, res, result));
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
}
}
yield this.afterUpdate(req, res, id, result);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
res.status(http_status_type_1.HTTP_STATUS_OK).json(result);
}
else {
res.status(http_status_type_1.HTTP_STATUS_ERROR).send(`Can't find the ${this.modelName} with id ${id} to update it.`);
return;
}
});
}
destroy(req, res) {
return __awaiter(this, void 0, void 0, function* () {
let id = parseInt(req.params['id'], 10);
if (!id || isNaN(id)) {
res.status(http_status_type_1.HTTP_STATUS_ERROR).send(`Invalid ${this.modelName} id: ${req.params['id']}`);
return;
}
let initialStatusCode = res.statusCode;
yield this.beforeDestroy(req, res, id);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
let destroyed = yield this.performDestroy(req, res, id);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
if (destroyed) {
yield this.afterDestroy(req, res, id);
if (res.statusCode !== initialStatusCode || res.headersSent)
return;
res.status(http_status_type_1.HTTP_STATUS_OK).end();
}
else {
res.status(http_status_type_1.HTTP_STATUS_ERROR).send({ msg: `Failed to delete ${this._singularName} with ID ${id}.` });
}
});
}
}
__decorate([
routes_1.Post(`/%%PLURAL_NAME%%/create`),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], CrudController.prototype, "create", null);
__decorate([
routes_1.Get(`/%%PLURAL_NAME%%/find`),
routes_1.Get(`/%%PLURAL_NAME%%/find-one`),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], CrudController.prototype, "find", null);
__decorate([
routes_1.Get(`/%%PLURAL_NAME%%/count`),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], CrudController.prototype, "count", null);
__decorate([
routes_1.Get(`/%%SINGULAR_NAME%%/:id`),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], CrudController.prototype, "get", null);
__decorate([
routes_1.Put(`/%%SINGULAR_NAME%%/:id`),
routes_1.Patch(`/%%SINGULAR_NAME%%/:id`),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], CrudController.prototype, "update", null);
__decorate([
routes_1.Delete(`/%%SINGULAR_NAME%%/:id`),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], CrudController.prototype, "destroy", null);
exports.CrudController = CrudController;
//# sourceMappingURL=crud-controller.js.map