Load javascript values from multiples sources and using multiple protocols
npm install javascript-value-locator
!Branch : release






Load javascript values from multiples sources and using multiple protocols
- Introduction
- Purpose and use cases
- Get started
- About the documentation
- Documentation
- License
This module provide a minimalist api to load (asynchronously only) javascript values from different sources, using javascript value locators - _JVL_. A _JVL_ is an object or a string (matching a specific format), which represent a way to load a javascript value. It's composed both of a protocol and a target.
``javascript
// this is a jvl object
{
protocol: 'protocol-name',
target: 'full/path/to/module/exporting/the/targeted/value'
}
// this is the equivalent jvl string
'protocol-name:full/path/to/module/exporting/the/targeted/value'
`
You can see this module as a kind of webpack at the run time, where protocols are loaders, and where instead of doing this :
`javascript
require.ensure([], require => {
const value = require('module/path');
// do something with the value
})
`
`javascript
const jvl = require('javascript-value-locator');
jvl.load('require:module/path').then(value => {
// do something with the value
})
`
And for example, if you want to load a yaml, you could use a specific protocol, as you would have used a yaml-loader in webpack
`javascript
const jvl = require('javascript-value-locator');
/**
* Assuming that a "require-yaml" protocol was defined in the first place
* (which is currently not the case)
*/
jvl.load('require-yaml:module/path.yaml').then(value => {
// do something with the value
})
`
_Note that the comparison with webpack is only here for explanatory purpose, this module doesn't aim the same use cases._
The previous examples are here only for the sake of explaining the module basic usage. If you want to require a module in node.js, you should more than probably just do a require (unless you want to load it asynchronously).
_The following use case is the one for what the module was created in the first place_.
- Use the JVL string format to "require" a module in a cli command option
Assuming you want to provide a command with an option which can be a javascript value. If the option is a number, it's ok to do that :
cli command input --javascript-value-option=5
But if the option is a complex/dynamic object, using JVL allow you to do that :
cli command input --javascript-value-option=require:full/path/to/module
The cli users have in that way a more fine control over the module he wants use to do some task.
A logger module is a good example. Imagine you implement a cli command which only log the input, you could have something like :
`javascript
// ./load-override.js
// create a custom load function
const path = require('path');
const {load, setLocatorDefaultProtocol, defaultProtocols} = require('javascript-value-locator');
module.exports = function customLoad(locator, options){
// if the locator is an object and doesn't have protocol property,
// or if it's a string without protocol ahead, the 'custom-protocol' will be used
return load(setLocatorDefaultProtocol(locator, 'custom-protocol'), options, {
protocols: Object.assign({}, defaultProtocols, {
'custom-protocol'{
// define a way to "require" the javascript value targeted
// for instance, require the path from a custom directory
// It will allow to provide some built-in log functions
defaultProtocols.require(resolve, reject,
path.join(__dirname, '../custom/directory/path', target)
);
}
})
})
}
`
`javascript
// ./log-command.js
// then use the custom load function in your log command implementation
const load = require('./load-override');
module.exports = async function logCommand(
input,
log = (...logs) => console.log(...logs) // provide a default logger
){
// enable silent mode
if(log === false){
log = ()=>{};
}
// enable the user to directly use a function as log option
if(typeof log !== 'function'){
log = await load(log);
}
assert(typeof log === 'function');
return log(input);
}
`
Make the cli implementation which will call this async function, then your users can do :
- this will use a simple console.log
cli log "hello world"
- this will not log anything
cli log "hello world" --log=false
- this will use a built-in logger defined in custom/directory/path
cli log "hello world" --log=custom-protocol:log-one
- this will use an other built-in logger defined in custom/directory/path
cli log "hello world" --log=log-two
- this will use a logger defined by the user
cli log "hello world" --log=require:path/to/a/custom/logger
#### Speculative use cases
The module wasn't thinked in order to do that, but it may could be used to accomplish some of these things :
- Create and use some custom protocols able to load javascript from the cloud
- Use in the browser to load assets (still with custom protocols)
- And probably more...
- using npm
npm install --save javascript-value-locator
- or using yarn
yarn add javascript-value-locator
TO DO - see the load function documentation for now
Currently, the only implemented protocol is the require. If needed, add others and eventually open a issue or event better, a PR.
You can use the inject.protocols option of the load function. Look here for concrete example.
JVL is not aimed to do that.
The following documentation was generated using documentation.js.
- CapitalizedCamelCasedNames are used for types
- dashified-case-names are used for filenames
- camelCasedNames are used for methods and properties
#### Table of Contents
- JavascriptValueLocator
- JavascriptValueLocatorString
- JavascriptValueLocatorObject
- JavascriptValueLocatorProtocol
- javascript-value-locator
- load
- setLocatorDefaultProtocol
- parse
- stringify
- defaultProtocols
- require
A JavascriptValueLocator (JVL) is a string or an object which describe a way to access to a javascript value.
It must provide at least:
- A protocol (JavascriptValueLocatorProtocol)
- A target as a string
Type: (JavascriptValueLocatorString \| JavascriptValueLocatorObject)
A JavascriptValueLocatorString (JVL string) is a string which describe a way to access to a javascript value. It must matches the following format:
- protocol-name:target-name see JavascriptValueLocator
Type: string
Examples
`javascript
// Those are valid JVL strings
"require:/path/to/file"
"any-defined-protocol-name:any-target-name_case is-NotImportant"
// Those are unvalid JVL strings
":target-name" // Missing protocol
"protocol-name" // Missing target
`
A JavascriptValueLocatorObject is an object which describe a way to access to a javascript value.
Type: object
Properties
- protocol (string \| JavascriptValueLocatorProtocol) The name of the protocol or the protocol himself (as a function which respect the JavascriptValueLocatorProtocol definition)target
- string The javascript value targeted.
A JavascriptValueLocatorProtocol is a function which take the following arguments (resolve, reject, target, options) and resolve the targeted javascript value or reject an error
Type: function
Parameters
- resolve function A resolve function which will be called with the targeted javascript value as single argumentreject
- function A reject function which will be called with a error as single argument if the javascript value load failedtarget
- string The target to load and resolve. A target must be a unique identifier/path (or maybe other things depending on the used protocol) to the requested javascript value. You must use it to know which value is requestedoptions
- object The options passed to the protocol.
The JVL API is an object providing the following properties:
- load
- setLocatorDefaultProtocol
- parse
- stringify
- defaultProtocols
Examples
`javascript`
// require the public API
const JVL = require('javascript-value-locator')
// then use a method of the API
JVL.load('npm:string-humanize@1.0.0').then(_ => console.log(_('hello-world'))) // Hello world
This function loads a javascript value in a async way
Parameters
- locator (JavascriptValueLocator \| Array<JavascriptValueLocator>) A javascript value locator as an object or a string which follow the JVL format. Can also be an Array of locators.options
- object? The javascript options object which will be passed to the locator protocol function. If locator is an object, it can provide directly an options object which will be merged with the options parameter. (optional, default {})inject
- object? A javascript object containing the load function dependencies. (optional, default {})inject.protocols
- object A Dictionnary where keys are the names of the protocols and value are the protocols functions. If locator is an object, it can provide directly a protocols key which will be merged with the inject.protocols parameter. (optional, default defaultProtocols)
Returns Promise A promise resolving the javascript value targeted by the locator. If locator was an Array, the promise resolve an Array containing all the targeted values in the same order as defined.
This function returns a locator with the specified default protocol if the input locator doesn't provide one.
Parameters
- locator ((string \| object) | Array<(string \| object)>) A potential JVL which must at least provide a target. It will be transformed in a valid JVL. If it's an Array, the function will return an Array of valid JVL. The output JVl will keep the type of the original input locator.defaultProtocol
- string If no protocol is found in the locator, then the default protocol will be setted as the current locator protocol. Note that you can't provide a protocol as a function using the setLocatorDefaultProtocol function.
Returns (JavascriptValueLocator \| Array<JavascriptValueLocator>) The corresponding locator as an object.
This function returns a locator object from a JVL string.
Parameters
- JVL JavascriptValueLocatorString The locator as string to parse.
Returns JavascriptValueLocatorObject The corresponding locator as an object.
This function transforms a locator object to a JVL string.
Parameters
- locator JavascriptValueLocatorObject The locator object to stringify.
Returns JavascriptValueLocatorString The corresponding JVL string.
This object contains the defaults protocols defined by the javascript-value-locator package :
- require
You can use it, for example, in order to create a new load functions with new custom protocols.
Examples
`javascript
//import the load function and the default-protocols
const {load, defaultProtocols} = require('javascript-value-locator')
//define some custom protocols
const customProtocols = {
newProtocol: function(resolve, reject, target, options){
resolve(getTheValueUsingTheTargetAndOptions)
//or
reject()
}
}
//create and export a function which call the original function,
//but passing to it a new protocols object dependency
module.exports = function customLoad(locator, options){
return load(locator, options, {
protocols: Object.assign({}, defaultProtocols, customProtocols)
})
}
`
This function is a JavascriptValueLocatorProtocol that use the node require function to load the target.
Parameters
- resolve function A resolve function which will be called with the targeted javascript value as single argument.reject
- function A reject function which will be called with a error as single argument if the javascript value load failed.target
- string The target to load and resolve. It must be a path to a valid node module.options
- object? A javascript object containing the require protocol options. (optional, default {})options.cwd
- string The current working directory to use if the target path is not absolute. (optional, default process.cwd()`)
Returns undefined
javascript-value-locator is released under MIT.
Copyright (c) 2017-present Alexis Tessier