index.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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. paranoid: false
  43. }))
  44. if (recs.length !== ids.length + keys.length) {
  45. const missing = [
  46. ...ids.filter(id => !recs[id]),
  47. ...keys.filter(key => !recs[key])
  48. ].join(', ')
  49. throw new Error(`Not all references retrieved. Expected ${ids.length + keys.length}, got ${recs.length}. Missing ${missing} from ${Type.name}.`)
  50. }
  51. ret = ret.map(ref => recs[ref] || ref)
  52. }
  53. return dict(ret)
  54. }
  55. const upsert = async (Type, object, fields) => {
  56. if (!fields) {
  57. fields = ['key']
  58. }
  59. for (var field of fields) {
  60. if (!object[field]) {
  61. throw new Error(`Missing upsert field '${field}' in ${JSON.stringify(object)}.`)
  62. }
  63. }
  64. const existing = await Type.findOne({where: _.pick(object, fields), paranoid: false})
  65. let record
  66. if (existing) {
  67. Object.assign(existing, object)
  68. await existing.save()
  69. record = existing
  70. } else {
  71. record = await Type.create(object)
  72. }
  73. for (let assoc of Object.values(Type.associations)) {
  74. if (object[assoc.as]) {
  75. if (assoc.associationType === 'BelongsToMany' || assoc.associationType === 'BelongsTo') {
  76. const recs = await fetch(assoc.target, object[assoc.as])
  77. await assoc.set(record, recs)
  78. }
  79. }
  80. }
  81. return record
  82. }
  83. const fill = (Type, objects, fields) => Promise.all(objects.map(object =>
  84. upsert(Type, object, fields)
  85. ))
  86. module.exports = {
  87. init: () => {
  88. //return sequelize.sync()
  89. },
  90. sequelize,
  91. User,
  92. Session,
  93. Role,
  94. UserRole,
  95. upsert,
  96. setup,
  97. fill,
  98. fetch
  99. }