UNPKG

path-loader

Version:

Utility that provides a single API for loading the content of a path/URL.

204 lines (185 loc) 6.4 kB
/* * The MIT License (MIT) * * Copyright (c) 2015 Jeremy Whitlock * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ 'use strict'; var supportedLoaders = { file: require('./lib/loaders/file'), http: require('./lib/loaders/http'), https: require('./lib/loaders/http') }; var defaultLoader = typeof window === 'object' || typeof importScripts === 'function' ? supportedLoaders.http : supportedLoaders.file; // Load promises polyfill if necessary /* istanbul ignore if */ if (typeof Promise === 'undefined') { require('native-promise-only'); } function getScheme (location) { if (typeof location !== 'undefined') { location = location.indexOf('://') === -1 ? '' : location.split('://')[0]; } return location; } /** * Utility that provides a single API for loading the content of a path/URL. * * @module path-loader */ function getLoader (location) { var scheme = getScheme(location); var loader = supportedLoaders[scheme]; if (typeof loader === 'undefined') { if (scheme === '') { loader = defaultLoader; } else { throw new Error('Unsupported scheme: ' + scheme); } } return loader; } /** * Loads a document at the provided location and returns a JavaScript object representation. * * @param {string} location - The location to the document * @param {module:path-loader.LoadOptions} [options] - The loader options * * @returns {Promise<*>} Always returns a promise even if there is a callback provided * * @example * // Example using Promises * * PathLoader * .load('./package.json') * .then(JSON.parse) * .then(function (document) { * console.log(document.name + ' (' + document.version + '): ' + document.description); * }, function (err) { * console.error(err.stack); * }); * * @example * // Example using options.prepareRequest to provide authentication details for a remotely secure URL * * PathLoader * .load('https://api.github.com/repos/whitlockjc/path-loader', { * prepareRequest: function (req, callback) { * req.auth('my-username', 'my-password'); * callback(undefined, req); * } * }) * .then(JSON.parse) * .then(function (document) { * console.log(document.full_name + ': ' + document.description); * }, function (err) { * console.error(err.stack); * }); * * @example * // Example loading a YAML file * * PathLoader * .load('/Users/not-you/projects/path-loader/.travis.yml') * .then(YAML.safeLoad) * .then(function (document) { * console.log('path-loader uses the', document.language, 'language.'); * }, function (err) { * console.error(err.stack); * }); * * @example * // Example loading a YAML file with options.processContent (Useful if you need information in the raw response) * * PathLoader * .load('/Users/not-you/projects/path-loader/.travis.yml', { * processContent: function (res, callback) { * callback(YAML.safeLoad(res.text)); * } * }) * .then(function (document) { * console.log('path-loader uses the', document.language, 'language.'); * }, function (err) { * console.error(err.stack); * }); */ module.exports.load = function (location, options) { var allTasks = Promise.resolve(); // Default options to empty object if (typeof options === 'undefined') { options = {}; } // Validate arguments allTasks = allTasks.then(function () { if (typeof location === 'undefined') { throw new TypeError('location is required'); } else if (typeof location !== 'string') { throw new TypeError('location must be a string'); } if (typeof options !== 'undefined') { if (typeof options !== 'object') { throw new TypeError('options must be an object'); } else if (typeof options.processContent !== 'undefined' && typeof options.processContent !== 'function') { throw new TypeError('options.processContent must be a function'); } } }); // Load the document from the provided location and process it allTasks = allTasks .then(function () { return new Promise(function (resolve, reject) { var loader = getLoader(location); loader.load(location, options || {}, function (err, document) { if (err) { reject(err); } else { resolve(document); } }); }); }) .then(function (res) { if (options.processContent) { return new Promise(function (resolve, reject) { // For consistency between file and http, always send an object with a 'text' property containing the raw // string value being processed. if (typeof res !== 'object') { res = {text: res}; } // Pass the path being loaded res.location = location; options.processContent(res, function (err, processed) { if (err) { reject(err); } else { resolve(processed); } }); }); } else { // If there was no content processor, we will assume that for all objects that it is a Superagent response // and will return its `text` property value. Otherwise, we will return the raw response. return typeof res === 'object' ? res.text : res; } }); return allTasks; };