jsonapi-serializer
Version:
A Node.js framework agnostic library for serializing your data to JSON API
1,682 lines (1,377 loc) • 192 kB
JavaScript
require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
'use strict';
var isPlainObject = require('lodash/isPlainObject');
var isFunction = require('lodash/isFunction');
var _find = require('lodash/find');
var _extend = require('lodash/extend');
var _transform = require('lodash/transform');
var Inflector = require('./inflector');
module.exports = function (jsonapi, data, opts) {
var alreadyIncluded = [];
function isComplexType(obj) {
return Array.isArray(obj) || isPlainObject(obj);
}
function getValueForRelationship(relationshipData, included) {
if (opts && relationshipData && opts[relationshipData.type]) {
var valueForRelationshipFct = opts[relationshipData.type]
.valueForRelationship;
return valueForRelationshipFct(relationshipData, included);
} else {
return included;
}
}
function findIncluded(relationshipData, ancestry) {
return new Promise(function (resolve) {
if (!jsonapi.included || !relationshipData) { resolve(null); }
var included = _find(jsonapi.included, {
id: relationshipData.id,
type: relationshipData.type
});
if (included) {
// To prevent circular references, check if the record type
// has already been processed in this thread
if (ancestry.indexOf(included.type) > -1) {
return Promise
.all([extractAttributes(included)])
.then(function (results) {
var attributes = results[0];
var relationships = results[1];
resolve(_extend(attributes, relationships));
});
}
return Promise
.all([extractAttributes(included), extractRelationships(included, ancestry + ':' + included.type + included.id)])
.then(function (results) {
var attributes = results[0];
var relationships = results[1];
resolve(_extend(attributes, relationships));
});
} else {
return resolve(null);
}
});
}
function keyForAttribute(attribute) {
if (isPlainObject(attribute)) {
return _transform(attribute, function (result, value, key) {
if (isComplexType(value)) {
result[keyForAttribute(key)] = keyForAttribute(value);
} else {
result[keyForAttribute(key)] = value;
}
});
} else if (Array.isArray(attribute)) {
return attribute.map(function (attr) {
if (isComplexType(attr)) {
return keyForAttribute(attr);
} else {
return attr;
}
});
} else {
if (isFunction(opts.keyForAttribute)) {
return opts.keyForAttribute(attribute);
} else {
return Inflector.caserize(attribute, opts);
}
}
}
function extractAttributes(from) {
var dest = keyForAttribute(from.attributes || {});
if ('id' in from) { dest[opts.id || 'id'] = from.id; }
if (opts.typeAsAttribute) {
if ('type' in from) { dest.type = from.type; }
}
if ('meta' in from) { dest.meta = keyForAttribute(from.meta || {}) }
return dest;
}
function extractRelationships(from, ancestry) {
if (!from.relationships) { return; }
var dest = {};
return Promise
.all(Object.keys(from.relationships).map(function (key) {
var relationship = from.relationships[key];
if (relationship.data === null) {
dest[keyForAttribute(key)] = null;
} else if (Array.isArray(relationship.data)) {
return Promise
.all(relationship.data.map(function (relationshipData) {
return extractIncludes(relationshipData, ancestry);
}))
.then(function (includes) {
if (includes) { dest[keyForAttribute(key)] = includes; }
});
} else {
return extractIncludes(relationship.data, ancestry)
.then(function (includes) {
if (includes) { dest[keyForAttribute(key)] = includes; }
});
}
}))
.then(function() {
return dest;
});
}
function extractIncludes(relationshipData, ancestry) {
return findIncluded(relationshipData, ancestry)
.then(function (included) {
var valueForRelationship = getValueForRelationship(relationshipData,
included);
if (valueForRelationship && isFunction(valueForRelationship.then)) {
return valueForRelationship.then(function (value) {
return value;
});
} else {
return valueForRelationship;
}
});
}
this.perform = function () {
return Promise
.all([extractAttributes(data), extractRelationships(data, data.type + data.id)])
.then(function (results) {
var attributes = results[0];
var relationships = results[1];
var record = _extend(attributes, relationships);
// Links
if (jsonapi.links) {
record.links = jsonapi.links;
}
// If option is present, transform record
if (opts && opts.transform) {
record = opts.transform(record);
}
return record;
});
};
};
},{"./inflector":5,"lodash/extend":158,"lodash/find":159,"lodash/isFunction":171,"lodash/isPlainObject":176,"lodash/transform":195}],2:[function(require,module,exports){
'use strict';
var isFunction = require('lodash/isFunction');
var DeserializerUtils = require('./deserializer-utils');
module.exports = function (opts) {
if (!opts) { opts = {}; }
this.deserialize = function (jsonapi, callback) {
function collection() {
return Promise
.all(jsonapi.data.map(function (d) {
return new DeserializerUtils(jsonapi, d, opts).perform();
}))
.then(function (result) {
if (isFunction(callback)) {
callback(null, result);
}
return result
});
}
function resource() {
return new DeserializerUtils(jsonapi, jsonapi.data, opts)
.perform()
.then(function (result) {
if (isFunction(callback)) {
callback(null, result);
}
return result
});
}
if (Array.isArray(jsonapi.data)) {
return collection();
} else {
return resource();
}
};
};
},{"./deserializer-utils":1,"lodash/isFunction":171}],3:[function(require,module,exports){
'use strict';
module.exports = function (errors) {
var jsonapi = {
errors: []
};
errors.forEach(function (error) {
var opts = {};
if (error.id) { opts.id = error.id; }
if (error.status) { opts.status = error.status; }
if (error.code) { opts.code = error.code; }
if (error.title) { opts.title = error.title; }
if (error.detail) { opts.detail = error.detail; }
if (error.source) {
opts.source = {};
if (error.source.pointer) {
opts.source.pointer = error.source.pointer;
}
if (error.source.parameter) {
opts.source.parameter = error.source.parameter;
}
}
if (error.links) {
opts.links = { about: error.links.about };
}
if (error.meta) {
opts.meta = error.meta;
}
jsonapi.errors.push(opts);
});
return jsonapi;
};
},{}],4:[function(require,module,exports){
'use strict';
var ErrorUtils = require('./error-utils');
module.exports = function (opts) {
if (!opts) { opts = []; }
if (Array.isArray(opts)) {
return new ErrorUtils(opts);
} else {
return new ErrorUtils([opts]);
}
};
},{"./error-utils":3}],5:[function(require,module,exports){
'use strict';
var Inflector = require('inflected');
module.exports = {
caserize: function (attribute, opts) {
attribute = Inflector.underscore(attribute);
switch (opts.keyForAttribute) {
case 'dash-case':
case 'lisp-case':
case 'spinal-case':
case 'kebab-case':
return Inflector.dasherize(attribute);
case 'underscore_case':
case 'snake_case':
return attribute;
case 'CamelCase':
return Inflector.camelize(attribute);
case 'camelCase':
return Inflector.camelize(attribute, false);
default:
return Inflector.dasherize(attribute);
}
},
pluralize: function (type) {
return Inflector.pluralize(type);
}
};
},{"inflected":8}],6:[function(require,module,exports){
'use strict';
var isPlainObject = require('lodash/isPlainObject');
var isFunction = require('lodash/isFunction');
var _merge = require('lodash/merge');
var _identity = require('lodash/identity');
var _transform = require('lodash/transform');
var _mapValues = require('lodash/mapValues');
var _mapKeys = require('lodash/mapKeys');
var _pick = require('lodash/pick');
var _pickBy = require('lodash/pickBy');
var _each = require('lodash/each');
var _isNil = require('lodash/isNil');
var Inflector = require('./inflector');
module.exports = function (collectionName, record, payload, opts, includedSet) {
function isComplexType(obj) {
return Array.isArray(obj) || isPlainObject(obj);
}
function transformFunction(result, value, key) {
if (isComplexType(value)) {
result[keyForAttribute(key)] = keyForAttribute(value);
} else {
result[keyForAttribute(key)] = value;
}
}
function attributeFunction(attr) {
if (isComplexType(attr)) {
return keyForAttribute(attr);
} else {
return attr;
}
}
const keyForAttributeFunction = isFunction(opts.keyForAttribute)
? opts.keyForAttribute
: (attribute) => Inflector.caserize(attribute, opts);
function keyForAttribute(attribute) {
if (isPlainObject(attribute)) {
return _transform(attribute, transformFunction);
} else if (Array.isArray(attribute)) {
return attribute.map(attributeFunction);
} else {
return keyForAttributeFunction(attribute);
}
}
function getId() {
return opts.id || 'id';
}
function getRef(current, item, opts) {
if (isFunction(opts.ref)) {
return opts.ref(current, item);
} else if (opts.ref === true) {
if (Array.isArray(item)) {
return item.map(function (val) {
return String(val);
});
} else if (item) {
return String(item);
}
} else if (item && item[opts.ref]){
return String(item[opts.ref]);
}
}
function getType(str, attrVal) {
var type;
attrVal = attrVal || {};
if (isFunction(opts.typeForAttribute)) {
type = opts.typeForAttribute(str, attrVal);
}
// If the pluralize option is on, typeForAttribute returned undefined or wasn't used
if ((opts.pluralizeType === undefined || opts.pluralizeType) && type === undefined) {
type = Inflector.pluralize(str);
}
if (type === undefined) {
type = str;
}
return type;
}
function getLinks(current, links, dest) {
return _mapValues(links, function (value) {
if (isFunction(value)) {
return value(record, current, dest);
} else {
return value;
}
});
}
function getMeta(current, meta) {
if (isFunction(meta)) {
return meta(record);
} else {
return _mapValues(meta, function (value) {
if (isFunction(value)) {
return value(record, current);
} else {
return value;
}
});
}
}
function pickFunction (value, key) {
return keyForAttribute(key);
}
function pick(obj, attributes) {
return _mapKeys(_pick(obj, attributes), pickFunction);
}
function isCompoundDocumentIncluded(setKey) {
return includedSet.get(setKey);
}
function pushToIncluded(payload, item) {
const setKey = `${item.type}-${item.id}`;
var included = isCompoundDocumentIncluded(setKey);
if (included) {
// Merge relationships
included.relationships = _merge(included.relationships,
_pickBy(item.relationships, _identity));
// Merge attributes
included.attributes = _merge(included.attributes,
_pickBy(item.attributes, _identity));
} else {
if (!payload.included) { payload.included = []; }
includedSet.set(setKey, item);
payload.included.push(item);
}
}
this.serialize = function (dest, current, attribute, opts) {
var data = null;
if (opts && opts.ref) {
if (!dest.relationships) { dest.relationships = {}; }
if (Array.isArray(current[attribute])) {
data = current[attribute].map((item) => this.serializeRef(item, current, attribute, opts));
} else {
data = this.serializeRef(current[attribute], current, attribute,
opts);
}
dest.relationships[keyForAttribute(attribute)] = {};
if (!opts.ignoreRelationshipData) {
dest.relationships[keyForAttribute(attribute)].data = data;
}
if (opts.relationshipLinks) {
var links = getLinks(current[attribute], opts.relationshipLinks, dest);
if (links.related) {
dest.relationships[keyForAttribute(attribute)].links = links;
}
}
if (opts.relationshipMeta) {
dest.relationships[keyForAttribute(attribute)].meta =
getMeta(current[attribute], opts.relationshipMeta);
}
} else {
if (Array.isArray(current[attribute])) {
if (current[attribute].length && isPlainObject(current[attribute][0])) {
data = current[attribute].map((item) => this.serializeNested(item, current, attribute, opts));
} else {
data = current[attribute];
}
dest.attributes[keyForAttribute(attribute)] = data;
} else if (isPlainObject(current[attribute])) {
data = this.serializeNested(current[attribute], current, attribute, opts);
dest.attributes[keyForAttribute(attribute)] = data;
} else {
dest.attributes[keyForAttribute(attribute)] = current[attribute];
}
}
};
this.serializeRef = function (dest, current, attribute, opts) {
var id = getRef(current, dest, opts);
var type = getType(attribute, dest);
var relationships = [];
var includedAttrs = [];
if (opts.attributes) {
if (dest) {
opts.attributes.forEach(function (attr) {
if (opts[attr] && !dest[attr] && opts[attr].nullIfMissing) {
dest[attr] = null;
}
});
}
relationships = opts.attributes.filter(function (attr) {
return opts[attr];
});
includedAttrs = opts.attributes.filter(function (attr) {
return !opts[attr];
});
}
var included = { type: type, id: id };
if (includedAttrs) { included.attributes = pick(dest, includedAttrs); }
const relationShipsFunction = (relationship) => {
if (dest && (isComplexType(dest[relationship]) || dest[relationship] === null)) {
this.serialize(included, dest, relationship, opts[relationship]);
}
}
relationships.forEach(relationShipsFunction);
if (includedAttrs.length &&
(opts.included === undefined || opts.included)) {
if (opts.includedLinks) {
included.links = getLinks(dest, opts.includedLinks);
}
if (typeof id !== 'undefined') { pushToIncluded(payload, included); }
}
return typeof id !== 'undefined' ? { type: type, id: id } : null;
};
this.serializeNested = function (dest, current, attribute, opts) {
var embeds = [];
var attributes = [];
var ret = {};
if (opts && opts.attributes) {
embeds = opts.attributes.filter(function (attr) {
return opts[attr];
});
attributes = opts.attributes.filter(function (attr) {
return !opts[attr];
});
if (attributes) { ret.attributes = pick(dest, attributes); }
const embedsFunction = (embed) => {
if (isComplexType(dest[embed])) {
this.serialize(ret, dest, embed, opts[embed]);
}
}
embeds.forEach(embedsFunction);
} else {
ret.attributes = dest;
}
return ret.attributes;
};
this.perform = function () {
if( record === null ){
return null;
}
// If option is present, transform record
if (opts && opts.transform) {
record = opts.transform(record);
}
// Top-level data.
var data = { type: getType(collectionName, record) };
if (!_isNil(record[getId()])) { data.id = String(record[getId()]); }
// Data links.
if (opts.dataLinks) {
data.links = getLinks(record, opts.dataLinks);
}
// Data meta
if (opts.dataMeta) {
data.meta = getMeta(record, opts.dataMeta);
}
_each(opts.attributes, (attribute) => {
var splittedAttributes = attribute.split(':');
if (opts[attribute] && !record[attribute] && opts[attribute].nullIfMissing) {
record[attribute] = null;
}
if (splittedAttributes[0] in record) {
if (!data.attributes) { data.attributes = {}; }
var attributeMap = attribute;
if (splittedAttributes.length > 1) {
attribute = splittedAttributes[0];
attributeMap = splittedAttributes[1];
}
this.serialize(data, record, attribute, opts[attributeMap]);
}
});
return data;
};
};
},{"./inflector":5,"lodash/each":156,"lodash/identity":165,"lodash/isFunction":171,"lodash/isNil":173,"lodash/isPlainObject":176,"lodash/mapKeys":181,"lodash/mapValues":182,"lodash/merge":184,"lodash/pick":185,"lodash/pickBy":186,"lodash/transform":195}],7:[function(require,module,exports){
'use strict';
var isFunction = require('lodash/isFunction');
var _mapValues = require('lodash/mapValues');
var SerializerUtils = require('./serializer-utils');
module.exports = function (collectionName, records, opts) {
this.serialize = function (records) {
var that = this;
var payload = {};
const includedSet = new Map();
function getLinksFunction(value) {
if (isFunction(value)) {
return value(records);
} else {
return value;
}
}
function getLinks(links) {
return _mapValues(links, getLinksFunction);
}
function collection() {
payload.data = [];
records.forEach(function (record) {
var serializerUtils = new SerializerUtils(that.collectionName, record,
payload, that.opts, includedSet);
payload.data.push(serializerUtils.perform());
});
return payload;
}
function resource() {
payload.data = new SerializerUtils(that.collectionName, records, payload,
that.opts, includedSet).perform(records);
return payload;
}
if (that.opts.topLevelLinks) {
payload.links = getLinks(that.opts.topLevelLinks);
}
if (that.opts.meta) {
payload.meta = _mapValues(that.opts.meta, function (value) {
if (isFunction(value)) {
return value(records);
} else {
return value;
}
});
}
if (Array.isArray(records)) {
return collection(records);
} else {
return resource(records);
}
};
if (arguments.length === 3) {
// legacy behavior
this.collectionName = collectionName;
this.opts = opts;
return this.serialize(records);
} else {
// treat as a reusable serializer
this.collectionName = collectionName;
this.opts = records;
}
};
},{"./serializer-utils":6,"lodash/isFunction":171,"lodash/mapValues":182}],8:[function(require,module,exports){
"use strict";
module.exports = require('./lib/Inflector');
},{"./lib/Inflector":10}],9:[function(require,module,exports){
(function (process,global){
'use strict';
var hasProp = require('./hasProp');
var remove = require('./remove');
var icPart = require('./icPart');
function Inflections() {
this.plurals = [];
this.singulars = [];
this.uncountables = [];
this.humans = [];
this.acronyms = {};
this.acronymRegex = /(?=a)b/;
}
Inflections.getInstance = function(locale) {
var storage = typeof process !== 'undefined' ? process : global;
storage.__Inflector_Inflections = storage.__Inflector_Inflections || {};
storage.__Inflector_Inflections[locale] = storage.__Inflector_Inflections[locale] || new Inflections();
return storage.__Inflector_Inflections[locale];
};
Inflections.prototype.acronym = function(word) {
this.acronyms[word.toLowerCase()] = word;
var values = [];
for (var key in this.acronyms) {
if (hasProp(this.acronyms, key)) {
values.push(this.acronyms[key]);
}
}
this.acronymRegex = new RegExp(values.join('|'));
};
Inflections.prototype.plural = function(rule, replacement) {
if (typeof rule === 'string') {
remove(this.uncountables, rule);
}
remove(this.uncountables, replacement);
this.plurals.unshift([rule, replacement]);
};
Inflections.prototype.singular = function(rule, replacement) {
if (typeof rule === 'string') {
remove(this.uncountables, rule);
}
remove(this.uncountables, replacement);
this.singulars.unshift([rule, replacement]);
};
Inflections.prototype.irregular = function(singular, plural) {
remove(this.uncountables, singular);
remove(this.uncountables, plural);
var s0 = singular[0];
var sRest = singular.substr(1);
var p0 = plural[0];
var pRest = plural.substr(1);
if (s0.toUpperCase() === p0.toUpperCase()) {
this.plural(new RegExp('(' + s0 + ')' + sRest + '$', 'i'), '$1' + pRest);
this.plural(new RegExp('(' + p0 + ')' + pRest + '$', 'i'), '$1' + pRest);
this.singular(new RegExp('(' + s0 + ')' + sRest + '$', 'i'), '$1' + sRest);
this.singular(new RegExp('(' + p0 + ')' + pRest + '$', 'i'), '$1' + sRest);
} else {
var sRestIC = icPart(sRest);
var pRestIC = icPart(pRest);
this.plural(new RegExp(s0.toUpperCase() + sRestIC + '$'), p0.toUpperCase() + pRest);
this.plural(new RegExp(s0.toLowerCase() + sRestIC + '$'), p0.toLowerCase() + pRest);
this.plural(new RegExp(p0.toUpperCase() + pRestIC + '$'), p0.toUpperCase() + pRest);
this.plural(new RegExp(p0.toLowerCase() + pRestIC + '$'), p0.toLowerCase() + pRest);
this.singular(new RegExp(s0.toUpperCase() + sRestIC + '$'), s0.toUpperCase() + sRest);
this.singular(new RegExp(s0.toLowerCase() + sRestIC + '$'), s0.toLowerCase() + sRest);
this.singular(new RegExp(p0.toUpperCase() + pRestIC + '$'), s0.toUpperCase() + sRest);
this.singular(new RegExp(p0.toLowerCase() + pRestIC + '$'), s0.toLowerCase() + sRest);
}
};
Inflections.prototype.uncountable = function() {
var words = Array.prototype.slice.call(arguments, 0);
this.uncountables = this.uncountables.concat(words);
};
Inflections.prototype.human = function(rule, replacement) {
this.humans.unshift([rule, replacement]);
};
Inflections.prototype.clear = function(scope) {
scope = scope || 'all';
if (scope === 'all') {
this.plurals = [];
this.singulars = [];
this.uncountables = [];
this.humans = [];
} else {
this[scope] = [];
}
};
module.exports = Inflections;
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./hasProp":14,"./icPart":15,"./remove":17,"_process":196}],10:[function(require,module,exports){
'use strict';
var Inflections = require('./Inflections');
var Transliterator = require('./Transliterator');
var Methods = require('./Methods');
var defaults = require('./defaults');
var isFunc = require('./isFunc');
var Inflector = Methods;
Inflector.inflections = function(locale, fn) {
if (isFunc(locale)) {
fn = locale;
locale = null;
}
locale = locale || 'en';
if (fn) {
fn(Inflections.getInstance(locale));
} else {
return Inflections.getInstance(locale);
}
};
Inflector.transliterations = function(locale, fn) {
if (isFunc(locale)) {
fn = locale;
locale = null;
}
locale = locale || 'en';
if (fn) {
fn(Transliterator.getInstance(locale));
} else {
return Transliterator.getInstance(locale);
}
}
for (var locale in defaults) {
Inflector.inflections(locale, defaults[locale]);
}
module.exports = Inflector;
},{"./Inflections":9,"./Methods":11,"./Transliterator":12,"./defaults":13,"./isFunc":16}],11:[function(require,module,exports){
'use strict';
var Methods = {
pluralize: function(word, locale) {
locale = locale || 'en';
return this._applyInflections(word, this.inflections(locale).plurals);
},
singularize: function(word, locale) {
locale = locale || 'en';
return this._applyInflections(word, this.inflections(locale).singulars);
},
camelize: function(term, uppercaseFirstLetter) {
if (uppercaseFirstLetter === null || uppercaseFirstLetter === undefined) {
uppercaseFirstLetter = true;
}
var result = '' + term, self = this;
if (uppercaseFirstLetter) {
result = result.replace(/^[a-z\d]*/, function(a) {
return self.inflections().acronyms[a] || self.capitalize(a);
});
} else {
result = result.replace(new RegExp('^(?:' + this.inflections().acronymRegex.source + '(?=\\b|[A-Z_])|\\w)'), function(a) {
return a.toLowerCase();
});
}
result = result.replace(/(?:_|(\/))([a-z\d]*)/gi, function(match, a, b, idx, string) {
a || (a = '');
return '' + a + (self.inflections().acronyms[b] || self.capitalize(b));
});
return result;
},
underscore: function(camelCasedWord) {
var result = '' + camelCasedWord;
result = result.replace(new RegExp('(?:([A-Za-z\\d])|^)(' + this.inflections().acronymRegex.source + ')(?=\\b|[^a-z])', 'g'), function(match, $1, $2) {
return '' + ($1 || '') + ($1 ? '_' : '') + $2.toLowerCase();
});
result = result.replace(/([A-Z\d]+)([A-Z][a-z])/g, '$1_$2');
result = result.replace(/([a-z\d])([A-Z])/g, '$1_$2');
result = result.replace(/-/g, '_');
return result.toLowerCase();
},
humanize: function(lowerCaseAndUnderscoredWord, options) {
var result = '' + lowerCaseAndUnderscoredWord;
var humans = this.inflections().humans;
var human, rule, replacement;
var self = this;
options = options || {};
if (options.capitalize === null || options.capitalize === undefined) {
options.capitalize = true;
}
for (var i = 0, ii = humans.length; i < ii; i++) {
human = humans[i];
rule = human[0];
replacement = human[1];
if (rule.test && rule.test(result) || result.indexOf(rule) > -1) {
result = result.replace(rule, replacement);
break;
}
}
result = result.replace(/_id$/, '');
result = result.replace(/_/g, ' ');
result = result.replace(/([a-z\d]*)/gi, function(match) {
return self.inflections().acronyms[match] || match.toLowerCase();
});
if (options.capitalize) {
result = result.replace(/^\w/, function(match) {
return match.toUpperCase();
});
}
return result;
},
capitalize: function(str) {
var result = str === null || str === undefined ? '' : String(str);
return result.charAt(0).toUpperCase() + result.slice(1);
},
titleize: function(word) {
return this.humanize(this.underscore(word)).replace(/(^|[\s¿\/]+)([a-z])/g, function(match, boundary, letter, idx, string) {
return match.replace(letter, letter.toUpperCase());
});
},
tableize: function(className) {
return this.pluralize(this.underscore(className));
},
classify: function(tableName) {
return this.camelize(this.singularize(tableName.replace(/.*\./g, '')));
},
dasherize: function(underscoredWord) {
return underscoredWord.replace(/_/g, '-');
},
foreignKey: function(className, separateWithUnderscore) {
if (separateWithUnderscore === null || separateWithUnderscore === undefined) {
separateWithUnderscore = true;
}
return this.underscore(className) + (separateWithUnderscore ? '_id' : 'id');
},
ordinal: function(number) {
var absNumber = Math.abs(Number(number));
var mod100 = absNumber % 100;
if (mod100 === 11 || mod100 === 12 || mod100 === 13) {
return 'th';
} else {
switch (absNumber % 10) {
case 1: return 'st';
case 2: return 'nd';
case 3: return 'rd';
default: return 'th';
}
}
},
ordinalize: function(number) {
return '' + number + this.ordinal(number);
},
transliterate: function(string, options) {
options = options || {};
var locale = options.locale || 'en';
var replacement = options.replacement || '?';
return this.transliterations(locale).transliterate(string, replacement);
},
parameterize: function(string, options) {
options = options || {};
if (options.separator === undefined) {
options.separator = '-';
}
if (options.separator === null) {
options.separator = '';
}
// replace accented chars with their ascii equivalents
var result = this.transliterate(string, options);
result = result.replace(/[^a-z0-9\-_]+/ig, options.separator);
if (options.separator.length) {
var separatorRegex = new RegExp(options.separator);
// no more than one of the separator in a row
result = result.replace(new RegExp(separatorRegex.source + '{2,}'), options.separator);
// remove leading/trailing separator
result = result.replace(new RegExp('^' + separatorRegex.source + '|' + separatorRegex.source + '$', 'i'), '');
}
return result.toLowerCase();
},
_applyInflections: function(word, rules) {
var result = '' + word, rule, regex, replacement;
if (result.length === 0) {
return result;
} else {
var match = result.toLowerCase().match(/\b\w+$/);
if (match && this.inflections().uncountables.indexOf(match[0]) > -1) {
return result;
} else {
for (var i = 0, ii = rules.length; i < ii; i++) {
rule = rules[i];
regex = rule[0];
replacement = rule[1];
if (result.match(regex)) {
result = result.replace(regex, replacement);
break;
}
}
return result;
}
}
}
};
module.exports = Methods;
},{}],12:[function(require,module,exports){
(function (process,global){
'use strict';
var DEFAULT_APPROXIMATIONS = {
'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE',
'Ç': 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I',
'Î': 'I', 'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O',
'Õ': 'O', 'Ö': 'O', '×': 'x', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U',
'Ü': 'U', 'Ý': 'Y', 'Þ': 'Th', 'ß': 'ss', 'à': 'a', 'á': 'a', 'â': 'a',
'ã': 'a', 'ä': 'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 'è': 'e', 'é': 'e',
'ê': 'e', 'ë': 'e', 'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 'ð': 'd',
'ñ': 'n', 'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ø': 'o',
'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y',
'Ā': 'A', 'ā': 'a', 'Ă': 'A', 'ă': 'a', 'Ą': 'A', 'ą': 'a', 'Ć': 'C',
'ć': 'c', 'Ĉ': 'C', 'ĉ': 'c', 'Ċ': 'C', 'ċ': 'c', 'Č': 'C', 'č': 'c',
'Ď': 'D', 'ď': 'd', 'Đ': 'D', 'đ': 'd', 'Ē': 'E', 'ē': 'e', 'Ĕ': 'E',
'ĕ': 'e', 'Ė': 'E', 'ė': 'e', 'Ę': 'E', 'ę': 'e', 'Ě': 'E', 'ě': 'e',
'Ĝ': 'G', 'ĝ': 'g', 'Ğ': 'G', 'ğ': 'g', 'Ġ': 'G', 'ġ': 'g', 'Ģ': 'G',
'ģ': 'g', 'Ĥ': 'H', 'ĥ': 'h', 'Ħ': 'H', 'ħ': 'h', 'Ĩ': 'I', 'ĩ': 'i',
'Ī': 'I', 'ī': 'i', 'Ĭ': 'I', 'ĭ': 'i', 'Į': 'I', 'į': 'i', 'İ': 'I',
'ı': 'i', 'IJ': 'IJ', 'ij': 'ij', 'Ĵ': 'J', 'ĵ': 'j', 'Ķ': 'K', 'ķ': 'k',
'ĸ': 'k', 'Ĺ': 'L', 'ĺ': 'l', 'Ļ': 'L', 'ļ': 'l', 'Ľ': 'L', 'ľ': 'l',
'Ŀ': 'L', 'ŀ': 'l', 'Ł': 'L', 'ł': 'l', 'Ń': 'N', 'ń': 'n', 'Ņ': 'N',
'ņ': 'n', 'Ň': 'N', 'ň': 'n', 'ʼn': '\'n', 'Ŋ': 'NG', 'ŋ': 'ng',
'Ō': 'O', 'ō': 'o', 'Ŏ': 'O', 'ŏ': 'o', 'Ő': 'O', 'ő': 'o', 'Œ': 'OE',
'œ': 'oe', 'Ŕ': 'R', 'ŕ': 'r', 'Ŗ': 'R', 'ŗ': 'r', 'Ř': 'R', 'ř': 'r',
'Ś': 'S', 'ś': 's', 'Ŝ': 'S', 'ŝ': 's', 'Ş': 'S', 'ş': 's', 'Š': 'S',
'š': 's', 'Ţ': 'T', 'ţ': 't', 'Ť': 'T', 'ť': 't', 'Ŧ': 'T', 'ŧ': 't',
'Ũ': 'U', 'ũ': 'u', 'Ū': 'U', 'ū': 'u', 'Ŭ': 'U', 'ŭ': 'u', 'Ů': 'U',
'ů': 'u', 'Ű': 'U', 'ű': 'u', 'Ų': 'U', 'ų': 'u', 'Ŵ': 'W', 'ŵ': 'w',
'Ŷ': 'Y', 'ŷ': 'y', 'Ÿ': 'Y', 'Ź': 'Z', 'ź': 'z', 'Ż': 'Z', 'ż': 'z',
'Ž': 'Z', 'ž': 'z'
};
var DEFAULT_REPLACEMENT_CHAR = '?';
function Transliterator() {
this.approximations = {};
for (var c in DEFAULT_APPROXIMATIONS) {
this.approximate(c, DEFAULT_APPROXIMATIONS[c]);
}
}
Transliterator.getInstance = function(locale) {
var storage = typeof process !== 'undefined' ? process : global;
storage.__Inflector_Transliterator = storage.__Inflector_Transliterator || {};
storage.__Inflector_Transliterator[locale] = storage.__Inflector_Transliterator[locale] || new Transliterator();
return storage.__Inflector_Transliterator[locale];
};
Transliterator.prototype.approximate = function(string, replacement) {
this.approximations[string] = replacement;
};
Transliterator.prototype.transliterate = function(string, replacement) {
var self = this;
return string.replace(/[^\u0000-\u007f]/g, function(c) {
return self.approximations[c] || replacement || DEFAULT_REPLACEMENT_CHAR;
});
};
module.exports = Transliterator;
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"_process":196}],13:[function(require,module,exports){
'use strict';
function enDefaults(inflect) {
inflect.plural(/$/, 's');
inflect.plural(/s$/i, 's');
inflect.plural(/^(ax|test)is$/i, '$1es');
inflect.plural(/(octop|vir)us$/i, '$1i');
inflect.plural(/(octop|vir)i$/i, '$1i');
inflect.plural(/(alias|status)$/i, '$1es');
inflect.plural(/(bu)s$/i, '$1ses');
inflect.plural(/(buffal|tomat)o$/i, '$1oes');
inflect.plural(/([ti])um$/i, '$1a');
inflect.plural(/([ti])a$/i, '$1a');
inflect.plural(/sis$/i, 'ses');
inflect.plural(/(?:([^f])fe|([lr])f)$/i, '$1$2ves');
inflect.plural(/(hive)$/i, '$1s');
inflect.plural(/([^aeiouy]|qu)y$/i, '$1ies');
inflect.plural(/(x|ch|ss|sh)$/i, '$1es');
inflect.plural(/(matr|vert|ind)(?:ix|ex)$/i, '$1ices');
inflect.plural(/^(m|l)ouse$/i, '$1ice');
inflect.plural(/^(m|l)ice$/i, '$1ice');
inflect.plural(/^(ox)$/i, '$1en');
inflect.plural(/^(oxen)$/i, '$1');
inflect.plural(/(quiz)$/i, '$1zes');
inflect.singular(/s$/i, '');
inflect.singular(/(ss)$/i, '$1');
inflect.singular(/(n)ews$/i, '$1ews');
inflect.singular(/([ti])a$/i, '$1um');
inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '$1sis');
inflect.singular(/(^analy)(sis|ses)$/i, '$1sis');
inflect.singular(/([^f])ves$/i, '$1fe');
inflect.singular(/(hive)s$/i, '$1');
inflect.singular(/(tive)s$/i, '$1');
inflect.singular(/([lr])ves$/i, '$1f');
inflect.singular(/([^aeiouy]|qu)ies$/i, '$1y');
inflect.singular(/(s)eries$/i, '$1eries');
inflect.singular(/(m)ovies$/i, '$1ovie');
inflect.singular(/(x|ch|ss|sh)es$/i, '$1');
inflect.singular(/^(m|l)ice$/i, '$1ouse');
inflect.singular(/(bus)(es)?$/i, '$1');
inflect.singular(/(o)es$/i, '$1');
inflect.singular(/(shoe)s$/i, '$1');
inflect.singular(/(cris|test)(is|es)$/i, '$1is');
inflect.singular(/^(a)x[ie]s$/i, '$1xis');
inflect.singular(/(octop|vir)(us|i)$/i, '$1us');
inflect.singular(/(alias|status)(es)?$/i, '$1');
inflect.singular(/^(ox)en/i, '$1');
inflect.singular(/(vert|ind)ices$/i, '$1ex');
inflect.singular(/(matr)ices$/i, '$1ix');
inflect.singular(/(quiz)zes$/i, '$1');
inflect.singular(/(database)s$/i, '$1');
inflect.irregular('person', 'people');
inflect.irregular('man', 'men');
inflect.irregular('child', 'children');
inflect.irregular('sex', 'sexes');
inflect.irregular('move', 'moves');
inflect.irregular('zombie', 'zombies');
inflect.uncountable('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep', 'jeans', 'police');
}
module.exports = {
en: enDefaults
};
},{}],14:[function(require,module,exports){
'use strict';
var hasOwnProp = Object.prototype.hasOwnProperty;
function hasProp(obj, key) {
return hasOwnProp.call(obj, key);
}
module.exports = hasProp;
},{}],15:[function(require,module,exports){
'use strict';
function icPart(str) {
return str.split('').map(function(c) { return '(?:' + [c.toUpperCase(), c.toLowerCase()].join('|') + ')'; }).join('')
}
module.exports = icPart;
},{}],16:[function(require,module,exports){
'use strict';
var toString = Object.prototype.toString;
function isFunc(obj) {
return toString.call(obj) === '[object Function]';
}
module.exports = isFunc;
},{}],17:[function(require,module,exports){
'use strict';
var splice = Array.prototype.splice;
function remove(arr, elem) {
for (var i = arr.length - 1; i >= 0; i--) {
if (arr[i] === elem) {
splice.call(arr, i, 1);
}
}
}
module.exports = remove;
},{}],18:[function(require,module,exports){
var getNative = require('./_getNative'),
root = require('./_root');
/* Built-in method references that are verified to be native. */
var DataView = getNative(root, 'DataView');
module.exports = DataView;
},{"./_getNative":97,"./_root":139}],19:[function(require,module,exports){
var hashClear = require('./_hashClear'),
hashDelete = require('./_hashDelete'),
hashGet = require('./_hashGet'),
hashHas = require('./_hashHas'),
hashSet = require('./_hashSet');
/**
* Creates a hash object.
*
* @private
* @constructor
* @param {Array} [entries] The key-value pairs to cache.
*/
function Hash(entries) {
var index = -1,
length = entries == null ? 0 : entries.length;
this.clear();
while (++index < length) {
var entry = entries[index];
this.set(entry[0], entry[1]);
}
}
// Add methods to `Hash`.
Hash.prototype.clear = hashClear;
Hash.prototype['delete'] = hashDelete;
Hash.prototype.get = hashGet;
Hash.prototype.has = hashHas;
Hash.prototype.set = hashSet;
module.exports = Hash;
},{"./_hashClear":105,"./_hashDelete":106,"./_hashGet":107,"./_hashHas":108,"./_hashSet":109}],20:[function(require,module,exports){
var listCacheClear = require('./_listCacheClear'),
listCacheDelete = require('./_listCacheDelete'),
listCacheGet = require('./_listCacheGet'),
listCacheHas = require('./_listCacheHas'),
listCacheSet = require('./_listCacheSet');
/**
* Creates an list cache object.
*
* @private
* @constructor
* @param {Array} [entries] The key-value pairs to cache.
*/
function ListCache(entries) {
var index = -1,
length = entries == null ? 0 : entries.length;
this.clear();
while (++index < length) {
var entry = entries[index];
this.set(entry[0], entry[1]);
}
}
// Add methods to `ListCache`.
ListCache.prototype.clear = listCacheClear;
ListCache.prototype['delete'] = listCacheDelete;
ListCache.prototype.get = listCacheGet;
ListCache.prototype.has = listCacheHas;
ListCache.prototype.set = listCacheSet;
module.exports = ListCache;
},{"./_listCacheClear":119,"./_listCacheDelete":120,"./_listCacheGet":121,"./_listCacheHas":122,"./_listCacheSet":123}],21:[function(require,module,exports){
var getNative = require('./_getNative'),
root = require('./_root');
/* Built-in method references that are verified to be native. */
var Map = getNative(root, 'Map');
module.exports = Map;
},{"./_getNative":97,"./_root":139}],22:[function(require,module,exports){
var mapCacheClear = require('./_mapCacheClear'),
mapCacheDelete = require('./_mapCacheDelete'),
mapCacheGet = require('./_mapCacheGet'),
mapCacheHas = require('./_mapCacheHas'),
mapCacheSet = require('./_mapCacheSet');
/**
* Creates a map cache object to store key-value pairs.
*
* @private
* @constructor
* @param {Array} [entries] The key-value pairs to cache.
*/
function MapCache(entries) {
var index = -1,
length = entries == null ? 0 : entries.length;
this.clear();
while (++index < length) {
var entry = entries[index];
this.set(entry[0], entry[1]);
}
}
// Add methods to `MapCache`.
MapCache.prototype.clear = mapCacheClear;
MapCache.prototype['delete'] = mapCacheDelete;
MapCache.prototype.get = mapCacheGet;
MapCache.prototype.has = mapCacheHas;
MapCache.prototype.set = mapCacheSet;
module.exports = MapCache;
},{"./_mapCacheClear":124,"./_mapCacheDelete":125,"./_mapCacheGet":126,"./_mapCacheHas":127,"./_mapCacheSet":128}],23:[function(require,module,exports){
var getNative = require('./_getNative'),
root = require('./_root');
/* Built-in method references that are verified to be native. */
var Promise = getNative(root, 'Promise');
module.exports = Promise;
},{"./_getNative":97,"./_root":139}],24:[function(require,module,exports){
var getNative = require('./_getNative'),
root = require('./_root');
/* Built-in method references that are verified to be native. */
var Set = getNative(root, 'Set');
module.exports = Set;
},{"./_getNative":97,"./_root":139}],25:[function(require,module,exports){
var MapCache = require('./_MapCache'),
setCacheAdd = require('./_setCacheAdd'),
setCacheHas = require('./_setCacheHas');
/**
*
* Creates an array cache object to store unique values.
*
* @private
* @constructor
* @param {Array} [values] The values to cache.
*/
function SetCache(values) {
var index = -1,
length = values == null ? 0 : values.length;
this.__data__ = new MapCache;
while (++index < length) {
this.add(values[index]);
}
}
// Add methods to `SetCache`.
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
SetCache.prototype.has = setCacheHas;
module.exports = SetCache;
},{"./_MapCache":22,"./_setCacheAdd":141,"./_setCacheHas":142}],26:[function(require,module,exports){
var ListCache = require('./_ListCache'),
stackClear = require('./_stackClear'),
stackDelete = require('./_stackDelete'),
stackGet = require('./_stackGet'),
stackHas = require('./_stackHas'),
stackSet = require('./_stackSet');
/**
* Creates a stack cache object to store key-value pairs.
*
* @private
* @constructor
* @param {Array} [entries] The key-value pairs to cache.
*/
function Stack(entries) {
var data = this.__data__ = new ListCache(entries);
this.size = data.size;
}
// Add methods to `Stack`.
Stack.prototype.clear = stackClear;
Stack.prototype['delete'] = stackDelete;
Stack.prototype.get = stackGet;
Stack.prototype.has = stackHas;
Stack.prototype.set = stackSet;
module.exports = Stack;
},{"./_ListCache":20,"./_stackClear":146,"./_stackDelete":147,"./_stackGet":148,"./_stackHas":149,"./_stackSet":150}],27:[function(require,module,exports){
var root = require('./_root');
/** Built-in value references. */
var Symbol = root.Symbol;
module.exports = Symbol;
},{"./_root":139}],28:[function(require,module,exports){
var root = require('./_root');
/** Built-in value references. */
var Uint8Array = root.Uint8Array;
module.exports = Uint8Array;
},{"./_root":139}],29:[function(require,module,exports){
var getNative = require('./_getNative'),
root = require('./_root');
/* Built-in method references that are verified to be native. */
var WeakMap = getNative(root, 'WeakMap');
module.exports = WeakMap;
},{"./_getNative":97,"./_root":139}],30:[function(require,module,exports){
/**
* A faster alternative to `Function#apply`, this function invokes `func`
* with the `this` binding of `thisArg` and the arguments of `args`.
*
* @private
* @param {Function} func The function to invoke.
* @param {*} thisArg The `this` binding of `func`.
* @param {Array} args The arguments to invoke `func` with.
* @returns {*} Returns the result of `func`.
*/
function apply(func, thisArg, args) {
switch (args.length) {
case 0: return func.call(thisArg);
case 1: return func.call(thisArg, args[0]);
case 2: return func.call(thisArg, args[0], args[1]);
case 3: return func.call(thisArg, args[0], args[1], args[2]);
}
return func.apply(thisArg, args);
}
module.exports = apply;
},{}],31:[function(require,module,exports){
/**
* A specialized version of `_.forEach` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array} Returns `array`.
*/
function arrayEach(array, iteratee) {
var index = -1,
length = array == null ? 0 : array.length;
while (++index < length) {
if (iteratee(array[index], index, array) === false) {
break;
}
}
return array;
}
module.exports = arrayEach;
},{}],32:[function(require,module,exports){
/**
* A specialized version of `_.filter` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} predicate The function invoked per iteration.
* @returns {Array} Returns the new filtered array.
*/
function arrayFilter(array, predicate) {
var index = -1,
length = array == null ? 0 : array.length,
resIndex = 0,
result = [];
while (++index < length) {
var value = array[index];
if (predicate(value, index, array)) {
result[resIndex++] = value;
}
}
return result;
}
module.exports = arrayFilter;
},{}],33:[function(require,module,exports){
var baseTimes = require('./_baseTimes'),
isArguments = require('./isArguments'),
isArray = require('./isArray'),
isBuffer = require('./isBuffer'),
isIndex = require('./_isIndex'),
isTypedArray = require('./isTypedArray');
/** Used for built-in method references. */
var objectProto = Object.prototype;
/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* Creates an array of the enumerable property names of the array-like `value`.
*
* @private
* @param {*} value The value to query.
* @param {boolean} inherited Specify returning inherited property names.
* @returns {Array} Returns the array of property names.
*/
function arrayLikeKeys(value, inherited) {
var isArr = isArray(value),
isArg = !isArr && isArguments(value),
isBuff = !isArr && !isArg && isBuffer(value),
isType = !isArr && !isArg && !isBuff && isTypedArray(value),
skipIndexes = isArr || isArg || isBuff || isType,
result = skipIndexes ? baseTimes(value.length, String) : [],
length = result.length;
for (var key in value) {
if ((inherited || hasOwnProperty.call(value, key)) &&
!(skipIndexes && (
// Safari 9 has enumerable `arguments.length` in strict mode.
key == 'length' ||
// Node.js 0.10 has enumerable non-index properties on buffers.
(isBuff && (key == 'offset' || key == 'parent')) ||
// PhantomJS 2 has enumerable non-index properties on typed arrays.
(isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
// Skip index properties.
isIndex(key, length)
))) {
result.push(key);
}
}
return result;
}
module.exports = arrayLikeKeys;
},{"./_baseTimes":71,"./_isIndex":112,"./isArguments":166,"./isArray":167,"./isBuffer":170,"./isTypedArray":178}],34:[function(require,module,exports){
/**
* A specialized version of `_.map` for arrays without support for iteratee
* shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array} Returns the new mapped array.
*/
function arrayMap(array, iteratee) {
var index = -1,
length = array == null ? 0 : array.length,
result = Array(length);
while (++index < length) {
result[index] = iteratee(array[index], index, array);
}
return result;
}
module.exports = arrayMap;
},{}],35:[function(require,module,exports){
/**
* Appends the elements of `values` to `array`.
*
* @private
* @param {Array} array The array to modify.
* @param {Array} values The values to append.
* @returns {Array} Returns `array`.
*/
function arrayPush(array, values) {
var index = -1,
length = values.length,
offset = array.length;
while (++index < length) {
array[offset + index] = values[index];
}
return array;
}
module.exports = arrayPush;
},{}],36:[function(require,module,exports){
/**
* A specialized version of `_.some` for arrays without support for iteratee
* shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} predicate The function invoked per iteration.
* @returns {boolean} Returns `true` if any element passes the predicate check,
* else `false`.
*/
function arraySome(array, predicate) {
var index = -1,
length = array == null ? 0 : array.length;
while (++index < length) {
if (predicate(array[index], index, array)) {
return true;
}
}
return false;
}
module.exports = arraySome;
},{}],37:[function(require,module,exports){
var baseAssignValue = require('./_baseAssignValue'),
eq = require('./eq');
/**
* This function is like `assignValue` except that it doesn't assign
* `undefined` values.
*
* @private
* @param {Object} object The object to modify.
* @param {string} key The key of the property to assign.
* @param {*} value The value to assign.
*/