helpers.mjs 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // @ts-check
  2. import { db, getCollectionNames, getCollectionInternal } from './mongodb.mjs'
  3. /**
  4. * @typedef {import('mongodb').Document} Document
  5. * @typedef {import('mongodb').Collection<Document>} Collection
  6. */
  7. /**
  8. * @param {Collection} collection
  9. * @param {Array<{ name: string }>} indexes
  10. * @return {Promise<void>}
  11. */
  12. async function addIndexesToCollection(collection, indexes) {
  13. await Promise.all(
  14. indexes.map(index => {
  15. index.background = true
  16. return collection.createIndex(index.key, index)
  17. })
  18. )
  19. }
  20. /**
  21. * @param {Collection} collection
  22. * @param {Array<{ name: string }>} indexes
  23. * @return {Promise<void>}
  24. */
  25. async function dropIndexesFromCollection(collection, indexes) {
  26. await Promise.all(
  27. indexes.map(async index => {
  28. try {
  29. await collection.dropIndex(index.name)
  30. } catch (err) {
  31. if (err.code === 27 /* IndexNotFound */) {
  32. console.log(`Index ${index.name} not found; drop was a no-op.`)
  33. } else {
  34. throw err
  35. }
  36. }
  37. })
  38. )
  39. }
  40. /**
  41. * @param {string} collectionName
  42. * @return {Promise<void>}
  43. */
  44. async function dropCollection(collectionName) {
  45. if (db[collectionName]) {
  46. throw new Error(`blocking drop of an active collection: ${collectionName}`)
  47. }
  48. const allCollections = await getCollectionNames()
  49. if (!allCollections.includes(collectionName)) return
  50. const collection = await getCollectionInternal(collectionName)
  51. await collection.drop()
  52. }
  53. class BadMigrationOrder extends Error {}
  54. /**
  55. * Asserts that a dependent migration has run. Throws an error otherwise.
  56. *
  57. * @param {string} migrationName
  58. */
  59. async function assertDependency(migrationName) {
  60. const migrations = await getCollectionInternal('migrations')
  61. const migration = await migrations.findOne({ name: migrationName })
  62. if (migration == null) {
  63. throw new BadMigrationOrder(
  64. `${migrationName} should run before this migration`
  65. )
  66. }
  67. }
  68. export default {
  69. BadMigrationOrder,
  70. addIndexesToCollection,
  71. dropIndexesFromCollection,
  72. dropCollection,
  73. assertDependency,
  74. }