@codetanzania/ewea-common
Version:
Common utilities for EWEA
1,685 lines (1,541 loc) • 120 kB
JavaScript
'use strict';
const eweaInternals = require('@codetanzania/ewea-internals');
const constants = require('@lykmapipo/constants');
const lodash = require('lodash');
const common = require('@lykmapipo/common');
const env = require('@lykmapipo/env');
const mongooseCommon = require('@lykmapipo/mongoose-common');
const mongooseLocaleSchema = require('mongoose-locale-schema');
const async = require('async');
const file = require('@lykmapipo/file');
const path = require('path');
const phone = require('@lykmapipo/phone');
const logger = require('@lykmapipo/logger');
const geoTools = require('@lykmapipo/geo-tools');
const predefine = require('@lykmapipo/predefine');
const permission = require('@lykmapipo/permission');
const emisStakeholder = require('@codetanzania/emis-stakeholder');
const DEFAULT_PREDEFINE_NAME = env.getString(
'DEFAULT_PREDEFINE_NAME',
'Unknown'
);
const DEFAULT_PREDEFINE_COLOR = env.getString(
'DEFAULT_PREDEFINE_COLOR',
'#6D9EEB'
);
const DEFAULT_PREDEFINE_WEIGHT = env.getNumber(
'DEFAULT_PREDEFINE_WEIGHT',
1000
);
const DEFAULT_PREDEFINE_RELATION = {
_id: null,
strings: {
name: mongooseLocaleSchema.localizedValuesFor({ en: DEFAULT_PREDEFINE_NAME }),
abbreviation: mongooseLocaleSchema.localizedAbbreviationsFor({ en: DEFAULT_PREDEFINE_NAME }),
color: DEFAULT_PREDEFINE_COLOR,
},
numbers: { weight: DEFAULT_PREDEFINE_WEIGHT },
};
const DEFAULT_UNIT_NAME = env.getString(
'DEFAULT_UNIT_NAME',
eweaInternals.PREDEFINE_UNIT_NAME
);
const DEFAULT_ADMINISTRATIVELEVEL_NAME = env.getString(
'DEFAULT_ADMINISTRATIVELEVEL_NAME',
eweaInternals.PREDEFINE_ADMINISTRATIVELEVEL_NAME
);
const DEFAULT_FEATURETYPE_NAME = env.getString(
'DEFAULT_FEATURETYPE_NAME',
eweaInternals.PREDEFINE_FEATURETYPE_NAME
);
const DEFAULT_EVENTINDICATOR_NAME = env.getString(
'DEFAULT_EVENTINDICATOR_NAME',
eweaInternals.PREDEFINE_EVENTINDICATOR_NAME
);
const DEFAULT_EVENTTOPIC_NAME = env.getString(
'DEFAULT_EVENTTOPIC_NAME',
eweaInternals.PREDEFINE_EVENTTOPIC_NAME
);
const DEFAULT_EVENTLEVEL_NAME = env.getString(
'DEFAULT_EVENTLEVEL_NAME',
eweaInternals.PREDEFINE_EVENTLEVEL_NAME
);
const DEFAULT_EVENTSEVERITY_NAME = env.getString(
'DEFAULT_EVENTSEVERITY_NAME',
eweaInternals.PREDEFINE_EVENTSEVERITY_NAME
);
const DEFAULT_EVENTCERTAINTY_NAME = env.getString(
'DEFAULT_EVENTCERTAINTY_NAME',
eweaInternals.PREDEFINE_EVENTCERTAINTY_NAME
);
const DEFAULT_EVENTSTATUS_NAME = env.getString(
'DEFAULT_EVENTSTATUS_NAME',
eweaInternals.PREDEFINE_EVENTSTATUS_NAME
);
const DEFAULT_EVENTURGENCY_NAME = env.getString(
'DEFAULT_EVENTURGENCY_NAME',
eweaInternals.PREDEFINE_EVENTURGENCY_NAME
);
const DEFAULT_EVENTRESPONSE_NAME = env.getString(
'DEFAULT_EVENTRESPONSE_NAME',
eweaInternals.PREDEFINE_EVENTRESPONSE_NAME
);
const DEFAULT_PARTYGROUP_NAME = env.getString(
'DEFAULT_PARTYGROUP_NAME',
eweaInternals.PREDEFINE_PARTYGROUP_NAME
);
const DEFAULT_PARTYROLE_NAME = env.getString(
'DEFAULT_PARTYROLE_NAME',
eweaInternals.PREDEFINE_PARTYROLE_NAME
);
const DEFAULT_EVENTGROUP_NAME = env.getString(
'DEFAULT_EVENTGROUP_NAME',
eweaInternals.PREDEFINE_EVENTGROUP_NAME
);
const DEFAULT_EVENTTYPE_NAME = env.getString(
'DEFAULT_EVENTTYPE_NAME',
eweaInternals.PREDEFINE_EVENTTYPE_NAME
);
const DEFAULT_EVENTFUNCTION_NAME = env.getString(
'DEFAULT_EVENTFUNCTION_NAME',
eweaInternals.PREDEFINE_EVENTFUNCTION_NAME
);
const DEFAULT_EVENTACTION_NAME = env.getString(
'DEFAULT_EVENTACTION_NAME',
eweaInternals.PREDEFINE_EVENTACTION_NAME
);
const DEFAULT_EVENTQUESTION_NAME = env.getString(
'DEFAULT_EVENTQUESTION_NAME',
eweaInternals.PREDEFINE_EVENTQUESTION_NAME
);
const DEFAULT_ADMINISTRATIVEAREA_NAME = env.getString(
'DEFAULT_ADMINISTRATIVEAREA_NAME',
eweaInternals.PREDEFINE_ADMINISTRATIVEAREA_NAME
);
const DEFAULT_EVENT_NUMBER = env.getString(
'DEFAULT_EVENT_NUMBER',
undefined
);
const DEFAULT_NAMES = common.sortedUniq([
DEFAULT_UNIT_NAME,
DEFAULT_ADMINISTRATIVELEVEL_NAME,
DEFAULT_FEATURETYPE_NAME,
DEFAULT_EVENTINDICATOR_NAME,
DEFAULT_EVENTTOPIC_NAME,
DEFAULT_EVENTLEVEL_NAME,
DEFAULT_EVENTSEVERITY_NAME,
DEFAULT_EVENTCERTAINTY_NAME,
DEFAULT_EVENTSTATUS_NAME,
DEFAULT_EVENTURGENCY_NAME,
DEFAULT_EVENTRESPONSE_NAME,
DEFAULT_PARTYGROUP_NAME,
DEFAULT_PARTYROLE_NAME,
DEFAULT_EVENTGROUP_NAME,
DEFAULT_EVENTTYPE_NAME,
DEFAULT_EVENTFUNCTION_NAME,
DEFAULT_EVENTACTION_NAME,
DEFAULT_EVENTQUESTION_NAME,
DEFAULT_ADMINISTRATIVEAREA_NAME,
]);
// TODO update for all modules?
const DEFAULT_PATHS = common.mergeObjects(
{
unit: { namespace: eweaInternals.PREDEFINE_NAMESPACE_UNIT },
role: { namespace: eweaInternals.PREDEFINE_NAMESPACE_PARTYROLE },
template: { namespace: eweaInternals.PREDEFINE_NAMESPACE_NOTIFICATIONTEMPLATE },
},
eweaInternals.EVENT_RELATIONS
);
const DEFAULT_SEEDS_IGNORE = [
eweaInternals.PREDEFINE_NAMESPACE_FEATURETYPE,
eweaInternals.PREDEFINE_NAMESPACE_EVENTINDICATOR,
eweaInternals.PREDEFINE_NAMESPACE_EVENTTOPIC,
eweaInternals.PREDEFINE_NAMESPACE_VEHICLE,
eweaInternals.PREDEFINE_NAMESPACE_EVENTFUNCTION,
eweaInternals.PREDEFINE_NAMESPACE_EVENTACTION,
eweaInternals.PREDEFINE_NAMESPACE_EVENTQUESTION,
eweaInternals.PREDEFINE_NAMESPACE_FEATURE,
eweaInternals.PREDEFINE_NAMESPACE_EVENTACTIONCATALOGUE,
eweaInternals.PREDEFINE_NAMESPACE_NOTIFICATIONTEMPLATE,
];
const DEFAULT_SEEDS = lodash.mapValues(
lodash.omit(eweaInternals.PREDEFINE_DEFAULTS, ...DEFAULT_SEEDS_IGNORE),
(defaultValue, namespace) => {
return {
_id: mongooseCommon.objectIdFor(eweaInternals.MODEL_NAME_PREDEFINE, namespace, defaultValue),
namespace,
strings: {
name: mongooseLocaleSchema.localizedValuesFor({ en: defaultValue }),
abbreviation: mongooseLocaleSchema.localizedAbbreviationsFor({ en: defaultValue }),
color: DEFAULT_PREDEFINE_COLOR,
},
numbers: { weight: DEFAULT_PREDEFINE_WEIGHT },
booleans: { default: true, system: true },
};
}
);
// TODO: move to internal or common or dispatch?
// TODO: use constants
const COMMON_VEHICLESTATUSES = {
Waiting: { weight: 1, name: 'Waiting', abbreviation: 'WTN' },
Enroute: { weight: 2, name: 'Enroute', abbreviation: 'ERT' },
Canceled: {
weight: DEFAULT_PREDEFINE_WEIGHT,
name: 'Canceled',
abbreviation: 'CNL',
},
AtPickup: { weight: 4, name: 'At Pickup', abbreviation: 'APU' },
FromPickup: { weight: 5, name: 'From Pickup', abbreviation: 'FPU' },
AtDropoff: { weight: 6, name: 'At Dropoff', abbreviation: 'ADO' },
FromDropoff: { weight: 7, name: 'From Dropoff', abbreviation: 'FDO' },
Completed: { weight: 8, name: 'Completed', abbreviation: 'CPT' },
Idle: { weight: DEFAULT_PREDEFINE_WEIGHT, name: 'Idle', abbreviation: 'IDL' },
};
const COMMON_VEHICLESTATUS_SEEDS = lodash.mapValues(
COMMON_VEHICLESTATUSES,
({ weight, name, abbreviation }) => {
const namespace = eweaInternals.PREDEFINE_NAMESPACE_VEHICLESTATUS;
return {
_id: mongooseCommon.objectIdFor(eweaInternals.MODEL_NAME_PREDEFINE, namespace, name),
namespace,
strings: {
name: mongooseLocaleSchema.localizedValuesFor({ en: name }),
abbreviation: mongooseLocaleSchema.localizedValuesFor({ en: abbreviation || name }),
},
numbers: { weight: weight || DEFAULT_PREDEFINE_WEIGHT },
booleans: { system: true },
};
}
);
// TODO: move to ewea-dispatch
const dispatchStatusFor = (optns) => {
// ensure options
const options = common.mergeObjects(optns);
// defaults
let dispatch = COMMON_VEHICLESTATUS_SEEDS.Waiting;
let vehicle = COMMON_VEHICLESTATUS_SEEDS.Idle;
// dispatched
if (options.dispatchedAt) {
dispatch = COMMON_VEHICLESTATUS_SEEDS.Enroute;
vehicle = COMMON_VEHICLESTATUS_SEEDS.Enroute;
}
// canceled
if (options.canceledAt) {
dispatch = COMMON_VEHICLESTATUS_SEEDS.Canceled;
vehicle = COMMON_VEHICLESTATUS_SEEDS.Idle;
}
// arrived at pickup
if (options.pickup && options.pickup.arrivedAt) {
dispatch = COMMON_VEHICLESTATUS_SEEDS.AtPickup;
vehicle = COMMON_VEHICLESTATUS_SEEDS.Enroute;
}
// dispatched from pickup
if (options.pickup && options.pickup.dispatchedAt) {
dispatch = COMMON_VEHICLESTATUS_SEEDS.FromPickup;
vehicle = COMMON_VEHICLESTATUS_SEEDS.Enroute;
}
// arrived at dropoff
if (options.dropoff && options.dropoff.arrivedAt) {
dispatch = COMMON_VEHICLESTATUS_SEEDS.AtDropoff;
vehicle = COMMON_VEHICLESTATUS_SEEDS.Enroute;
}
// dispatched from dropoff
if (options.dropoff && options.dropoff.dispatchedAt) {
dispatch = COMMON_VEHICLESTATUS_SEEDS.FromDropoff;
vehicle = COMMON_VEHICLESTATUS_SEEDS.Enroute;
}
// resolved/completed
if (options.resolvedAt || options.completedAt) {
dispatch = COMMON_VEHICLESTATUS_SEEDS.Completed;
vehicle = COMMON_VEHICLESTATUS_SEEDS.Idle;
}
return { dispatch, vehicle };
};
// TODO: move to ewea-case
const COMMON_CASESTAGES = {
Screening: { weight: 1, name: 'Screening', abbreviation: 'SCRN' },
Suspect: { weight: 2, name: 'Suspect', abbreviation: 'SUSP' },
Probable: { weight: 3, name: 'Probable', abbreviation: 'PROB' },
Confirmed: { weight: 4, name: 'Confirmed', abbreviation: 'CNFD' },
Recovered: { weight: 5, name: 'Recovered', abbreviation: 'REC' },
Followup: { weight: 6, name: 'Followup', abbreviation: 'FOL' },
Died: { weight: 7, name: 'Died', abbreviation: 'DD' },
};
const COMMON_CASESTAGE_SEEDS = lodash.mapValues(
COMMON_CASESTAGES,
({ weight, name, abbreviation }) => {
const namespace = eweaInternals.PREDEFINE_NAMESPACE_CASESTAGE;
return {
_id: mongooseCommon.objectIdFor(eweaInternals.MODEL_NAME_PREDEFINE, namespace, name),
namespace,
strings: {
name: mongooseLocaleSchema.localizedValuesFor({ en: name }),
abbreviation: mongooseLocaleSchema.localizedValuesFor({ en: abbreviation || name }),
},
numbers: { weight: weight || DEFAULT_PREDEFINE_WEIGHT },
booleans: { system: true },
};
}
);
const COMMON_CASESEVERITIES = {
Asymptomatic: { weight: 0, name: 'Asymptomatic', abbreviation: 'ASY' },
Mild: { weight: 2, name: 'Mild', abbreviation: 'MIL' },
Moderate: { weight: 3, name: 'Moderate', abbreviation: 'MOD' },
Severe: { weight: 4, name: 'Severe', abbreviation: 'SEV' },
Critical: { weight: 5, name: 'Critical', abbreviation: 'CRT' },
};
const COMMON_CASESEVERITY_SEEDS = lodash.mapValues(
COMMON_CASESEVERITIES,
({ weight, name, abbreviation }) => {
const namespace = eweaInternals.PREDEFINE_NAMESPACE_CASESEVERITY;
return {
_id: mongooseCommon.objectIdFor(eweaInternals.MODEL_NAME_PREDEFINE, namespace, name),
namespace,
strings: {
name: mongooseLocaleSchema.localizedValuesFor({ en: name }),
abbreviation: mongooseLocaleSchema.localizedValuesFor({ en: abbreviation || name }),
},
numbers: { weight: weight || DEFAULT_PREDEFINE_WEIGHT },
booleans: { system: true },
};
}
);
// TODO move to ewea-case
const caseSeverityFor = (optns) => {
// ensure options
const { score } = common.mergeObjects(optns);
// special
if (score === 0) {
return COMMON_CASESEVERITY_SEEDS.Asymptomatic;
}
// mild
if (score > 0 && score <= 2) {
return COMMON_CASESEVERITY_SEEDS.Mild;
}
// moderate
if (score > 2 && score <= 3) {
return COMMON_CASESEVERITY_SEEDS.Moderate;
}
// severe
if (score > 3 && score <= 4) {
return COMMON_CASESEVERITY_SEEDS.Severe;
}
// critical
if (score > 4) {
return COMMON_CASESEVERITY_SEEDS.Critical;
}
// return default
return DEFAULT_SEEDS[eweaInternals.PREDEFINE_NAMESPACE_CASESEVERITY];
};
/**
* @function connect
* @name connect
* @description Ensure database connection
* @param {Function} done callback to invoke on success or error
* @returns {Error} connection error if failed
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.1.0
* @version 0.1.0
* @static
* @public
* @example
*
* connect(error => { ... });
*/
const connect = (done) => {
return mongooseCommon.connect((error) => {
if (!error && !env.isTest()) {
file.createModels();
}
return done(error);
});
};
/**
* @function syncIndexes
* @name syncIndexes
* @description Synchronize model database indexes
* @param {Function} done callback to invoke on success or error
* @returns {Error|object} error if failed else sync results
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.1.0
* @version 0.1.0
* @static
* @public
* @example
*
* syncIndexes(error => { ... });
*/
const syncIndexes = (done) => async.waterfall([connect, mongooseCommon.syncIndexes], done);
/**
* @function pathFor
* @name pathFor
* @description Derive path from application base
* @param {...string} [paths] valid path to derive from base
* @returns {string} derived path
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* pathFor('seeds');
* => /home/ewea/seeds
*/
const pathFor = (...paths) => {
const base = env.getString('BASE_PATH', process.cwd());
const path$1 = path.join(base, ...paths);
return path$1;
};
/**
* @function dataPathFor
* @name dataPathFor
* @description Derive data path from application base of given file name
* @param {string} fileName valid file name
* @returns {string} valid data path
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* dataPathFor('events.csv');
* => /home/ewea/data/events.csv
*/
const dataPathFor = (fileName) => {
const path$1 = env.getString('DATA_PATH', pathFor('data'));
return path.resolve(path$1, fileName);
};
/**
* @function seedPathFor
* @name seedPathFor
* @description Derive seed path from application base of given file name
* @param {string} fileName valid file name
* @returns {string} valid seed path
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* seedPathFor('events.json');
* => /home/ewea/seeds/events.json
*/
const seedPathFor = (fileName) => {
const path$1 = env.getString('SEED_PATH', pathFor('seeds'));
return path.resolve(path$1, fileName);
};
/**
* @function csvPathFor
* @name csvPathFor
* @description Derive csv seed path of given model name
* @param {string} modelName valid model name or predefine namespace
* @returns {string} valid csv seed path
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* csvPathFor('events');
* => /home/ewea/data/events.csv
*/
const csvPathFor = (modelName) => {
const fileName = `${common.pluralize(lodash.toLower(modelName))}.csv`;
const csvPath = dataPathFor(fileName);
return csvPath;
};
/**
* @function shapeFilePathFor
* @name shapeFilePathFor
* @description Derive shapefile seed path of given model name
* @param {string} modelName valid model name or predefine namespace
* @returns {string} valid shapefile seed path
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* shapeFilePathFor('events');
* => /home/ewea/data/events.shp
*/
const shapeFilePathFor = (modelName) => {
const fileName = `${common.pluralize(lodash.toLower(modelName))}.shp`;
const shapeFilePath = dataPathFor(fileName);
return shapeFilePath;
};
/**
* @function geoJsonPathFor
* @name geoJsonPathFor
* @description Derive geojson seed path of given model name
* @param {string} modelName valid model name or predefine namespace
* @returns {string} valid geojson seed path
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* geoJsonPathFor('events');
* => /home/ewea/data/events.geojson
*/
const geoJsonPathFor = (modelName) => {
const fileName = `${common.pluralize(lodash.toLower(modelName))}.geojson`;
const geoJsonFilePath = dataPathFor(fileName);
return geoJsonFilePath;
};
/**
* @function jsonPathFor
* @name jsonPathFor
* @description Derive json seed path of given model name
* @param {string} modelName valid model name or predefine namespace
* @returns {string} valid json seed path
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* jsonPathFor('events');
* => /home/ewea/seeds/events.json
*/
const jsonPathFor = (modelName) => {
const fileName = `${common.pluralize(lodash.toLower(modelName))}.json`;
const jsonFilePath = dataPathFor(fileName);
return jsonFilePath;
};
/**
* @function transformSeedKeys
* @name transformSeedKeys
* @description Transform and normalize seed keys
* @param {object} seed valid seed
* @returns {object} transformed seed
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* transformSeedKeys({ Name: 'John Doe' });
* => { name: 'John Doe' }
*/
const transformSeedKeys = (seed) => {
// copy seed
const data = common.mergeObjects(seed);
// normalize keys
const transformed = lodash.mapKeys(data, (value, key) => {
// key to lower
// TODO: camelize?
let path = lodash.toLower(lodash.trim(key));
// key to path
path = common.join(lodash.split(path, ' '), '.');
// return normalized key
return path;
});
// return
return transformed;
};
/**
* @function transformGeoFields
* @name transformGeoFields
* @description Transform and normalize seed geo fields
* @param {object} seed valid seed
* @returns {object} transformed seed
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.6.0
* @version 0.1.0
* @static
* @public
* @example
*
* transformGeoFields({ point: '1,2' });
* => { point: { type: 'Point', coordinates: [ 1, 2 ] } }
*/
const transformGeoFields = (seed) => {
// copy seed
const transformed = common.mergeObjects(seed);
// allowed geo fields
const fields = {
location: 'location',
centroid: 'centroid',
point: 'point',
'geos.point': 'geos.point',
circle: 'polygon',
'geos.circle': 'geos.polygon',
polygon: 'polygon',
'geos.polygon': 'geos.polygon',
geometry: 'geometry',
};
// transform geo fields
lodash.forEach(fields, (seedPath, originalPath) => {
// parse coordinates to geometry
try {
const geometry = geoTools.parseCoordinateString(seed[originalPath]);
if (geometry) {
transformed[seedPath] = geometry;
}
} catch (e) {
// ignore on error
}
});
// otherwise tranform longitude and latitude
if (transformed.longitude && transformed.latitude) {
transformed.point = {
type: 'Point',
coordinates: [
Number(transformed.longitude),
Number(transformed.latitude),
],
};
}
// return
return transformed;
};
/**
* @function transformOtherFields
* @name transformOtherFields
* @description Transform and normalize other seed fields
* @param {object} seed valid seed
* @returns {object} transformed seed
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.6.0
* @version 0.1.0
* @static
* @public
* @example
*
* transformOtherFields({ action: '...' });
* => { name: '...', action: '...' }
*/
const transformOtherFields = (seed) => {
// copy seed
const transformed = common.mergeObjects(seed);
// ensure event action catalogue.name from action
if (lodash.isEmpty(transformed.name) && !lodash.isEmpty(transformed.action)) {
transformed.name = transformed.action;
}
// ensure weight from level & order
const weight = lodash.toNumber(transformed.level || transformed.order);
if (!lodash.isNaN(weight)) {
transformed.weight = weight;
transformed.numbers = common.mergeObjects(transformed.numbers, { weight });
}
// return
return transformed;
};
/**
* @function applyTransformsOn
* @name applyTransformsOn
* @description Transform and normalize seed
* @param {object|object[]} seed valid seed(s)
* @param {...Function} [transformers] transform to apply on seed
* @returns {object} transformed seed
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* applyTransformsOn({ Name: 'John Doe' });
* => { name: 'John Doe' }
*/
const applyTransformsOn = (seed, ...transformers) => {
// copy seed
let data = common.compact([].concat(seed));
data = lodash.map(data, (value) => {
// copy value
let transformed = common.mergeObjects(value);
// ensure transformers
const baseTransformers = [
transformSeedKeys,
transformGeoFields,
transformOtherFields,
];
const transforms = common.compact(baseTransformers.concat(transformers));
// apply transform sequentially
lodash.forEach(transforms, (applyTransformOn) => {
transformed = lodash.isFunction(applyTransformOn)
? applyTransformOn(transformed)
: common.mergeObjects(transformed);
});
// return transformed
return transformed;
});
// return
data = lodash.isArray(seed) ? data : lodash.first(data);
return data;
};
/**
* @function transformToPredefineSeed
* @name transformToPredefineSeed
* @description Transform and normalize given seed to predefine seed
* @param {object} seed valid seed
* @returns {object} valid predefine seed
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* transformToPredefineSeed({ Name: 'John Doe' });
* => { strings: { name: { en : 'John Doe' } } }
*/
const transformToPredefineSeed = (seed) => {
// copy seed
const data = common.mergeObjects(seed);
// normalize to predefine
let predefine$1 = predefine.transformToPredefine(data);
predefine$1.raw = data;
// transform relations
// TODO: honor exist populate option
// TODO: handle parent of administrative area using level
const populate = {};
lodash.forEach(eweaInternals.PREDEFINE_RELATIONS, (value, key) => {
const hasRelation = key && seed[key];
if (hasRelation) {
const options = common.mergeObjects(value);
const path = `relations.${options.path || key}`;
const modelName = options.ref || eweaInternals.MODEL_NAME_PREDEFINE;
const namespaces = common.compact([].concat(options.namespace));
const array = options.array || false;
const vals = common.sortedUniq(lodash.split(seed[key], ','));
const match =
modelName === eweaInternals.MODEL_NAME_PREDEFINE
? { 'strings.name.en': { $in: vals }, namespace: { $in: namespaces } }
: { name: { $in: vals } };
// honour administrative area seed hierarchy
const handleAdministrativeArea =
seed.namespace === eweaInternals.PREDEFINE_NAMESPACE_ADMINISTRATIVEAREA &&
key === 'parent' &&
seed.level;
const ignore = handleAdministrativeArea
? {
model: modelName,
path: 'relations.level',
match: {
'strings.name.en': { $in: [seed.level] },
namespace: { $in: [eweaInternals.PREDEFINE_NAMESPACE_ADMINISTRATIVELEVEL] },
},
array: false,
}
: {};
populate[path] = { model: modelName, match, array, ignore };
}
});
predefine$1.populate = populate;
// return
predefine$1 = lodash.omit(predefine$1, ...[...lodash.keys(eweaInternals.PREDEFINE_RELATIONS), 'relations']);
return predefine$1;
};
/**
* @function transformToPartySeed
* @name transformToPartySeed
* @description Transform and normalize given seed to party seed
* @param {object} seed valid seed
* @returns {object} valid party seed
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.6.0
* @version 0.1.0
* @static
* @public
* @example
*
* transformToPartySeed({ Name: 'John Doe' });
* => { name: 'John Doe' }
*/
const transformToPartySeed = (seed) => {
// copy seed
let data = common.mergeObjects(seed);
// generate seed object id
const shouldGenerateId =
!lodash.get(data, '_id') && common.areNotEmpty(data.mobile, data.email);
if (shouldGenerateId) {
lodash.set(
data,
'_id',
mongooseCommon.objectIdFor(eweaInternals.MODEL_NAME_PARTY, phone.toE164(data.mobile), lodash.toLower(data.email))
);
}
// ensure default password
if (lodash.isEmpty(data.password)) {
data.password = env.getString(
'DEFAULT_HASHED_PASSWORD',
// TODO: dynamically hash DEFAULT_PASSWORD
'$2a$10$rwpL/BhU8xY4fkf8SG7fHugF4PCioTJqy8BLU7BZ8N0YV.8Y1dXem'
);
}
// ensure confirmed time
data.confirmedAt = new Date();
// clear lock
data.failedAttempts = 0;
data.lockedAt = null;
data.unlockedAt = null;
data.unlockToken = null;
data.unlockSentAt = null;
data.unlockTokenExpiryAt = null;
// transform relations
const populate = {};
lodash.forEach(eweaInternals.PARTY_RELATIONS, (value, key) => {
const hasRelation = key && data[key];
if (hasRelation) {
const options = common.mergeObjects(value);
const path = `${options.path || key}`;
const modelName = options.ref || eweaInternals.MODEL_NAME_PREDEFINE;
const namespaces = common.compact([].concat(options.namespace));
const array = options.array || false;
const vals = common.sortedUniq(lodash.split(data[key], ','));
const match =
modelName === eweaInternals.MODEL_NAME_PREDEFINE
? { 'strings.name.en': { $in: vals }, namespace: { $in: namespaces } }
: { name: { $in: vals } };
populate[path] = { model: modelName, match, array };
}
});
data.populate = populate;
// return
data = lodash.omit(data, ...[...lodash.keys(eweaInternals.PARTY_RELATIONS), 'relations', 'namespace']);
return data;
};
/**
* @function transformToEventSeed
* @name transformToEventSeed
* @description Transform and normalize given seed to event seed
* @param {object} seed valid seed
* @returns {object} valid event seed
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.6.0
* @version 0.1.0
* @static
* @public
* @example
*
* transformToEventSeed({ Name: 'John Doe' });
* => { name: 'John Doe' }
*/
const transformToEventSeed = (seed) => {
// copy seed
let data = common.mergeObjects(seed);
// generate seed object id
if (!lodash.get(data, '_id') && data.number) {
lodash.set(data, '_id', mongooseCommon.objectIdFor(eweaInternals.MODEL_NAME_EVENT, data.number));
}
// transform relations
const populate = {};
lodash.forEach(eweaInternals.EVENT_RELATIONS, (value, key) => {
const hasRelation = key && data[key];
if (hasRelation) {
const options = common.mergeObjects(value);
const path = `${options.path || key}`;
const modelName = options.ref || eweaInternals.MODEL_NAME_PREDEFINE;
const namespaces = common.compact([].concat(options.namespace));
const array = options.array || false;
const vals = common.sortedUniq(lodash.split(data[key], ','));
const match =
modelName === eweaInternals.MODEL_NAME_PREDEFINE
? { 'strings.name.en': { $in: vals }, namespace: { $in: namespaces } }
: { name: { $in: vals } };
populate[path] = { model: modelName, match, array };
}
});
data.populate = populate;
// return
data = lodash.omit(data, ...[...lodash.keys(eweaInternals.EVENT_RELATIONS), 'relations', 'namespace']);
return data;
};
/**
* @function transformToVehicleDispatchSeed
* @name transformToVehicleDispatchSeed
* @description Transform and normalize given seed to vehicle dispatch seed
* @param {object} seed valid seed
* @returns {object} valid vehicle dispatch seed
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.14.0
* @version 0.1.0
* @static
* @public
* @example
*
* transformToVehicleDispatchSeed({ Name: 'John Doe' });
* => { name: 'John Doe' }
*/
const transformToVehicleDispatchSeed = (seed) => {
// copy seed
let data = common.mergeObjects(seed);
// generate seed object id
if (!lodash.get(data, '_id') && data.number) {
lodash.set(data, '_id', mongooseCommon.objectIdFor(eweaInternals.MODEL_NAME_VEHICLEDISPATCH, data.number));
}
// transform relations
const populate = {};
lodash.forEach(eweaInternals.VEHICLE_DISPATCH_RELATIONS, (value, key) => {
const hasRelation = key && data[key];
if (hasRelation) {
const options = common.mergeObjects(value);
const path = `${options.path || key}`;
const modelName = options.ref || eweaInternals.MODEL_NAME_PREDEFINE;
const namespaces = common.compact([].concat(options.namespace));
const array = options.array || false;
const vals = common.sortedUniq(lodash.split(data[key], ','));
const match =
modelName === eweaInternals.MODEL_NAME_PREDEFINE
? { 'strings.name.en': { $in: vals }, namespace: { $in: namespaces } }
: { name: { $in: vals } };
populate[path] = { model: modelName, match, array };
}
});
data.populate = populate;
// return
data = lodash.omit(
data,
...[...lodash.keys(eweaInternals.VEHICLE_DISPATCH_RELATIONS), 'relations', 'namespace']
);
return data;
};
/**
* @function transformToCaseSeed
* @name transformToCaseSeed
* @description Transform and normalize given seed to case seed
* @param {object} seed valid seed
* @returns {object} valid case seed
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.18.0
* @version 0.1.0
* @static
* @public
* @example
*
* transformToCaseSeed({ Name: 'John Doe' });
* => { name: 'John Doe' }
*/
const transformToCaseSeed = (seed) => {
// TODO: support alias on relation doted path
// copy seed
let data = common.mergeObjects(seed);
// generate seed object id
if (!lodash.get(data, '_id') && data.number) {
lodash.set(data, '_id', mongooseCommon.objectIdFor(eweaInternals.MODEL_NAME_CASE, data.number));
}
// transform relations
const populate = {};
lodash.forEach(eweaInternals.CASE_RELATIONS, (value, key) => {
const hasRelation = key && data[key];
if (hasRelation) {
const options = common.mergeObjects(value);
const path = `${options.path || key}`;
const modelName = options.ref || eweaInternals.MODEL_NAME_PREDEFINE;
const namespaces = common.compact([].concat(options.namespace));
const array = options.array || false;
const vals = common.sortedUniq(lodash.split(data[key], ','));
const match =
modelName === eweaInternals.MODEL_NAME_PREDEFINE
? { 'strings.name.en': { $in: vals }, namespace: { $in: namespaces } }
: { name: { $in: vals } };
populate[path] = { model: modelName, match, array };
}
});
data.populate = populate;
// return
data = lodash.omit(data, ...[...lodash.keys(eweaInternals.CASE_RELATIONS), 'relations', 'namespace']);
return data;
};
/**
* @function readCsvFile
* @name readCsvFile
* @description Read csv seed and apply seed transforms
* @param {string} path valid csv path
* @param {Function[]} [transformers] transforms to apply on seed
* @param {Function} done callback to invoke on next seed
* @returns {object} transformed seed
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* readCsvFile(path, transforms, (error, { finished, feature, next }) => { ... });
*/
const readCsvFile = (path, transformers, done) => {
return geoTools.readCsv({ path }, (error, { finished, feature, next }) => {
let data = feature;
if (!lodash.isEmpty(feature) && next && !finished) {
data = applyTransformsOn(feature, ...transformers);
}
return done(error, { finished, feature: data, next });
});
};
/**
* @function processCsvSeed
* @name processCsvSeed
* @description process each csv row (data)
* @param {object} [optns] valid options
* @param {string} [optns.Model=undefined] valid model name
* @param {object} [optns.properties={}] valid extra properties to merge on each seed
* @param {string} [optns.namespace=undefined] valid predefine namespace
* @param {string} [optns.domain=undefined] valid predefine domain
* @param {boolean} [optns.throws=false] whether to throw error
* @param {Function} done callback to invoke on success or error
* @returns {Function} call back function
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* const options = { Model = undefined, properties = {}, namespace = undefined, throws = false }
* processCsvSeed((options, done) => (error, {finished, feature, next}) => { ... });
*/
const processCsvSeed =
(
{
Model = undefined,
properties = {},
namespace = undefined,
domain = undefined,
throws = false,
},
done
) =>
(error, { finished, feature, next }) => {
// handle file read errors
if (error) {
return throws ? done(error) : done();
}
// handle read finish
if (finished) {
return done();
}
// process datas
if (feature && next) {
// seed data & next chunk from csv read stream
const data = common.mergeObjects(properties, { namespace, domain }, feature);
return Model.seed(data, next);
}
// request next chunk from csv read stream
return next && next();
};
/**
* @function seedFromCsv
* @name seedFromCsv
* @description Seed given model from csv file
* @param {object} optns valid seed options
* @param {string} [optns.modelName] valid model name
* @param {string} [optns.namespace] valid predefine namespace
* @param {string} [optns.domain=undefined] valid predefine domain
* @param {boolean} [optns.throws=false] whether to throw error
* @param {string} [optns.filePath=undefined] valid full file path for csv seed
* @param {object} [optns.properties={}] extra properties to merge on each seed
* @param {Function} [optns.transform] valid seed transform
* @param {Function[]} [optns.transformers] valid predefine transformers
* @param {Function} done callback to invoke on success or error
* @returns {Error|undefined} error if fails else undefined
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.6.0
* @version 0.1.0
* @static
* @public
* @example
*
* const opts = { modelName: ..., transformers: [ ... ] };
* seedFromCsv(optns, error => { ... });
*/
const seedFromCsv = (optns, done) => {
// normalize options
const {
filePath = undefined,
properties = {},
modelName = undefined,
namespace = undefined,
domain = undefined,
throws = true,
transform = (seed) => seed,
transformers = [],
} = common.mergeObjects(optns);
// do: seed data to model if exists
const Model = mongooseCommon.model(modelName);
if (Model) {
// prepare seed options
const isPredefine =
modelName === eweaInternals.MODEL_NAME_PREDEFINE && !lodash.isEmpty(namespace);
const csvFilePath = filePath || csvPathFor(namespace || modelName);
const appliedTransformers = isPredefine
? lodash.map([transformToPredefineSeed, ...transformers, transform], (fn) => {
return (seed) => {
return fn({ namespace, domain, ...seed });
};
})
: [...transformers, transform];
// seed from csv
return readCsvFile(
csvFilePath,
appliedTransformers,
processCsvSeed({ Model, properties, namespace, domain, throws }, done)
);
}
// backoff: no data model found
return done();
};
/**
* @function seedFromJson
* @name seedFromJson
* @description Seed given model from json file
* @param {object} optns valid seed options
* @param {string} [optns.modelName] valid model name
* @param {string} [optns.namespace] valid predefine namespace
* @param {string} [optns.domain=undefined] valid predefine domain
* @param {boolean} [optns.throws=false] whether to throw error
* @param {string} [optns.filePath=undefined] valid full file path for json seed
* @param {object} [optns.properties={}] extra properties to merge on each seed
* @param {Function} [optns.transform] valid seed transform
* @param {Function[]} [optns.transformers] valid predefine transformers
* @param {Function} done callback to invoke on success or error
* @returns {Error|undefined} error if fails else undefined
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.6.0
* @version 0.1.0
* @static
* @public
* @example
*
* const opts = { modelName: ..., transformers: [ ... ] };
* seedFromJson(optns, error => { ... });
*/
const seedFromJson = (optns, done) => {
// normalize options
const {
filePath = undefined,
properties = {},
modelName = undefined,
namespace = undefined,
domain = undefined,
throws = false,
transform = (seed) => seed,
transformers = [],
} = common.mergeObjects(optns);
// do: seed data to model if exists
const Model = mongooseCommon.model(modelName);
if (Model) {
// prepare seed options
const isPredefine =
modelName === eweaInternals.MODEL_NAME_PREDEFINE && !lodash.isEmpty(namespace);
const jsonFilePath = filePath || jsonPathFor(namespace || modelName);
const appliedTransformers = isPredefine
? lodash.map([transformToPredefineSeed, ...transformers, transform], (fn) => {
return (seed) => {
return fn({ namespace, domain, ...seed });
};
})
: [...transformers, transform];
// prepare json seed stages
const path = lodash.endsWith(jsonFilePath, '.json')
? jsonFilePath
: `${jsonFilePath}.json`;
return geoTools.readJson({ path, throws }, (error, data) => {
if (!lodash.isEmpty(data)) {
const doTransform = (seed) => {
const merged = common.mergeObjects(properties, { namespace, domain }, seed);
return applyTransformsOn(merged, ...appliedTransformers);
};
return Model.seed({ data, transform: doTransform }, done);
}
return done(error, data);
});
}
// backoff: no data model found
return done();
};
/**
* @function seedFromSeeds
* @name seedFromSeeds
* @description Seed given model from seeds file
* @param {object} optns valid seed options
* @param {string} [optns.modelName] valid model name
* @param {boolean} [optns.throws=false] whether to throw error
* @param {Function} [optns.filter=undefined] seed data filter
* @param {Function} [optns.transform=undefined] seed data transformer
* @param {Function} done callback to invoke on success or error
* @returns {Error|undefined} error if fails else undefined
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.6.0
* @version 0.1.0
* @static
* @public
* @example
*
* const opts = { modelName: ... };
* seedFromSeeds(optns, error => { ... });
*/
const seedFromSeeds = (optns, done) => {
// TODO: transform relations to populate?
// normalize options
const {
modelName = undefined,
throws = false,
data = undefined,
filter,
transform = (seed) => seed,
transformers = [],
} = common.mergeObjects(optns);
// merge transform & transformers
const doTransform = (seed) => {
const merged = common.mergeObjects(seed);
const appliedTransformers = common.compact(
[].concat(transformers).concat(transform)
);
return applyTransformsOn(merged, ...appliedTransformers);
};
// do: seed data to model if seeds exists
const Model = mongooseCommon.model(modelName);
const canSeed = Model && lodash.isFunction(Model.seed);
if (canSeed) {
// filter, transform & seed
const options = { data, filter, transform: doTransform };
return Model.seed(options, (error, results) => {
// reply with errors
if (throws) {
return done(error, results);
}
// ignore errors
return done(null, results);
});
}
// backoff: no data model found
return done();
};
/**
* @function seedPredefine
* @name seedPredefine
* @description Seed given predefine namespace
* @param {object} optns valid seed options
* @param {string} optns.namespace valid predefine namespace
* @param {string} [optns.domain=undefined] valid predefine domain
* @param {boolean} [optns.throws=false] whether to ignore error
* @param {Function} [optns.transform] valid seed transform
* @param {Function[]} [optns.transformers] valid predefine transformers
* @param {Function} done callback to invoke on success or error
* @returns {Error|undefined} error if fails else undefined
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* seedPredefine(optns, error => { ... });
*/
const seedPredefine = (optns, done) => {
// TODO: default transform(namespace, domain, parent, name code)
// normalize options
const {
modelName = eweaInternals.MODEL_NAME_PREDEFINE,
namespace = undefined,
domain = undefined,
throws = false,
transform = (seed) => seed,
transformers = [],
} = common.mergeObjects(optns);
// prepare namespace filter
const filter = (seed) => seed.namespace === namespace;
// prepare options
const options = {
modelName,
namespace,
domain,
throws,
transform,
transformers,
filter,
};
// prepare predefine seed stages
const fromSeeds = (next) => seedFromSeeds(options, (error) => next(error));
const fromJson = (next) => seedFromJson(options, (error) => next(error));
const fromCsv = (next) => seedFromCsv(options, (error) => next(error));
const stages = [fromCsv, fromJson, fromSeeds];
// do seed predefine
return async.waterfall(stages, done);
};
/**
* @function seedParty
* @name seedParty
* @description Seed given parties
* @param {object} optns valid seed options
* @param {string} optns.type valid party type
* @param {boolean} [optns.throws=false] whether to ignore error
* @param {Function} [optns.transform] valid seed transform
* @param {Function[]} [optns.transformers] valid party transformers
* @param {Function} done callback to invoke on success or error
* @returns {Error|undefined} error if fails else undefined
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* seedParty(optns, error => { ... });
*/
const seedParty = (optns, done) => {
// normalize options
const {
modelName = eweaInternals.MODEL_NAME_PARTY,
type = 'Focal',
throws = false,
transform = (seed) => seed,
transformers = [],
} = common.mergeObjects(optns);
// prepare type filter
const filter = (seed) => seed.type === type;
// prepare options
const options = {
modelName,
namespace: type,
properties: { type },
type,
throws,
transform,
transformers: [transformToPartySeed, ...transformers],
filter,
};
// prepare party seed stages
const fromSeeds = (next) => seedFromSeeds(options, (error) => next(error));
const fromJson = (next) => seedFromJson(options, (error) => next(error));
const fromCsv = (next) => seedFromCsv(options, (error) => next(error));
const stages = [fromCsv, fromJson, fromSeeds];
// do seed party
return async.waterfall(stages, done);
};
/**
* @function seedEvent
* @name seedEvent
* @description Seed given events
* @param {object} optns valid seed options
* @param {boolean} [optns.throws=false] whether to ignore error
* @param {Function} [optns.transform] valid seed transform
* @param {Function[]} [optns.transformers] valid event transformers
* @param {Function} done callback to invoke on success or error
* @returns {Error|undefined} error if fails else undefined
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.3.0
* @version 0.1.0
* @static
* @public
* @example
*
* seedEvent(optns, error => { ... });
*/
const seedEvent = (optns, done) => {
// normalize options
const {
modelName = eweaInternals.MODEL_NAME_EVENT,
throws = false,
transform = (seed) => seed,
transformers = [],
} = common.mergeObjects(optns);
// prepare options
const options = {
modelName,
properties: {},
throws,
transform,
transformers: [transformToEventSeed, ...transformers],
};
// prepare event seed stages
const fromSeeds = (next) => seedFromSeeds(options, (error) => next(error));
const fromJson = (next) => seedFromJson(options, (error) => next(error));
const fromCsv = (next) => seedFromCsv(options, (error) => next(error));
const stages = [fromCsv, fromJson, fromSeeds];
// do seed event
return async.waterfall(stages, done);
};
/**
* @function seedVehicleDispatch
* @name seedVehicleDispatch
* @description Seed given vehicle dispatches
* @param {object} optns valid seed options
* @param {boolean} [optns.throws=false] whether to ignore error
* @param {Function} [optns.transform] valid seed transform
* @param {Function[]} [optns.transformers] valid event transformers
* @param {Function} done callback to invoke on success or error
* @returns {Error|undefined} error if fails else undefined
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.14.0
* @version 0.1.0
* @static
* @public
* @example
*
* seedVehicleDispatch(optns, error => { ... });
*/
const seedVehicleDispatch = (optns, done) => {
// normalize options
const {
modelName = eweaInternals.MODEL_NAME_VEHICLEDISPATCH,
throws = false,
transform = (seed) => seed,
transformers = [],
} = common.mergeObjects(optns);
// prepare options
const options = {
modelName,
properties: {},
throws,
transform,
transformers: [transformToVehicleDispatchSeed, ...transformers],
};
// prepare vehicle dispatch seed stages
const fromSeeds = (next) => seedFromSeeds(options, (error) => next(error));
const fromJson = (next) => seedFromJson(options, (error) => next(error));
const fromCsv = (next) => seedFromCsv(options, (error) => next(error));
const stages = [fromCsv, fromJson, fromSeeds];
// do seed vehicle dispatch
return async.waterfall(stages, done);
};
/**
* @function seedCase
* @name seedCase
* @description Seed given cases
* @param {object} optns valid seed options
* @param {boolean} [optns.throws=false] whether to ignore error
* @param {Function} [optns.transform] valid seed transform
* @param {Function[]} [optns.transformers] valid case transformers
* @param {Function} done callback to invoke on success or error
* @returns {Error|undefined} error if fails else undefined
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.18.0
* @version 0.1.0
* @static
* @public
* @example
*
* seedCase(optns, error => { ... });
*/
const seedCase = (optns, done) => {
// normalize options
const {
modelName = eweaInternals.MODEL_NAME_CASE,
throws = false,
transform = (seed) => seed,
transformers = [],
} = common.mergeObjects(optns);
// prepare options
const options = {
modelName,
properties: {},
throws,
transform,
transformers: [transformToCaseSeed, ...transformers],
};
// prepare case seed stages
const fromSeeds = (next) => seedFromSeeds(options, (error) => next(error));
const fromJson = (next) => seedFromJson(options, (error) => next(error));
const fromCsv = (next) => seedFromCsv(options, (error) => next(error));
const stages = [fromCsv, fromJson, fromSeeds];
// do seed vehicle dispatch
return async.waterfall(stages, done);
};
/**
* @function seedPermissions
* @name seedPermissions
* @description Seed permissions
* @param {Function} done callback to invoke on success or error
* @returns {Error|undefined} error if fails else undefined
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.4.0
* @version 0.1.0
* @static
* @public
* @example
*
* seedPermissions(error => { ... });
*/
const seedPermissions = (done) => {
// TODO: honour wildcard for _id generation
logger.debug('Start Seeding Permissions Data');
// generate object id
const transform = (seed) => {
const merged = common.mergeObjects(
{ _id: mongooseCommon.objectIdFor(eweaInternals.MODEL_NAME_PERMISSION, seed.wildcard) },
seed
);
return merged;
};
// prepare permissions seed stages
// TODO: dashboard permission seeds
const seedResourcePermissions = (next) => {
const data = permission.Permission.prepareResourcesPermissions();
const options = { data, transform };
return permission.Permission.seed(options, (error) => next(error));
};
const seedPredefineNamespacePermissions = (next) => {
const data = predefine.listPermissions();
const options = { data, transform };
return permission.Permission.seed(options, (error) => next(error));
};
const stages = [seedResourcePermissions, seedPredefineNamespacePermissions];
// do seed permissions
return async.waterfall(stages, (error) => {
logger.debug('Finish Seeding Permissions Data');
return done(error);
});
};
/**
* @function seedDefaults
* @name seedDefaults
* @description Seed default predefines
* @param {Function} done callback to invoke on success or error
* @returns {Error|undefined} error if fails else undefined
* @author lally elias <lallyelias87@gmail.com>
* @license MIT
* @since 0.15.0
* @version 0.1.0
* @static
* @public
* @example
*
* seedDefaults(error => { ... });
*/
const seedDefaults = (done) => {
// TODO: honour code for _id generation
logger.debug('Start Seeding Default Predefines Data');
// prepare options
const m