Skip to content

Commit

Permalink
non-crud controller generator
Browse files Browse the repository at this point in the history
  • Loading branch information
Hage Yaapa committed Jan 31, 2019
1 parent 668928b commit c033759
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 46 deletions.
66 changes: 66 additions & 0 deletions lib/basic-controller-generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use strict';

const { decorate, metadata, param } = require('./helpers.js');
const rest = require('@loopback/rest');
const context = require('@loopback/context');

module.exports = function (specifications, operations) {

const paths = Object.keys(specifications);
const controllerClasses = {};
const decorationProperties = [];

paths.forEach(path => {
const methods = Object.keys(specifications[path]);
methods.forEach(method => {
const decorationProperty = [path];
const specs = specifications[path][method];
const controllerName = specs['x-controller-name'];
const operationName = specs['x-operation-name'];

if (!(controllerName in controllerClasses)) {
// Create the basic class
controllerClasses[controllerName] = class {
constructor(req) {
this.req = req;
}
}
}

// Add the class methods dynamically
controllerClasses[controllerName].prototype[operationName] = operations[operationName];
decorationProperty.push(method);
decorationProperty.push(operationName);
decorationProperties.push(decorationProperty);
});
});

const controllerName = Object.keys(controllerClasses)[0];
let ControllerClass = controllerClasses[controllerName];

Object.defineProperty(ControllerClass, 'name', { writable: true });
ControllerClass.name = controllerName;
Object.defineProperty(ControllerClass, 'name', { writable: false });

decorationProperties.forEach(decorationProperty => {
const path = decorationProperty[0];
const method = decorationProperty[1];
const operation = decorationProperty[2];

decorate([
rest[method](path, {
responses: specifications[path][method].responses
}),
metadata('design:type', Function),
metadata('design:paramtypes', []),
metadata('design:returntype', Object)
], ControllerClass.prototype, operation, null);
});

ControllerClass = decorate([
param(0, context.inject(rest.RestBindings.Http.REQUEST)),
metadata('design:paramtypes', [Object])
], ControllerClass);

return ControllerClass;
};
178 changes: 133 additions & 45 deletions server/controllers/ping.controller.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,149 @@
'use strict';

const { decorate, metadata, param } = require('../../lib/helpers.js');
const rest = require("@loopback/rest");
const context = require("@loopback/context");
const generateBasicController = require('../../lib/basic-controller-generator.js');

const PING_RESPONSE = {
description: 'Ping Response',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
greeting: { type: 'string' },
date: { type: 'string' },
url: { type: 'string' },
headers: {
type: 'object',
properties: {
'Content-Type': { type: 'string' },
},
additionalProperties: true,
},
},
},
},
const operations = {
ping: function ping() {
return {
greeting: 'Ping from LoopBack',
date: new Date(),
url: this.req.url,
headers: Object.assign({}, this.req.headers),
};
},
};

class PingController {
constructor(req) {
this.req = req;
}
pang: function pang() {
return {
greeting: 'Pang from LoopBack',
date: new Date(),
url: this.req.url,
headers: Object.assign({}, this.req.headers),
};
},

ping() {
pong: function pong() {
return {
greeting: 'Hello from LoopBack',
greeting: 'Pong from LoopBack',
date: new Date(),
url: this.req.url,
headers: Object.assign({}, this.req.headers),
};
}
};

decorate([
rest.get('/ping', {
responses: {
'200': PING_RESPONSE,
const specifications = {
'/ping': {
'get': {
'x-controller-name': 'PingController',
'x-operation-name': 'ping',
'responses': {
'200': {
'description': 'GET Ping Response',
'content': {
'application/json': {
'schema': {
'type': 'object',
'properties': {
'greeting': {
'type': 'string'
},
'date': {
'type': 'string'
},
'url': {
'type': 'string'
},
'headers': {
'type': 'object',
'properties': {
'Content-Type': {
'type': 'string'
}
},
'additionalProperties': true
}
}
}
}
}
}
}
},
}),
metadata("design:type", Function),
metadata("design:paramtypes", []),
metadata("design:returntype", Object)
], PingController.prototype, "ping", null);

PingController = decorate([
param(0, context.inject(rest.RestBindings.Http.REQUEST)),
metadata("design:paramtypes", [Object])
], PingController);
'post': {
'x-controller-name': 'PingController',
'x-operation-name': 'pang',
'responses': {
'200': {
'description': 'POST Ping Response',
'content': {
'application/json': {
'schema': {
'type': 'object',
'properties': {
'greeting': {
'type': 'string'
},
'date': {
'type': 'string'
},
'url': {
'type': 'string'
},
'headers': {
'type': 'object',
'properties': {
'Content-Type': {
'type': 'string'
}
},
'additionalProperties': true
}
}
}
}
}
}
}
}
},
'/pong': {
'get': {
'x-controller-name': 'PingController',
'x-operation-name': 'pong',
'responses': {
'200': {
'description': 'GET Pong Response',
'content': {
'application/json': {
'schema': {
'type': 'object',
'properties': {
'greeting': {
'type': 'string'
},
'date': {
'type': 'string'
},
'url': {
'type': 'string'
},
'headers': {
'type': 'object',
'properties': {
'Content-Type': {
'type': 'string'
}
},
'additionalProperties': true
}
}
}
}
}
}
}
},
}
}

exports.PingController = PingController;
exports.PingPongController = generateBasicController(specifications, operations);
2 changes: 1 addition & 1 deletion server/datasources/memory.datasource.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';

const config = require('./memory.datasource.json');
const generateDataSource = require('../../lib/datasource-generator.js');
const config = require('./memory.datasource.json');
exports.MemoryDataSource = generateDataSource('memory', config);
1 change: 1 addition & 0 deletions server/models/color.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const modelDefinition = {
}
},
// Supporting these additional features would be a lot of additional work
// and some features are still not available in LB4, yet
'validations': [],
'relations': {},
'acls': [],
Expand Down

0 comments on commit c033759

Please sign in to comment.