/**
* @module flitter-upload/UploadUnit
*/
const Unit = require('libflitter/Unit')
const File = require('./model/File')
const FlitterStore = require('./store/FlitterStore')
const ncp = require('ncp')
const path = require('path')
/**
* Unit that prepares and provides services for uploading,
* accessing, and sending files.
* @extends module:libflitter/Unit~Unit
*/
class UploadUnit extends Unit {
/**
* Defines the services required by this unit.
* @returns {Array<string>}
*/
static get services() {
return [...super.services, 'models', 'configs', 'output', 'canon', 'utility']
}
/**
* Get the name of the service provided by this unit: 'upload'
* @returns {string} - 'upload'
*/
static get name() {
return 'upload'
}
/**
* Object mapping store type names to static class references
* for the store types supported by flitter-upload.
*
* Should map string -> {@link module:flitter-upload/store/Store~Store} class definitions.
*
* Supported types:
* - FlitterStore
*
* @type {object}
*/
store_classes = { FlitterStore }
/**
* Store configurations loaded from 'configs::upload.stores'.
* @type {object}
*/
store_configs = {}
/**
* Name of the default store. False if not set. Loaded
* from 'configs::upload.default_store'.
* @type {boolean|string}
*/
default_store_name = false
/**
* Mapping of store names to instances of the stores themselves.
* e.g. maps string -> {@link module:flitter-upload/store/Store~Store}.
* @type {object}
*/
stores = {}
/**
* Initialize the unit. Load the configurations from config files,
* then instantiate the configured stores.
* @param {module:libflitter/app/FlitterApp~FlitterApp} app - the application
* @returns {Promise<void>}
*/
async go(app) {
const di = app.di()
const upload_config = this.configs.get('upload')
this.store_configs = upload_config ? upload_config.stores : undefined
this.default_store_name = upload_config ? upload_config.default_store : undefined
this.models.external_model(this, 'File', File)
for ( const provider of Object.values(this.store_classes) ) {
di.make(provider)
}
if ( this.store_configs ) {
for (const store_name in this.store_configs) {
if (!this.store_configs.hasOwnProperty(store_name)) continue
const config = this.store_configs[store_name]
config.name = store_name
if (!config.type || !(Object.keys(this.store_classes).includes(config.type))) {
this.output.warn(`Invalid or missing upload store type for ${store_name}.`)
continue
}
const StoreClass = this.store_classes[config.type]
const store = new StoreClass(config)
await store.init()
this.stores[store_name] = store
}
}
this.canon.register_resource('uploader', (name) => this.get(name))
}
/**
* Handler for the 'upload' deployment. This creates the 'upload:UploadFile'
* middleware, and the upload configuration.
* @returns {Promise<void>}
*/
async deploy() {
const package_dir = __dirname
const base_dir = path.dirname(this.utility.root())
this.output.info(`Deploying uploader resources from ${package_dir} to ${base_dir}.`, 0)
function do_copy(from, to){
return new Promise(
(resolve, reject) => {
ncp(from, to, (error) => {
if ( error ) reject(error)
resolve()
})
}
)
}
await do_copy(path.resolve(package_dir, 'deploy'), base_dir)
}
/**
* Get the default file store provider.
* @returns {module:flitter-upload/store/Store~Store}
*/
provider() {
return this.get(this.default_store_name)
}
/**
* Get a configured store by name.
* This is registered as the 'uploader' canonical resolver.
* @param {string} store_name
* @returns {module:flitter-upload/store/Store~Store}
*/
get(store_name) {
return this.stores[store_name]
}
}
module.exports = exports = UploadUnit