Upgrade lodash to v4 and lint more files (#8495)

* common: import lodash modules separately

* remove test/content from .eslintignore, fix with eslint --fix content/index

* lint test/content

* lint content/index except for lodash methods

* upgrade server/models

* upgrade server/middlewares and server/libs

* port server/controllers/top-level

* port server/controllers/api-v3

* port views and tests

* client old port lodash and _(, missing _.

* upgrade client-old

* port common/script (root level files only)

* port common/script/fns

* port common/libs

* port common/script/ops

* port common/script/content and common/script/libs/shops.js

* misc fixes

* misc fixes

* misc fixes

* more tests fixes

* fix payments test stubbing, down to 2 failing tests

* remove more instances of lodash wrapping

* fix bug where toObject does not clone object

* fix tests

* upgrade migration or add lodash 4 note

* update shrinkwrap

* fix linting

* upgrade eslint-config-habitrpg

* update shrinkwrap

* recompile shrinkwrap
This commit is contained in:
Matteo Pagliazzi
2017-03-01 17:10:48 +01:00
committed by GitHub
parent ef02e59590
commit 98c019a0b6
150 changed files with 4996 additions and 1533 deletions

View File

@@ -1,6 +1,6 @@
import content from '../content/index';
import i18n from '../i18n';
import { get } from 'lodash';
import get from 'lodash/get';
let achievs = {};
let achievsContent = content.achievements;

View File

@@ -1,5 +1,5 @@
import _ from 'lodash';
import get from 'lodash/get';
// TODO remove completely, only used in client
module.exports = _.get;
module.exports = get;

View File

@@ -1,5 +1,5 @@
import _ from 'lodash';
import set from 'lodash/set';
// TODO remove completely, only used in client
module.exports = _.set;
module.exports = set;

View File

@@ -1,4 +1,5 @@
import _ from 'lodash';
import isEmpty from 'lodash/isEmpty';
import filter from 'lodash/filter';
/*
are any tags active?
@@ -7,7 +8,7 @@ are any tags active?
// TODO move to client
module.exports = function noTags (tags) {
return _.isEmpty(tags) || _.isEmpty(_.filter(tags, (t) => {
return isEmpty(tags) || isEmpty(filter(tags, (t) => {
return t;
}));
};

View File

@@ -1,13 +1,15 @@
// An utility to pick deep properties from an object.
// Works like _.pick but supports nested props (ie pickDeep(obj, ['deep.property']))
import _ from 'lodash';
import each from 'lodash/each';
import set from 'lodash/set';
import get from 'lodash/get';
module.exports = function pickDeep (obj, properties) {
if (!_.isArray(properties)) throw new Error('"properties" must be an array');
if (!Array.isArray(properties)) throw new Error('"properties" must be an array');
let result = {};
_.each(properties, (prop) => _.set(result, prop, _.get(obj, prop)));
each(properties, (prop) => set(result, prop, get(obj, prop)));
return result;
};

View File

@@ -1,10 +1,10 @@
import moment from 'moment';
import _ from 'lodash';
import filter from 'lodash/filter';
// TODO used only in v2
module.exports = function preenTodos (tasks) {
return _.filter(tasks, (t) => {
return filter(tasks, (t) => {
return !t.completed || t.challenge && t.challenge.id || moment(t.dateCompleted).isAfter(moment().subtract({
days: 3,
}));

View File

@@ -1,4 +1,5 @@
import _ from 'lodash';
import values from 'lodash/values';
import keys from 'lodash/keys';
function trueRandom () {
return Math.random();
@@ -7,7 +8,7 @@ function trueRandom () {
// Get a random property from an object
// returns random property (the value)
module.exports = function randomVal (obj, options = {}) {
let array = options.key ? _.keys(obj) : _.values(obj);
let array = options.key ? keys(obj) : values(obj);
let random = options.predictableRandom || trueRandom();
array.sort();

View File

@@ -1,4 +1,6 @@
import _ from 'lodash';
import isEmpty from 'lodash/isEmpty';
import maxBy from 'lodash/maxBy';
import values from 'lodash/values';
import uuid from './uuid';
/*
@@ -8,7 +10,7 @@ import uuid from './uuid';
*/
module.exports = function refPush (reflist, item) {
item.sort = _.isEmpty(reflist) ? 0 : _.max(reflist, 'sort').sort + 1;
item.sort = isEmpty(reflist) ? 0 : maxBy(values(reflist), 'sort').sort + 1;
if (!(item.id && !reflist[item.id])) {
item.id = uuid();

View File

@@ -1,5 +1,11 @@
import _ from 'lodash';
import pickBy from 'lodash.pickby'; // Not available in lodash 3
import values from 'lodash/values';
import map from 'lodash/map';
import keys from 'lodash/keys';
import each from 'lodash/each';
import eachRight from 'lodash/eachRight';
import toArray from 'lodash/toArray';
import pickBy from 'lodash/pickBy';
import sortBy from 'lodash/sortBy';
import content from '../content/index';
import i18n from '../i18n';
@@ -22,10 +28,9 @@ shops.getMarketCategories = function getMarket (user, language) {
notes: i18n.t('dropsExplanation', language),
};
eggsCategory.items = _(content.questEggs)
.values()
eggsCategory.items = sortBy(values(content.questEggs)
.filter(egg => egg.canBuy(user))
.concat(_.values(content.dropEggs))
.concat(values(content.dropEggs))
.map(egg => {
return {
key: egg.key,
@@ -37,7 +42,7 @@ shops.getMarketCategories = function getMarket (user, language) {
currency: 'gems',
purchaseType: 'eggs',
};
}).sortBy('key').value();
}), 'key');
categories.push(eggsCategory);
let hatchingPotionsCategory = {
@@ -45,8 +50,7 @@ shops.getMarketCategories = function getMarket (user, language) {
text: i18n.t('hatchingPotions', language),
notes: i18n.t('dropsExplanation', language),
};
hatchingPotionsCategory.items = _(content.hatchingPotions)
.values()
hatchingPotionsCategory.items = sortBy(values(content.hatchingPotions)
.filter(hp => !hp.limited)
.map(hatchingPotion => {
return {
@@ -59,7 +63,7 @@ shops.getMarketCategories = function getMarket (user, language) {
currency: 'gems',
purchaseType: 'hatchingPotions',
};
}).sortBy('key').value();
}), 'key');
categories.push(hatchingPotionsCategory);
let premiumHatchingPotionsCategory = {
@@ -67,8 +71,7 @@ shops.getMarketCategories = function getMarket (user, language) {
text: i18n.t('magicHatchingPotions', language),
notes: i18n.t('premiumPotionNoDropExplanation', language),
};
premiumHatchingPotionsCategory.items = _(content.hatchingPotions)
.values()
premiumHatchingPotionsCategory.items = sortBy(values(content.hatchingPotions)
.filter(hp => hp.limited && hp.canBuy())
.map(premiumHatchingPotion => {
return {
@@ -81,7 +84,7 @@ shops.getMarketCategories = function getMarket (user, language) {
currency: 'gems',
purchaseType: 'hatchingPotions',
};
}).sortBy('key').value();
}), 'key');
categories.push(premiumHatchingPotionsCategory);
let foodCategory = {
@@ -89,8 +92,7 @@ shops.getMarketCategories = function getMarket (user, language) {
text: i18n.t('food', language),
notes: i18n.t('dropsExplanation', language),
};
foodCategory.items = _(content.food)
.values()
foodCategory.items = sortBy(values(content.food)
.filter(food => food.canDrop || food.key === 'Saddle')
.map(foodItem => {
return {
@@ -103,7 +105,7 @@ shops.getMarketCategories = function getMarket (user, language) {
currency: 'gems',
purchaseType: 'food',
};
}).sortBy('key').value();
}), 'key');
categories.push(foodCategory);
return categories;
@@ -112,13 +114,13 @@ shops.getMarketCategories = function getMarket (user, language) {
shops.getQuestShopCategories = function getQuestShopCategories (user, language) {
let categories = [];
_.each(content.userCanOwnQuestCategories, type => {
each(content.userCanOwnQuestCategories, type => {
let category = {
identifier: type,
text: i18n.t(`${type}Quests`, language),
};
category.items = _(content.questsByLevel)
category.items = content.questsByLevel
.filter(quest => quest.canBuy(user) && quest.category === type)
.map(quest => {
let locked = lockQuest(quest, user);
@@ -137,7 +139,7 @@ shops.getQuestShopCategories = function getQuestShopCategories (user, language)
class: locked ? `inventory_quest_scroll_locked inventory_quest_scroll_${quest.key}_locked` : `inventory_quest_scroll inventory_quest_scroll_${quest.key}`,
purchaseType: 'quests',
};
}).value();
});
categories.push(category);
});
@@ -190,7 +192,7 @@ shops.getTimeTravelersCategories = function getTimeTravelersCategories (user, la
purchaseAll: true,
};
category.items = _.map(set.items, item => {
category.items = map(set.items, item => {
return {
key: item.key,
text: item.text(language),
@@ -228,19 +230,19 @@ shops.getSeasonalShopCategories = function getSeasonalShopCategories (user, lang
let categories = [];
let flatGearArray = _.toArray(content.gear.flat);
let flatGearArray = toArray(content.gear.flat);
let spells = pickBy(content.spells.special, (spell, key) => {
return _.indexOf(AVAILABLE_SPELLS, key) !== -1;
return AVAILABLE_SPELLS.indexOf(key) !== -1;
});
if (_.keys(spells).length > 0) {
if (keys(spells).length > 0) {
let category = {
identifier: 'spells',
text: i18n.t('seasonalItems', language),
};
category.items = _.map(spells, (spell, key) => {
category.items = map(spells, (spell, key) => {
return {
key,
text: spell.text(language),
@@ -258,16 +260,16 @@ shops.getSeasonalShopCategories = function getSeasonalShopCategories (user, lang
}
let quests = pickBy(content.quests, (quest, key) => {
return _.indexOf(AVAILABLE_QUESTS, key) !== -1;
return AVAILABLE_QUESTS.indexOf(key) !== -1;
});
if (_.keys(quests).length > 0) {
if (keys(quests).length > 0) {
let category = {
identifier: 'quests',
text: i18n.t('quests', language),
};
category.items = _.map(quests, (quest, key) => {
category.items = map(quests, (quest, key) => {
return {
key,
text: quest.text(language),
@@ -294,12 +296,9 @@ shops.getSeasonalShopCategories = function getSeasonalShopCategories (user, lang
text: AVAILABLE_SETS[key],
};
category.items = _(flatGearArray).filter((gear) => {
if (gear.index !== key) {
return false;
}
return user.items.gear.owned[gear.key] === undefined;
}).where({index: key}).map(gear => {
category.items = flatGearArray.filter((gear) => {
return user.items.gear.owned[gear.key] === undefined && gear.index === key;
}).map(gear => {
return {
key: gear.key,
text: gear.text(language),
@@ -312,7 +311,8 @@ shops.getSeasonalShopCategories = function getSeasonalShopCategories (user, lang
purchaseType: 'gear',
class: `shop_${gear.key}`,
};
}).value();
});
if (category.items.length > 0) {
categories.push(category);
}
@@ -325,23 +325,22 @@ shops.getSeasonalShopCategories = function getSeasonalShopCategories (user, lang
shops.getBackgroundShopSets = function getBackgroundShopSets (language) {
let sets = [];
_.eachRight(content.backgrounds, (group, key) => {
eachRight(content.backgrounds, (group, key) => {
let set = {
identifier: key,
text: i18n.t(key, language),
};
set.items = _(group)
.map((background, bgKey) => {
return {
key: bgKey,
text: background.text(language),
notes: background.notes(language),
value: background.price,
currency: background.currency || 'gems',
purchaseType: 'backgrounds',
};
}).value();
set.items = map(group, (background, bgKey) => {
return {
key: bgKey,
text: background.text(language),
notes: background.notes(language),
value: background.price,
currency: background.currency || 'gems',
purchaseType: 'backgrounds',
};
});
sets.push(set);
});

View File

@@ -1,4 +1,6 @@
import _ from 'lodash';
import each from 'lodash/each';
import get from 'lodash/get';
import values from 'lodash/values';
import content from '../content/index';
import * as statHelpers from '../statHelpers';
@@ -11,9 +13,9 @@ function equipmentStatBonusComputed (stat, user) {
// if toObject doesn't exist, we're on the client side and can assume the object is already plain JSON
// see http://stackoverflow.com/questions/25767334/underscore-js-keys-and-omit-not-working-as-expected
let equipped = user.items.gear.equipped;
let equippedKeys = !equipped.toObject ? _.values(equipped) : _.values(equipped.toObject());
let equippedKeys = values(!equipped.toObject ? equipped : equipped.toObject());
_.each(equippedKeys, (equippedItem) => {
each(equippedKeys, (equippedItem) => {
let equipmentStat = gear[equippedItem][stat];
let classBonusMultiplier = gear[equippedItem].klass === user.stats.class ||
gear[equippedItem].specialClass === user.stats.class ? 0.5 : 0;
@@ -35,9 +37,9 @@ module.exports = function statsComputed (user) {
buff: {},
levelBonus: {},
};
_.each(['per', 'con', 'str', 'int'], (stat) => {
let baseStat = _.get(user, 'stats')[stat];
let buff = _.get(user, 'stats.buffs')[stat];
each(['per', 'con', 'str', 'int'], (stat) => {
let baseStat = get(user, 'stats')[stat];
let buff = get(user, 'stats.buffs')[stat];
let equipmentBonus = equipmentStatBonusComputed(stat, user);
statBreakdown[stat] = equipmentBonus.gearBonus + equipmentBonus.classBonus + baseStat + buff;

View File

@@ -1,5 +1,5 @@
import { v4 as uuid } from 'uuid';
import _ from 'lodash';
import defaults from 'lodash/defaults';
import moment from 'moment';
// Even though Mongoose handles task defaults, we want to make sure defaults are set on the client-side before
@@ -15,7 +15,7 @@ module.exports = function taskDefaults (task = {}) {
}
let defaultId = uuid();
let defaults = {
let defaultTaskObj = {
_id: defaultId,
text: task._id || defaultId,
notes: '',
@@ -31,16 +31,16 @@ module.exports = function taskDefaults (task = {}) {
updatedAt: new Date(),
};
_.defaults(task, defaults);
defaults(task, defaultTaskObj);
if (task.type === 'habit' || task.type === 'daily') {
_.defaults(task, {
defaults(task, {
history: [],
});
}
if (task.type === 'todo' || task.type === 'daily') {
_.defaults(task, {
defaults(task, {
completed: false,
collapseChecklist: false,
checklist: [],
@@ -48,7 +48,7 @@ module.exports = function taskDefaults (task = {}) {
}
if (task.type === 'habit') {
_.defaults(task, {
defaults(task, {
up: true,
down: true,
frequency: 'daily',
@@ -58,7 +58,7 @@ module.exports = function taskDefaults (task = {}) {
}
if (task.type === 'daily') {
_.defaults(task, {
defaults(task, {
streak: 0,
repeat: {
m: true,

View File

@@ -1,9 +1,13 @@
import _ from 'lodash';
import each from 'lodash/each';
import lodashFind from 'lodash/find';
import filter from 'lodash/filter';
import sortBy from 'lodash/sortBy';
import reduce from 'lodash/reduce';
import content from '../content/index';
// Return the list of gear items available for purchase
let sortOrder = _.reduce(content.gearTypes, (accumulator, val, key) => {
let sortOrder = reduce(content.gearTypes, (accumulator, val, key) => {
accumulator[val] = key;
return accumulator;
}, {});
@@ -11,15 +15,15 @@ let sortOrder = _.reduce(content.gearTypes, (accumulator, val, key) => {
module.exports = function updateStore (user) {
let changes = [];
_.each(content.gearTypes, (type) => {
let found = _.find(content.gear.tree[type][user.stats.class], (item) => {
each(content.gearTypes, (type) => {
let found = lodashFind(content.gear.tree[type][user.stats.class], (item) => {
return !user.items.gear.owned[item.key];
});
if (found) changes.push(found);
});
changes = changes.concat(_.filter(content.gear.flat, (val) => {
changes = changes.concat(filter(content.gear.flat, (val) => {
if (['special', 'mystery', 'armoire'].indexOf(val.klass) !== -1 && !user.items.gear.owned[val.key] && (val.canOwn ? val.canOwn(user) : false)) {
return true;
} else {
@@ -27,5 +31,5 @@ module.exports = function updateStore (user) {
}
}));
return _.sortBy(changes, (change) => sortOrder[change.type]);
return sortBy(changes, (change) => sortOrder[change.type]);
};