punchcard-content-types
Version:
Combines with input plugins to create forms with validation. Creates forms for Punchcard CMS.
129 lines (106 loc) • 3.51 kB
JavaScript
;
const dir = require('node-dir');
const yaml = require('js-yaml');
const slugify = require('lodash/kebabCase');
const path = require('path');
const utils = require('../utils');
/**
* Gets all Content Types
*
* @param {object} config - configuration object
*
* @returns {Promise} - An {Array} containing {Object} for each content type, including `name` {string}, `id` name {string}, and full config {object} loaded from YAML config file
*/
const load = (config) => {
const configuration = config || {};
const types = [];
const ids = [];
let contentPath = path.join(process.cwd(), 'content-types');
return new Promise((resolve, reject) => {
if (typeof configuration !== 'object') {
reject(new Error('Configuration parameter must be an object'));
}
if (configuration.hasOwnProperty('content')) {
if (configuration.content.hasOwnProperty('directory')) {
contentPath = configuration.content.directory;
}
}
dir.readFiles(contentPath, {
match: /.yml$/,
exclude: /^\./,
}, (err, content, next) => {
if (err) {
reject(err);
}
const type = yaml.safeLoad(content);
if (!type.hasOwnProperty('name')) {
reject(new Error('Content types require a name'));
}
if (!type.hasOwnProperty('id')) {
reject(new Error('Content types require an id'));
}
if (type.id !== slugify(type.id)) {
reject(new Error(`${type.id} needs to be written in kebab case (e.g. ${slugify(type.id)}`));
}
if (ids.indexOf(type.id) === -1) {
ids.push(type.id);
types.push(type);
}
else {
reject(new Error(`Content type ${type.id} is duplicated!`));
}
if (!type.hasOwnProperty('identifier')) {
reject(new Error(`Identifier missing in content type '${type.name}'.`));
}
if (type.hasOwnProperty('identifier')) {
if (typeof type.identifier !== 'string') {
reject(new Error(`Identifier in content type '${type.name}' must be a string`));
}
}
// find attribute which is the identifier
const attr = type.attributes.find(a => {
return a.id === type.identifier;
});
if (typeof attr === undefined) {
reject(new Error(`Identifier '${type.identifier}' is not an attribute in content type '${type.name}'.`));
}
// check attribute only has one input
if (attr.inputs && Array.isArray(Object.keys(attr.inputs)) && Object.keys(attr.inputs).length > 1) {
reject(new Error(`Attribute '${type.identifier}' in content type '${type.name}' cannot be the identifier. Only attributes with one input can be the identifier.`));
}
next();
}, (err) => {
if (err) {
reject(err);
}
resolve(types);
});
});
};
/**
* Names of Content Types
*
* @param {array} types - Array of content types
*
* @returns {array} of Content Type names
*/
const names = types => {
return types.map(type => {
return type.name;
});
};
/**
* Attributes of a Content Type
*
* @param {string} id id of a content type
* @param {array} types array of content type objects
*
* @returns {array} array of content type's attribute objects
*/
const attributes = (id, types) => {
const filtered = utils.singleItem('id', id, types);
return filtered ? filtered[0].attributes : false;
};
module.exports = load;
module.exports.names = names;
module.exports.attributes = attributes;