|
|
@@ -6,9 +6,55 @@ const User = require('./user')
|
|
|
const Session = require('./session')
|
|
|
const Role = require('./role')
|
|
|
const setup = require('./setup')
|
|
|
+const { dict } = require('../util')
|
|
|
+const { Op } = require('sequelize')
|
|
|
|
|
|
const UserRole = User.belongsToMany(Role, { through: 'userRoles' })
|
|
|
|
|
|
+const isUUID = (str) =>
|
|
|
+ typeof str === 'string' &&
|
|
|
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(str)
|
|
|
+
|
|
|
+const fetch = async (Type, refs) => {
|
|
|
+ if (!Array.isArray(refs)) {
|
|
|
+ return (await fetch(Type, [refs]))[0]
|
|
|
+ }
|
|
|
+ let ret = refs.slice(0)
|
|
|
+ const keys = []
|
|
|
+ const ids = []
|
|
|
+ for (let ref of refs) {
|
|
|
+ if (isUUID(ref)) ids.push(ref)
|
|
|
+ else if (typeof ref === 'string') keys.push(ref)
|
|
|
+ }
|
|
|
+ if (keys.length || ids.length) {
|
|
|
+ const or = []
|
|
|
+ if (ids.length) or.push({
|
|
|
+ id: {
|
|
|
+ [Op.in]: ids
|
|
|
+ }
|
|
|
+ })
|
|
|
+ if (keys.length) or.push({
|
|
|
+ key: {
|
|
|
+ [Op.in]: keys
|
|
|
+ }
|
|
|
+ })
|
|
|
+ const recs = dict(await Type.findAll({
|
|
|
+ where: {
|
|
|
+ [Op.or]: or
|
|
|
+ }
|
|
|
+ }))
|
|
|
+ if (recs.length !== ids.length + keys.length) {
|
|
|
+ const missing = [
|
|
|
+ ...ids.filter(id => !recs[id]),
|
|
|
+ ...keys.filter(key => !recs[key])
|
|
|
+ ].join(', ')
|
|
|
+ throw new Error(`Not all references retrieved. Expected ${ids.length + keys.length}, got ${recs.length}. Missing ${missing} from ${Type.name}.`)
|
|
|
+ }
|
|
|
+ ret = ret.map(ref => recs[ref] || ref)
|
|
|
+ }
|
|
|
+ return dict(ret)
|
|
|
+}
|
|
|
+
|
|
|
const upsert = async (Type, object, fields) => {
|
|
|
if (!fields) {
|
|
|
fields = ['key']
|
|
|
@@ -19,15 +65,31 @@ const upsert = async (Type, object, fields) => {
|
|
|
}
|
|
|
}
|
|
|
const existing = await Type.findOne({where: _.pick(object, fields)})
|
|
|
+ let record
|
|
|
if (existing) {
|
|
|
Object.assign(existing, object)
|
|
|
await existing.save()
|
|
|
- return existing
|
|
|
+ record = existing
|
|
|
} else {
|
|
|
- return await Type.create(object)
|
|
|
+ record = await Type.create(object)
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let assoc of Object.values(Type.associations)) {
|
|
|
+ if (object[assoc.as]) {
|
|
|
+ if (assoc.associationType === 'BelongsToMany' || assoc.associationType === 'BelongsTo') {
|
|
|
+ const recs = await fetch(assoc.target, object[assoc.as])
|
|
|
+ await assoc.set(record, recs)
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ return record
|
|
|
}
|
|
|
|
|
|
+const fill = (Type, objects, fields) => Promise.all(objects.map(object =>
|
|
|
+ upsert(Type, object, fields)
|
|
|
+))
|
|
|
+
|
|
|
module.exports = {
|
|
|
init: () => {
|
|
|
//return sequelize.sync()
|
|
|
@@ -38,5 +100,7 @@ module.exports = {
|
|
|
Role,
|
|
|
UserRole,
|
|
|
upsert,
|
|
|
- setup
|
|
|
+ setup,
|
|
|
+ fill,
|
|
|
+ fetch
|
|
|
}
|