index.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. const path = require('path')
  2. const log = require('./util/log')
  3. const report = require('./reports')
  4. const matcher = require('./util/matcher')
  5. const Group = report.Group
  6. const Backup = require('./backup')
  7. const os = require('os')
  8. // Backup source directory
  9. var backupDirectory = path.join(os.homedir(), '/Library/Application Support/MobileSync/Backup/')
  10. osType = process.platform
  11. if (osType === "win32") {
  12. var backupDirectory = path.join(require('os').homedir(), '\\Apple\\MobileSync\\Backup')
  13. }
  14. // Object containing all report modules
  15. var moduleCache = report.types
  16. // Array of plugin modules
  17. var plugins = []
  18. /**
  19. * Add an array of plugins to the plugins list.
  20. * @param {Array<Object>} array contains array of plugin objects.
  21. */
  22. function registerModule (array) {
  23. if (!(array instanceof Array)) {
  24. array = [ array ]
  25. }
  26. plugins.push(...array)
  27. moduleCache = getCompleteModuleList()
  28. }
  29. /**
  30. * Remove all non-default plugins.
  31. */
  32. function clearModules () {
  33. plugins = []
  34. moduleCache = getCompleteModuleList()
  35. }
  36. /**
  37. * Get all modules in a top-down manner.
  38. */
  39. function getCompleteModuleList () {
  40. let allModules = {}
  41. // Add all of the require()'d modules into the plugins list.
  42. plugins.forEach(function (plugin) {
  43. allModules = { ...allModules, ...plugin }
  44. })
  45. // Add all of the modules to a single object.
  46. // JS's behavior dictates that the items are added sequentially
  47. // So, the default reports overwrite any third party plugin.
  48. let result = {
  49. ...allModules,
  50. ...report.types
  51. }
  52. moduleCache = result
  53. return result
  54. }
  55. /**
  56. * Try to find a single report.
  57. * @param {string} query name to find.
  58. */
  59. function findReport (query) {
  60. return new Promise((resolve, reject) => {
  61. // Check there is no wildcard in the query.
  62. if (query.indexOf('*') > -1) {
  63. return reject(new Error('Cannot run a wildcard match here.'))
  64. }
  65. // Run matches.
  66. let matches = matcher(moduleCache, query, (el) => !(el instanceof Group))
  67. // If no report found, fail.
  68. if (matches.length === 0) {
  69. return reject(new Error(`No report found with name "${query}"`))
  70. }
  71. // If multiple matches, fail.
  72. if (matches.length > 1) {
  73. return reject(new Error(`Multiple report matches for name "${query}", not allowed.`))
  74. }
  75. // Resolve match
  76. resolve(matches[0])
  77. })
  78. }
  79. /**
  80. * Translate the raw output of a report to the correct result, based on the "raw" parameter.
  81. * @param {Object} report The report module
  82. * @param {Object} result Raw data output from the aforementioned report
  83. * @param {Object} params parameters object.
  84. */
  85. function compileReport (report, result, { raw }) {
  86. return new Promise((resolve, reject) => {
  87. if (!raw && report.output) {
  88. if (result instanceof Array) {
  89. log.verbose('compiling report (array)...')
  90. // if it's an array, translate each item.
  91. result = result.map(item => {
  92. // For each item, run the functions on the entry.
  93. let editedResult = {}
  94. for (let [key, value] of Object.entries(report.output)) {
  95. editedResult[key] = value(item)
  96. }
  97. return editedResult
  98. })
  99. resolve(result)
  100. } else {
  101. log.verbose('compiling report (single)...')
  102. // Otherwise, translate the object returned.
  103. let editedResult = {}
  104. for (let [key, value] of Object.entries(report.output)) {
  105. editedResult[key] = value(result)
  106. }
  107. resolve(editedResult)
  108. }
  109. } else {
  110. resolve(result)
  111. }
  112. })
  113. }
  114. /**
  115. * Run a named report and resolve to it's output.
  116. * The output is formatted based on the `report.output` key, if the params.raw option is NOT set to true.
  117. * @param {string} query report name
  118. * @param {Object=} params parameters.
  119. */
  120. function run (query, params) {
  121. params = params || {}
  122. return new Promise(async (resolve, reject) => {
  123. try {
  124. let report = await findReport(query)
  125. let result = await runReport(report, params)
  126. let compiled = await compileReport(report, result, params)
  127. resolve(compiled)
  128. } catch (e) {
  129. reject(e)
  130. }
  131. })
  132. }
  133. /**
  134. * Run a report
  135. * @param {object} report report module
  136. * @param {object=} params parameters
  137. */
  138. function runReport (report, params) {
  139. params = params || {}
  140. return new Promise((resolve, reject) => {
  141. var backup
  142. // Cannot run < v3 backups in this manner.
  143. if (!report.version || report.version < 3) {
  144. return reject(new Error(`Cannot call ${report.name} as a module, it is not updated to the v3 api`))
  145. }
  146. // If it requires a backup and none is provided, reject.
  147. if (report.requiresBackup) {
  148. if (!params.backup) {
  149. return reject(new Error('Please specify the `backup` parameter to run this report.'))
  150. }
  151. backup = new Backup(backupDirectory, params.backup)
  152. }
  153. // Input params to func
  154. let inputParams = {
  155. ...params,
  156. backup
  157. }
  158. report.run(module.exports, inputParams)
  159. .then(resolve)
  160. .catch(reject)
  161. })
  162. }
  163. module.exports = {
  164. // Exported Libraries
  165. Backup,
  166. Group,
  167. // Module management
  168. registerModule,
  169. clearModules,
  170. get modules () {
  171. return moduleCache
  172. },
  173. // Source directory
  174. set base (value) {
  175. backupDirectory = value
  176. },
  177. get base () {
  178. return backupDirectory
  179. },
  180. // Runners
  181. run,
  182. findReport,
  183. runReport,
  184. compileReport,
  185. // misc
  186. setLogLevel (lvl) {
  187. log.setVerbose(lvl)
  188. }
  189. }