Adapt authoring tool UI documentation

v1.0.0-rc.4

adapt-authoring-core/lib/AbstractModule.js

  1. import Hook from './Hook.js'
  2. /**
  3. * Abstract class for authoring tool modules. All custom modules must extend this class.
  4. * @memberof core
  5. */
  6. class AbstractModule {
  7. /** @ignore */
  8. static get MODULE_READY () {
  9. return 'MODULE_READY'
  10. }
  11. /**
  12. * Create the Module instance
  13. * @param {Object} app Reference to the main application
  14. * @param {Object} pkg Config object from package.json for this module
  15. */
  16. constructor (app, pkg) {
  17. /** @ignore */
  18. this._startTime = Date.now()
  19. /** @ignore */
  20. this._isReady = false
  21. /**
  22. * Reference to the main app instance
  23. * @type {App}
  24. */
  25. this.app = app
  26. /**
  27. * Module config options
  28. * @type {Object}
  29. */
  30. this.pkg = pkg
  31. /**
  32. * Name of the module
  33. * @type {String}
  34. */
  35. this.name = pkg?.name || this.constructor.name
  36. /**
  37. * Root directory of this module
  38. * @type {String}
  39. */
  40. this.rootDir = pkg?.rootDir
  41. /**
  42. * Time taken in milliseconds for module to initialise
  43. * @type {Number}
  44. */
  45. this.initTime = undefined
  46. /**
  47. * Hook invoked on module ready
  48. * @type {Hook}
  49. */
  50. this.readyHook = new Hook()
  51. this.init()
  52. .then(() => this.setReady())
  53. .catch(e => this.setReady(e))
  54. }
  55. /**
  56. * Initialises the module. Any custom initialisation tasks should go here. Any uncaught errors thrown here will be caught later and halt the module's load, so make sure any non-fatal errors are handled.
  57. * @return {Promise}
  58. */
  59. async init () {
  60. }
  61. /**
  62. * Signals that the module is loaded
  63. * @param {Error} error
  64. * @return {Promise}
  65. */
  66. async setReady (error) {
  67. if (this._isReady) {
  68. return
  69. }
  70. await this.readyHook.invoke(error)
  71. if (error) {
  72. return
  73. }
  74. this._isReady = true
  75. this.initTime = Math.round((Date.now() - this._startTime))
  76. this.log('debug', AbstractModule.MODULE_READY, this.initTime)
  77. }
  78. /**
  79. * Used to listen to the module's ready signal. The returned promise will be resolved when the module has completed initialisation successfully.
  80. * @return {Promise}
  81. */
  82. async onReady () {
  83. return new Promise((resolve, reject) => {
  84. if (this._isReady) {
  85. return this._initError ? reject(this._initError) : resolve(this)
  86. }
  87. this.readyHook.tap(error => {
  88. /** @ignore */this._initError = error
  89. error ? reject(error) : resolve(this)
  90. })
  91. })
  92. }
  93. /**
  94. * Shortcut for retrieving config values
  95. * @param {String} key
  96. * @return {*}
  97. */
  98. getConfig (key) {
  99. try {
  100. return this.app.config.get(`${this.name}.${key}`)
  101. } catch (e) {
  102. return undefined
  103. }
  104. }
  105. /**
  106. * Log a message using the Logger module
  107. * @param {String} level Log level of message
  108. * @param {...*} rest Arguments to log
  109. */
  110. log (level, ...rest) {
  111. const _log = (e, instance) => {
  112. if (!this.app.logger || (instance && instance.name !== this.app.logger.name)) return false
  113. this.app.dependencyloader.moduleLoadedHook.untap(_log)
  114. this.app.logger.log(level, this.name.replace(/^adapt-authoring-/, ''), ...rest)
  115. return true
  116. }
  117. if (!_log()) this.app.dependencyloader.moduleLoadedHook.tap(_log)
  118. }
  119. }
  120. export default AbstractModule