index.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. const _ = require('lodash')
  2. const config = require('../../config')
  3. const bcrypt = require('bcrypt')
  4. const sequelize = require('./sequelize')
  5. const User = require('./user')
  6. const Session = require('./session')
  7. const Role = require('./role')
  8. const setup = require('./setup')
  9. const { dict } = require('../util')
  10. const { Op } = require('sequelize')
  11. const UserRole = User.belongsToMany(Role, { through: 'userRoles' })
  12. const isUUID = (str) =>
  13. typeof str === 'string' &&
  14. /^[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)
  15. const fetch = async (Type, refs) => {
  16. if (!Array.isArray(refs)) {
  17. return (await fetch(Type, [refs]))[0]
  18. }
  19. let ret = refs.slice(0)
  20. const keys = []
  21. const ids = []
  22. for (let ref of refs) {
  23. if (isUUID(ref)) ids.push(ref)
  24. else if (typeof ref === 'string') keys.push(ref)
  25. }
  26. if (keys.length || ids.length) {
  27. const or = []
  28. if (ids.length) or.push({
  29. id: {
  30. [Op.in]: ids
  31. }
  32. })
  33. if (keys.length) or.push({
  34. key: {
  35. [Op.in]: keys
  36. }
  37. })
  38. const recs = dict(await Type.findAll({
  39. where: {
  40. [Op.or]: or
  41. }
  42. }))
  43. if (recs.length !== ids.length + keys.length) {
  44. const missing = [
  45. ...ids.filter(id => !recs[id]),
  46. ...keys.filter(key => !recs[key])
  47. ].join(', ')
  48. throw new Error(`Not all references retrieved. Expected ${ids.length + keys.length}, got ${recs.length}. Missing ${missing} from ${Type.name}.`)
  49. }
  50. ret = ret.map(ref => recs[ref] || ref)
  51. }
  52. return dict(ret)
  53. }
  54. const upsert = async (Type, object, fields) => {
  55. if (!fields) {
  56. fields = ['key']
  57. }
  58. for (var field of fields) {
  59. if (!object[field]) {
  60. throw new Error(`Missing upsert field '${field}' in ${JSON.stringify(object)}.`)
  61. }
  62. }
  63. const existing = await Type.findOne({where: _.pick(object, fields)})
  64. let record
  65. if (existing) {
  66. Object.assign(existing, object)
  67. await existing.save()
  68. record = existing
  69. } else {
  70. record = await Type.create(object)
  71. }
  72. for (let assoc of Object.values(Type.associations)) {
  73. if (object[assoc.as]) {
  74. if (assoc.associationType === 'BelongsToMany' || assoc.associationType === 'BelongsTo') {
  75. const recs = await fetch(assoc.target, object[assoc.as])
  76. await assoc.set(record, recs)
  77. }
  78. }
  79. }
  80. return record
  81. }
  82. const fill = (Type, objects, fields) => Promise.all(objects.map(object =>
  83. upsert(Type, object, fields)
  84. ))
  85. module.exports = {
  86. init: () => {
  87. //return sequelize.sync()
  88. },
  89. sequelize,
  90. User,
  91. Session,
  92. Role,
  93. UserRole,
  94. upsert,
  95. setup,
  96. fill,
  97. fetch
  98. }