javascript-value-locator

1.4.7 • Public • Published

Javascript Value Locator

unstable

Branch : release version npm version

Build Status Coverage Status

Dependency Status devDependency Status

Load javascript values from multiples sources and using multiple protocols

Introduction

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.

// 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 :

require.ensure([], require => {
    const value = require('module/path');
 
    // do something with the value
})

You do this :

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

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.

Purpose and 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 :

// ./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'](resolve, reject, target){
                
                // 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)
                );
            }
        })
    })
}
// ./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...

Get started

Install

  • using npm

    npm install --save javascript-value-locator

  • or using yarn

    yarn add javascript-value-locator

Load one or more values from JVL

TO DO - see the load function documentation for now

Available protocols

Currently, the only implemented protocol is the require. If needed, add others and eventually open a issue or event better, a PR.

Use custom protocols

You can use the inject.protocols option of the load function. Look here for concrete example.

Load a value synchronously

JVL is not aimed to do that.

About the documentation

The following documentation was generated using documentation.js.

Naming conventions

  • CapitalizedCamelCasedNames are used for types

  • dashified-case-names are used for filenames

  • camelCasedNames are used for methods and properties

Documentation

Table of Contents

JavascriptValueLocator

A JavascriptValueLocator (JVL) is a string or an object which describe a way to access to a javascript value. It must provide at least:

Type: (JavascriptValueLocatorString | JavascriptValueLocatorObject)

JavascriptValueLocatorString

A JavascriptValueLocatorString (JVL string) is a string which describe a way to access to a javascript value. It must matches the following format:

Type: string

Examples

// 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

JavascriptValueLocatorObject

A JavascriptValueLocatorObject is an object which describe a way to access to a javascript value.

Type: object

Properties

JavascriptValueLocatorProtocol

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 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. 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 requested
  • options object The options passed to the protocol.

javascript-value-locator

The JVL API is an object providing the following properties:

Examples

// 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

load

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.

setLocatorDefaultProtocol

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.

parse

This function returns a locator object from a JVL string.

Parameters

Returns JavascriptValueLocatorObject The corresponding locator as an object.

stringify

This function transforms a locator object to a JVL string.

Parameters

Returns JavascriptValueLocatorString The corresponding JVL string.

defaultProtocols

This object contains the defaults protocols defined by the javascript-value-locator package :

You can use it, for example, in order to create a new load functions with new custom protocols.

Examples

//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)
    })
}

require

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

License

javascript-value-locator is released under MIT. Copyright (c) 2017-present Alexis Tessier

Versions

Current Tags

  • Version
    Downloads (Last 7 Days)
    • Tag
  • 1.4.7
    5
    • latest

Version History

Package Sidebar

Install

npm i javascript-value-locator

Weekly Downloads

12

Version

1.4.7

License

MIT

Last publish

Collaborators

  • alexistessier