UNPKG

copious-transitions

Version:
396 lines (350 loc) 17.5 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: lib/general_static.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: lib/general_static.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>const fs = require('fs') const fsPromises = require('fs/promises') const AppLifeCycle = require("./general_lifecyle") const path = require('path') // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- function no_trailing(char,str) { while ( str.lastIndexOf(char) === (str.length - 1) ) { str = str.slice(0,-1) } return(str) } /* function require_trailing(char,str) { if ( str.lastIndexOf(char) !== (str.length - 1) ) { str = str + char } return(str) } function no_leading(char,str) { while ( str.length &amp;&amp; ( str[0] != char ) ) { str = str.substr(1) } return(str) } */ function require_leading(char,str) { if ( str[0] !== char ) { str = char + str } return(str) } function itemize_dir(dir_name) { let item_map = {} try { let dirList = fs.readdirSync(dir_name) dirList.forEach(file => { let bname = path.basename(file) let type = path.extname(file) let key = bname.replace(type,'') item_map[key] = { 'fname' : file, 'ftype' : type } }) } catch (e) { } return(item_map) // if all else fails } // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- var g_string_types = ['ascii','utf8','json','text',"html"] function load_file(fname,ftype) { // could do Promise.all to speed up startup... if ( g_debug ) console.log(fname) let data = "" try { console.log(`reading file ${fname}`) data = fs.readFileSync(fname) if ( g_string_types.indexOf(ftype) >= 0 ) { data = data.toString() } if ( ftype === 'json' ) { data = JSON.parse(data) } } catch (e) {} return data } async function async_load_file(fname,ftype) { try { let data = await fsPromises.readFile(fname) if ( g_string_types.indexOf(ftype) >= 0 ) { data = data.toString() } if ( ftype === 'json' ) { data = JSON.parse(data) } return data } catch (e) { if ( ftype === 'json' ) return {} else return("") } } /** * * This class provide a basic interface for carrying out actions required for providing static content. * Here **Static Content** is taken to mean content that is created previous to the launch of the application. * * The application sets a static store by passing a class (constructor) to the GeneralStatic constructor * as in new GeneralStatic(MyStaticStoreClass) v.s. new GeneralStatic(), which uses the general database static storage class. * * This static storage is not a replacement for all ways of serving static files. The primary web server of an website might * be the best place for setting up static file service. * * The presence of this class in the library can be used in conjunction with the contractual access clases. And, there may be some * files best stored with the application code - and that might have more to do with installation of an application than configuring * the static load. * * Also, this module has methods for preparing JSON descriptors of HTML and JavaScript that goes with it. This allows for * parts of pages to be delivered as lazy loaded components. * * Finally, some processes may request files from the local process. * * @memberof base */ class GeneralStatic extends AppLifeCycle { // constructor(AppStaticStorageClass) { super() // this.db = null this.trans_engine = null // this._preloaded = {} // nothing preloaded this.custom_static_store = null if ( AppStaticStorageClass ) { this.custom_static_store = new AppStaticStorageClass() } } // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- /** * Loads files from locations that are identified in the `static_files` field of the configuration. * The `static_files` object may have a directory field, in which case all the files in the directory will be loaded. * Otherwise, it will have a map of files, *files*, which will be transfered into the `_preloaded` map. * * Once all the entries are established in the map `_preloaded`, they data is loaded into the map for later access. * * @param {object} db_obj * @param {object} conf */ initialize(db_obj,conf) { this.db = db_obj if ( conf ) { this.claim_asset_directory(conf.static_files.directory) this.claim_assets(conf.static_files.files) // can override directory entries this.preload_all(conf) } if ( this.custom_static_store ) { try { this.custom_static_store.initialize(db_obj,conf) } catch (e) { } } } // /** * Set the transion engine reference. * @param {object} transition_engine - a reference to the application transition engine */ set_transition_engine(transition_engine) { this.trans_engine = transition_engine } // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- // // FETCH /** * * This method may be the point of this module. It attempts to find a static asset and return an object * describing it if it does find it. * * The contractual methods that use this method * prefer to have an object delivered wiht two fields `mime_type` and `string`. The first field * identifies the type of object that it is, the second is the string representation of the object. * * In most cases, this returns an object from the `_preloaded` table. But, if the object is not there, * this method will try to find it in the DB or in the custom static store. * * @param {string} asset_key * @param {object} etc - and object to pass to `static_store` if used. * @returns {object} */ async fetch(asset_key,etc) { if ( asset_key ) { // first try to get a preloaded asset.... (the idea is that there should not be too many, so this search will be fast) let asset = this._preloaded[asset_key] if ( asset ) { return(asset) } else { // since the asset is not "PRELOADED" asset = this.static_store(asset_key,etc) // look into the a custom static store if there is one. if ( asset ) { return(asset) } else if ( this.db ) { let result = await this.db.static_store(asset_key) return(result) // defer to the static store managed by general db } } } return("not found -- no direct file reads") } /** * static_store -- a custom store supplied by the application in lieu of other other stores the application may supply to the db * the app might not want to call out a DB implementation... so this is a little extra * This makes the supplied static store custom for just the static pathways and falls out of scope of other assets * managed through the DB. (Use this option carefully) * * @param {*} asset_key * @param {*} etc * @returns {object|boolean} returns false if no `custom_static_store` has been set up. Returns the result of `custom_static_store.fetch` othewise. */ static_store(asset_key,etc) { if ( this.custom_static_store ) { return(this.custom_static_store.fetch(asset_key,etc)) } return(false) } // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- // claim_assets -- copies the file map into the _preloaded map (keys to asset data...) // claim_assets(file_map) { if ( file_map ) { for ( var entry in file_map ) { this._preloaded[entry] = file_map[entry] } } } // // claim_asset_directory --- reads in an entire directory of assets and places them into the _preloaded map // claim_asset_directory(dir_name) { if ( dir_name ) { let preload_dir = itemize_dir(dir_name) this.claim_assets(preload_dir) } } // /** * * The configuration object is available for those applications that use it to identify files * to be loaded. * * The result of calling this method should be that the table `_preloaded[fileKey]` should have a number * of assests stored in memory for later retrieval. * * If the `custom_static_store` has been set up using a parameter to the constructor (AppStaticStorageClass), * the custom store will be used to load the `_preloaded` map. Otherwise, files will be loaded from the paths * found in thie objects stored in the the `_preloaded` map. * * @param {object} conf */ preload_all(conf) { // a descendant might use conf if ( this.custom_static_store ) { this.custom_static_store.load(this._preloaded) } else { for ( let fileKey in this._preloaded ) { this._preloaded[fileKey].data = load_file(this._preloaded[fileKey].fname,this._preloaded[fileKey].ftype) } } } // /** * * @param {string} fileKey * @returns {string} */ async reload(fileKey) { let loadable_asset = this._preloaded[fileKey] if ( loadable_asset ) { let data = await async_load_file(loadable_asset.fname,loadable_asset.ftype) return(data) } } /** * Some assets are delivered to the web app as an object with two parts, script and html... * This takes an html page (maybe just some part of one) with script and html. It splits the page into the two parts * and then it stores the pair for delivery. * * @param {Buffer} data * @returns {object} - this is an object with two fields, `html` and `script`. */ prepare_asset(data) { if ( !(data) ) { console.error("Static asset prepare, file not fount") return "" // empty string } let htmlpage = data.toString() // let html_parts = htmlpage.split("&lt;script>") let html = html_parts[0] // let script = html_parts[1] script = script.replace('&lt;/script>','').trim() //console.log(script) let json = { "html" : encodeURIComponent(html), "script" : encodeURIComponent(script) } return(json) } // // generic_prep_cwd_offset // /** * Some applications call this method during preloading. * This method looks for the field `app_spec` on the `static_files` field of the configuration object. * * After making an attemp to clean up the string, which is a relative directory to the root directory, * this method update all the `fname` fields of the descriptors stored in the `_preloaded` map. * * @param {object} conf */ generic_prep_cwd_offset(conf) { // if ( conf &amp;&amp; conf.static_files &amp;&amp; conf.static_files.app_spec ) { // let application_specific_loc = conf.static_files.app_spec.trim() application_specific_loc = no_trailing('/',application_specific_loc) application_specific_loc = require_leading('/',application_specific_loc) // if ( application_specific_loc ) { // let root_dir = process.cwd() for ( let asset in this._preloaded ) { // let assetDescr = this._preloaded[asset] let fname = assetDescr.fname fname = require_leading('/',fname) assetDescr.fname = root_dir + application_specific_loc + fname } // } } } } module.exports = GeneralStatic </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Namespaces</h3><ul><li><a href="Contractual.html">Contractual</a></li><li><a href="CopiousTransitions.html">CopiousTransitions</a></li><li><a href="DefaultDB.html">DefaultDB</a></li><li><a href="base.html">base</a></li><li><a href="field_validators.html">field_validators</a></li></ul><h3>Classes</h3><ul><li><a href="Contractual.LocalTObjectCache.html">LocalTObjectCache</a></li><li><a href="Contractual.MimeHandling.html">MimeHandling</a></li><li><a href="Contractual.TransitionHandling.html">TransitionHandling</a></li><li><a href="Contractual.UserHandling.html">UserHandling</a></li><li><a href="CopiousTransitions.CopiousTransitions.html">CopiousTransitions</a></li><li><a href="DefaultDB.CustomizationMethodsByApplication.html">CustomizationMethodsByApplication</a></li><li><a href="DefaultDB.FauxInMemStore.html">FauxInMemStore</a></li><li><a href="DefaultDB.FileMapper.html">FileMapper</a></li><li><a href="DefaultDB.FilesAndRelays.html">FilesAndRelays</a></li><li><a href="DefaultDB.FilesAndRelays_base.html">FilesAndRelays_base</a></li><li><a href="DefaultDB.LocalStaticDB.html">LocalStaticDB</a></li><li><a href="DefaultDB.LocalStorageLifeCycle.html">LocalStorageLifeCycle</a></li><li><a href="DefaultDB.LocalStorageSerialization.html">LocalStorageSerialization</a></li><li><a href="DefaultDB.PageableMemStoreElement.html">PageableMemStoreElement</a></li><li><a href="DefaultDB.PersistenceContracts.html">PersistenceContracts</a></li><li><a href="DefaultDB.RemoteMessaging.html">RemoteMessaging</a></li><li><a href="DefaultDB.StaticDBDefault.html">StaticDBDefault</a></li><li><a href="GeneralUserDBWrapperImpl.html">GeneralUserDBWrapperImpl</a></li><li><a href="SessionTokenManager.html">SessionTokenManager</a></li><li><a href="base.DBClass.html">DBClass</a></li><li><a href="base.EndpointManager.html">EndpointManager</a></li><li><a href="base.GeneralAppLifeCycle.html">GeneralAppLifeCycle</a></li><li><a href="base.GeneralAuth.html">GeneralAuth</a></li><li><a href="base.GeneralBusiness.html">GeneralBusiness</a></li><li><a href="base.GeneralDynamic.html">GeneralDynamic</a></li><li><a href="base.GeneralMiddleWare.html">GeneralMiddleWare</a></li><li><a href="base.GeneralStatic.html">GeneralStatic</a></li><li><a href="base.GeneralTransitionEngImpl.html">GeneralTransitionEngImpl</a></li><li><a href="base.SessionManager.html">SessionManager</a></li><li><a href="base.SessionManager_Lite.html">SessionManager_Lite</a></li><li><a href="base.TaggedTransition.html">TaggedTransition</a></li><li><a href="base.TokenTables.html">TokenTables</a></li><li><a href="base.UserMessageEndpoint.html">UserMessageEndpoint</a></li><li><a href="base.WebSocketManager.html">WebSocketManager</a></li><li><a href="field_validators.DataLookupField.html">DataLookupField</a></li><li><a href="field_validators.EmailField.html">EmailField</a></li><li><a href="field_validators.EmailVerifyField.html">EmailVerifyField</a></li><li><a href="field_validators.FieldTest.html">FieldTest</a></li><li><a href="field_validators.FieldValidatorTools.html">FieldValidatorTools</a></li><li><a href="field_validators.ForeignAuth.html">ForeignAuth</a></li><li><a href="field_validators.GeneralValidator.html">GeneralValidator</a></li><li><a href="field_validators.LengthyAlphabetField.html">LengthyAlphabetField</a></li><li><a href="field_validators.LengthyDigitalField.html">LengthyDigitalField</a></li><li><a href="field_validators.LengthyField.html">LengthyField</a></li><li><a href="field_validators.LengthyStringField.html">LengthyStringField</a></li><li><a href="field_validators.PasswordField.html">PasswordField</a></li><li><a href="field_validators.PasswordVerifyField.html">PasswordVerifyField</a></li><li><a href="field_validators.TypeCheckField.html">TypeCheckField</a></li></ul><h3>Global</h3><ul><li><a href="global.html#generate_password_block">generate_password_block</a></li><li><a href="global.html#load_configuration">load_configuration</a></li><li><a href="global.html#load_parameters">load_parameters</a></li><li><a href="global.html#module_top">module_top</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.2</a> on Tue Oct 31 2023 17:32:59 GMT-0700 (Pacific Daylight Time) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>