|  |  |  | /* eslint-env browser */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const { head, isFunction, isObject, isString, last } = require('lodash'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const db = require('../database'); | 
					
						
							|  |  |  | const { deferredToPromise } = require('../deferred_to_promise'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const closeDatabaseConnection = ({ Backbone } = {}) => | 
					
						
							|  |  |  |   deferredToPromise(Backbone.sync('closeall')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | exports.runMigrations = async ({ Backbone, database, logger } = {}) => { | 
					
						
							|  |  |  |   if ( | 
					
						
							|  |  |  |     !isObject(Backbone) || | 
					
						
							|  |  |  |     !isObject(Backbone.Collection) || | 
					
						
							|  |  |  |     !isFunction(Backbone.Collection.extend) | 
					
						
							|  |  |  |   ) { | 
					
						
							|  |  |  |     throw new TypeError('runMigrations: Backbone is required'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( | 
					
						
							|  |  |  |     !isObject(database) || | 
					
						
							|  |  |  |     !isString(database.id) || | 
					
						
							|  |  |  |     !Array.isArray(database.migrations) | 
					
						
							|  |  |  |   ) { | 
					
						
							|  |  |  |     throw new TypeError('runMigrations: database is required'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (!isObject(logger)) { | 
					
						
							|  |  |  |     throw new TypeError('runMigrations: logger is required'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const { | 
					
						
							|  |  |  |     firstVersion: firstMigrationVersion, | 
					
						
							|  |  |  |     lastVersion: lastMigrationVersion, | 
					
						
							|  |  |  |   } = getMigrationVersions(database); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const databaseVersion = await db.getVersion(database.id); | 
					
						
							|  |  |  |   const isAlreadyUpgraded = databaseVersion >= lastMigrationVersion; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   logger.info('Database status', { | 
					
						
							|  |  |  |     firstMigrationVersion, | 
					
						
							|  |  |  |     lastMigrationVersion, | 
					
						
							|  |  |  |     databaseVersion, | 
					
						
							|  |  |  |     isAlreadyUpgraded, | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (isAlreadyUpgraded) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const migrationCollection = new (Backbone.Collection.extend({ | 
					
						
							|  |  |  |     database, | 
					
						
							|  |  |  |     storeName: 'items', | 
					
						
							|  |  |  |   }))(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Note: this legacy migration technique is required to bring old clients with
 | 
					
						
							|  |  |  |   //   data in IndexedDB forward into the new world of SQLCipher only.
 | 
					
						
							|  |  |  |   await deferredToPromise(migrationCollection.fetch({ limit: 1 })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   logger.info('Close database connection'); | 
					
						
							|  |  |  |   await closeDatabaseConnection({ Backbone }); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const getMigrationVersions = database => { | 
					
						
							|  |  |  |   if (!isObject(database) || !Array.isArray(database.migrations)) { | 
					
						
							|  |  |  |     throw new TypeError("'database' is required"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const firstMigration = head(database.migrations); | 
					
						
							|  |  |  |   const lastMigration = last(database.migrations); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const firstVersion = firstMigration | 
					
						
							|  |  |  |     ? parseInt(firstMigration.version, 10) | 
					
						
							|  |  |  |     : null; | 
					
						
							|  |  |  |   const lastVersion = lastMigration | 
					
						
							|  |  |  |     ? parseInt(lastMigration.version, 10) | 
					
						
							|  |  |  |     : null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { firstVersion, lastVersion }; | 
					
						
							|  |  |  | }; |