mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-27 04:43:12 +03:00
104f84f252
As discussed with the product team we want to enforce kebab-case file names for all files, with the exception of files which export a single class, in which case they should be PascalCase and reflect the class which they export. This will help find classes faster, and should push better naming for them too. Some files and packages have been excluded from this linting, specifically when a library or framework depends on the naming of a file for the functionality e.g. Ember, knex-migrator, adapter-manager
101 lines
3.6 KiB
JavaScript
101 lines
3.6 KiB
JavaScript
const debug = require('@tryghost/debug')('frame');
|
|
const _ = require('lodash');
|
|
|
|
/**
|
|
* @description The "frame" holds all information of a request.
|
|
*
|
|
* Each party can modify the frame by reference.
|
|
* A request hits a lot of stages in the API implementation and that's why modification by reference was the
|
|
* easiest to use. We always have access to the original input, we never loose track of it.
|
|
*/
|
|
class Frame {
|
|
constructor(obj = {}) {
|
|
this.original = obj;
|
|
|
|
/**
|
|
* options: Query params, url params, context and custom options
|
|
* data: Body or if the ctrl wants query/url params inside body
|
|
* user: Logged in user
|
|
* file: Uploaded file
|
|
* files: Uploaded files
|
|
* apiType: Content or admin api access
|
|
* docName: The endpoint name, e.g. "posts"
|
|
* method: The method name, e.g. "browse"
|
|
*/
|
|
this.options = {};
|
|
this.data = {};
|
|
this.user = {};
|
|
this.file = {};
|
|
this.files = [];
|
|
this.apiType = null;
|
|
this.docName = null;
|
|
this.method = null;
|
|
this.response = null;
|
|
}
|
|
|
|
/**
|
|
* @description Configure the frame.
|
|
*
|
|
* If you instantiate a new frame, all the data you pass in, land in `this.original`. This is helpful
|
|
* for debugging to see what the original input was.
|
|
*
|
|
* This function will prepare the incoming data for further processing.
|
|
* Based on the API ctrl implemented, this fn will pick allowed properties to either options or data.
|
|
*/
|
|
configure(apiConfig) {
|
|
debug('configure');
|
|
|
|
if (apiConfig.options) {
|
|
if (typeof apiConfig.options === 'function') {
|
|
apiConfig.options = apiConfig.options(this);
|
|
}
|
|
|
|
if (Object.prototype.hasOwnProperty.call(this.original, 'query')) {
|
|
Object.assign(this.options, _.pick(this.original.query, apiConfig.options));
|
|
}
|
|
|
|
if (Object.prototype.hasOwnProperty.call(this.original, 'params')) {
|
|
Object.assign(this.options, _.pick(this.original.params, apiConfig.options));
|
|
}
|
|
|
|
if (Object.prototype.hasOwnProperty.call(this.original, 'options')) {
|
|
Object.assign(this.options, _.pick(this.original.options, apiConfig.options));
|
|
}
|
|
}
|
|
|
|
this.options.context = this.original.context;
|
|
|
|
if (this.original.body && Object.keys(this.original.body).length) {
|
|
this.data = _.cloneDeep(this.original.body);
|
|
} else {
|
|
if (apiConfig.data) {
|
|
if (typeof apiConfig.data === 'function') {
|
|
apiConfig.data = apiConfig.data(this);
|
|
}
|
|
|
|
if (Object.prototype.hasOwnProperty.call(this.original, 'query')) {
|
|
Object.assign(this.data, _.pick(this.original.query, apiConfig.data));
|
|
}
|
|
|
|
if (Object.prototype.hasOwnProperty.call(this.original, 'params')) {
|
|
Object.assign(this.data, _.pick(this.original.params, apiConfig.data));
|
|
}
|
|
|
|
if (Object.prototype.hasOwnProperty.call(this.original, 'options')) {
|
|
Object.assign(this.data, _.pick(this.original.options, apiConfig.data));
|
|
}
|
|
}
|
|
}
|
|
|
|
this.user = this.original.user;
|
|
this.file = this.original.file;
|
|
this.files = this.original.files;
|
|
|
|
debug('original', this.original);
|
|
debug('options', this.options);
|
|
debug('data', this.data);
|
|
}
|
|
}
|
|
|
|
module.exports = Frame;
|