libflitter/middleware/MiddlewareUnit.js

  1. /**
  2. * @module libflitter/middleware/MiddlewareUnit
  3. */
  4. const CanonicalUnit = require('../canon/CanonicalUnit')
  5. const Middleware = require('./Middleware')
  6. const SoftError = require('../errors/SoftError')
  7. const path = require('path')
  8. /**
  9. * Unit to load and manage middleware class definitions.
  10. * @extends module:libflitter/canon/CanonicalUnit~CanonicalUnit
  11. */
  12. class MiddlewareUnit extends CanonicalUnit {
  13. /**
  14. * Defines the services required by this unit.
  15. * @returns {Array<string>}
  16. */
  17. static get services() {
  18. return [...super.services, 'output']
  19. }
  20. /**
  21. * Get the name of the service provided by this unit: 'middlewares'
  22. * @returns {string} - 'middlewares'
  23. */
  24. static get name() {
  25. return 'middlewares'
  26. }
  27. /**
  28. * Instantiate the unit.
  29. * @param {string} [base_directory = './app/routing/middleware']
  30. * @param {string} [globals_file = './app/routing/Middleware.js']
  31. */
  32. constructor(base_directory = './app/routing/middleware', globals_file = './app/routing/Middleware.js') {
  33. super(base_directory)
  34. /**
  35. * Fully-qualified path to the file with the definitions for globally-applied middleware.
  36. * @type {Promise<void> | Promise<string>}
  37. */
  38. this.globals_file = path.resolve(globals_file)
  39. /**
  40. * The canonical name of the item.
  41. * @type {string} = 'middleware'
  42. */
  43. this.canonical_item = 'middleware'
  44. /**
  45. * The file extension of the canonical item files.
  46. * @type {string} - '.middleware.js'
  47. */
  48. this.suffix = '.middleware.js'
  49. }
  50. /**
  51. * Initializes the unit. Registers global middleware.
  52. * @param {module:libflitter/app/FlitterApp~FlitterApp} app - the Flitter app
  53. * @returns {Promise<void>}
  54. */
  55. async go(app) {
  56. await super.go(app)
  57. // Register global middlewares
  58. const globals = require(this.globals_file)
  59. this.globals = globals
  60. for ( const name of globals ) {
  61. if ( !(name in this.canonical_items) ) {
  62. throw (new SoftError(`Unknown middleware name in global Middleware.js file: ${name}`)).unit(this.constructor.name)
  63. }
  64. app.express.use(async (req, res, next, args = {}) => {
  65. return await this.canonical_items[name].test(req, res, next, args)
  66. })
  67. }
  68. }
  69. /**
  70. * Prepare a single canonical middleware definition and return the value that should be given by the resolver.
  71. * @param {object} info
  72. * @param {module:libflitter/app/FlitterApp} info.app
  73. * @param {string} info.name - the unqualified canonical name
  74. * @param {*} info.instance - the static middleware CLASS from the file
  75. * @returns {Promise<*>}
  76. */
  77. async init_canonical_file({app, name, instance}) {
  78. if ( instance.prototype instanceof Middleware ) {
  79. this.output.debug('Registering middleware: '+name)
  80. return new instance(app)
  81. } else {
  82. throw (new SoftError(`Invalid middleware class definition for ${name}. Middleware classes must extend libflitter/middleware/Middleware.`)).unit(this.constructor.name)
  83. }
  84. }
  85. /**
  86. * A helper function to return the Express middleware function for a registered middleware, using its Flitter canonical name.
  87. * @param {string} name - the Flitter canonical name of the middleware whose handler should be returned
  88. * @param {*} args - An argument or arguments to be passed to the middleware function as the 4th argument.
  89. * @returns {function} - the Express middleware
  90. */
  91. get(name, args) {
  92. if ( !this.canonical_items[name] ) {
  93. throw (new SoftError('Attempted to access middleware that does not exist: '+name)).unit(this.constructor.name)
  94. }
  95. return (req, res, next, merge_args) => {
  96. let pass_args = typeof args === 'undefined' ? (merge_args ? merge_args : {}) : args
  97. return this.canonical_items[name].test(req, res, next, pass_args)
  98. }
  99. }
  100. /**
  101. * Get the directories provided by this unit.
  102. * {@link module:libflitter/middleware/MiddlewareUnit~MiddlewareUnit#directory} as "middleware".
  103. * @returns {{middleware: string}}
  104. */
  105. directories() {
  106. return {
  107. ...super.directories(),
  108. global_middleware: this.globals_file,
  109. }
  110. }
  111. /**
  112. * Get the templates provided by this unit.
  113. * Currently, "middleware" template, using the generator {@link module:libflitter/templates/middleware}.
  114. * @returns {{middleware: {template: (middleware|(function(string): string)|*), extension: string, directory: string}}}
  115. */
  116. templates(){
  117. return {
  118. middleware: {
  119. template: require('../templates/middleware'),
  120. directory: this.directory,
  121. extension: '.middleware.js'
  122. }
  123. }
  124. }
  125. /**
  126. * Get the fully-qualified path to the migrations provided by this unit.
  127. * @returns {string}
  128. */
  129. migrations(){
  130. return path.resolve(__dirname, 'migrations')
  131. }
  132. }
  133. module.exports = exports = MiddlewareUnit
JAVASCRIPT
Copied!