'use strict';

const fs = require('fs');
const path = require('path');
const url = require('url');
const util = require('util');
const got = require('got');
const mime = require('mime');
const debug = require('debug')('asset-resolver');
const globby = require('globby');

const cache = {};
const readFile = util.promisify(fs.readFile);

function isUrl(resource) {
  return /(^\/\/)|(:\/\/)/.test(resource);
}

function handle(filter) {
  return resource => {
    debug('handle request', resource.path);
    return Promise.resolve(resource)
      .then(filter)
      .then(result => {
        if (!result) {
          debug('FAILED');
          return Promise.reject(
            new Error(`${resource.path} rejected by filter`)
          );
        }

        debug('Passed filter:', resource.path);
        return resource;
      });
  };
}

/**
 * Token generated by concatenating username and password with `:` character within a base64 encoded string.
 * @param  {String} user User identifier.
 * @param  {String} pass Password.
 * @returns {String} Base64 encoded authentication token.
 */
const token = (user, pass) =>
  Buffer.from([user, pass].join(':')).toString('base64');

/**
 * Get external resource
 * @param {string} resource Ressource to be fetched
 * @param {object} opts Option hash
 * @returns {Promise} Promise
 */
function requestAsync(resource, opts = {}) {
  const settings = {
    followRedirect: true,
    encoding: null,
    rejectUnauthorized: false,
    retry: 0
  };

  if (opts.user && opts.pass) {
    settings.headers = {
      Authorization: `Basic ${token(opts.user, opts.pass)}`
    };
  }

  return new Promise((resolve, reject) => {
    // Handle protocol-relative urls
    resource = url.resolve('http://te.st', resource); // eslint-disable-line node/no-deprecated-api
    got(resource, settings)
      .then(response => {
        if (response.statusCode !== 200) {
          const msg = `Wrong status code ${response.statusCode} for ${resource}`;
          debug(msg);
          return reject(new Error(msg));
        }

        const {headers = {}} = response;

        const mimeType = headers['content-type'] || mime.getType(resource);

        resolve({
          contents: response.body,
          path: resource,
          mime: mimeType
        });
      })
      .catch(error => {
        debug('Url failed:', error.message || error);
        return reject(error);
      });
  });
}

/**
 * Get local resource
 * @param {string} resource Resource to be fetched
 * @returns {Promise} Promise
 */
function readAsync(resource) {
  return readFile(resource).then(body => {
    const mimeType = mime.getType(resource);

    debug('Fetched:', resource);

    return {
      contents: body,
      path: resource,
      mime: mimeType
    };
  });
}

function join(base, file) {
  if (isUrl(file)) {
    return file;
  }

  if (isUrl(base)) {
    // eslint-disable-next-line node/no-deprecated-api
    return url.resolve(base.endsWith('/') ? base : `${base}/`, file);
  }

  return path.join(base, file);
}

function glob(base) {
  return base.reduce((res, val) => {
    if (isUrl(val)) {
      res.push(val);
      return res;
    }

    if (fs.existsSync(val) && fs.lstatSync(val).isDirectory()) {
      res.push(val);
      return res;
    }

    let files = [];
    try {
      files = globby.sync([val], {
        nodir: false,
        onlyDirectories: true,
        cwd: process.cwd()
      });
    } catch (error) {
      console.error(error.message);
    }

    return [...res, ...files];
  }, []);
}

function getResource(base, file, opts) {
  const resource = join(base, file);
  if (cache[resource]) {
    return cache[resource].then(handle(opts.filter));
  }

  if (isUrl(resource)) {
    cache[resource] = requestAsync(resource, opts);
  } else {
    cache[resource] = readAsync(resource);
  }

  return cache[resource].then(handle(opts.filter));
}

module.exports.getResource = getResource;
module.exports.glob = glob;

@@ -370,39 +370,60 @@
 urn 
-/(%5E%5C/%5C/)%7C(:%5C/%5C/)/.test(resource
+resource.startsWith('//') %7C%7C resource.includes('://'
 );%0A%7D

Use string.startsWith and string.includes.