Adapt authoring tool UI documentation

v1.0.0-rc.4

adapt-authoring-core/lib/App.js

  1. import AbstractModule from './AbstractModule.js'
  2. import DependencyLoader from './DependencyLoader.js'
  3. import { fileURLToPath } from 'url'
  4. import fs from 'fs'
  5. import path from 'path'
  6. import Utils from './Utils.js'
  7. let instance
  8. /**
  9. * Core functionality
  10. * @namespace core
  11. */
  12. /**
  13. * The main application class
  14. * @memberof core
  15. * @extends {AbstractModule}
  16. */
  17. class App extends AbstractModule {
  18. /**
  19. * The singleton instance. Self-initialises it if there isn't one.
  20. * @type {App}
  21. */
  22. static get instance () {
  23. if (!instance) instance = new App()
  24. return instance
  25. }
  26. /** @override */
  27. constructor () {
  28. const rootDir = process.env.ROOT_DIR ?? process.cwd()
  29. const adaptJson = JSON.parse(fs.readFileSync(path.join(rootDir, Utils.metadataFileName)))
  30. const packageJson = JSON.parse(fs.readFileSync(path.join(rootDir, Utils.packageFileName)))
  31. super(null, { ...packageJson, ...adaptJson, name: 'adapt-authoring-core', rootDir })
  32. }
  33. /** @override */
  34. async init () {
  35. /**
  36. * Reference to the passed arguments (parsed for easy reference)
  37. * @type {Object}
  38. */
  39. this.args = Utils.getArgs()
  40. /**
  41. * Instance of App instance (required by all AbstractModules)
  42. * @type {App}
  43. */
  44. this.app = this
  45. /**
  46. * Reference to the DependencyLoader instance
  47. * @type {DependencyLoader}
  48. */
  49. this.dependencyloader = new DependencyLoader(this)
  50. /** @ignore */ this._isStarting = false
  51. const configRootDir = this.getConfig('rootDir')
  52. if (configRootDir) /** @ignore */this.rootDir = configRootDir
  53. let startError
  54. try {
  55. await this.start()
  56. } catch (e) {
  57. startError = e
  58. }
  59. const failedMods = this.dependencyloader.failedModules
  60. if (failedMods.length) this.log('warn', `${failedMods.length} module${failedMods.length === 1 ? '' : 's'} failed to load: ${failedMods}. See above for details`)
  61. if (startError) {
  62. process.exitCode = 1
  63. throw new Error('Failed to start App')
  64. }
  65. }
  66. /**
  67. * The Adapt module dependencies and their configs
  68. * @type {Object}
  69. */
  70. get dependencies () {
  71. return this.dependencyloader.configs
  72. }
  73. /**
  74. * Starts the app
  75. * @return {Promise} Resolves when the app has started
  76. */
  77. async start () {
  78. if (this._isReady) throw new Error('warn', 'cannot start app, already started')
  79. if (this._isStarting) throw new Error('warn', 'cannot start app, already initialising')
  80. this._isStarting = true
  81. await this.dependencyloader.load()
  82. this._isStarting = false
  83. }
  84. /**
  85. * Enables waiting for other modules to load
  86. * @param {...String} modNames Names of modules to wait for
  87. * @return {Promise} Resolves when specified module has been loaded
  88. */
  89. async waitForModule (...modNames) {
  90. const results = await Promise.all(modNames.map(m => this.dependencyloader.waitForModule(m)))
  91. return results.length > 1 ? results : results[0]
  92. }
  93. /** @override */
  94. setReady (error) {
  95. this._isStarting = false
  96. super.setReady(error)
  97. }
  98. }
  99. export default App