<commit_before>/*!
 * node-sass: lib/extensions.js
 */

var eol = require('os').EOL,
  fs = require('fs'),
  pkg = require('../package.json'),
  mkdir = require('mkdirp'),
  path = require('path'),
  defaultBinaryDir = path.join(__dirname, '..', 'vendor'),
  trueCasePathSync = require('true-case-path');

/**
 * Get the human readable name of the Platform that is running
 *
 * @param  {string} platform - An OS platform to match, or null to fallback to
 * the current process platform
 * @return {Object} The name of the platform if matched, false otherwise
 *
 * @api public
 */
function getHumanPlatform(platform) {
  switch (platform || process.platform) {
    case 'darwin': return 'OS X';
    case 'freebsd': return 'FreeBSD';
    case 'linux': return 'Linux';
    case 'linux_musl': return 'Linux/musl';
    case 'win32': return 'Windows';
    default: return false;
  }
}

/**
 * Provides a more readable version of the architecture
 *
 * @param  {string} arch - An instruction architecture name to match, or null to
 * lookup the current process architecture
 * @return {Object} The value of the process architecture, or false if unknown
 *
 * @api public
 */
function getHumanArchitecture(arch) {
  switch (arch || process.arch) {
    case 'ia32': return '32-bit';
    case 'x86': return '32-bit';
    case 'x64': return '64-bit';
    default: return false;
  }
}

/**
 * Get the friendly name of the Node environment being run
 *
 * @param  {Object} abi - A Node Application Binary Interface value, or null to
 * fallback to the current Node ABI
 * @return {Object} Returns a string name of the Node environment or false if
 * unmatched
 *
 * @api public
 */
function getHumanNodeVersion(abi) {
  switch (parseInt(abi || process.versions.modules, 10)) {
    case 11: return 'Node 0.10.x';
    case 14: return 'Node 0.12.x';
    case 42: return 'io.js 1.x';
    case 43: return 'io.js 1.1.x';
    case 44: return 'io.js 2.x';
    case 45: return 'io.js 3.x';
    case 46: return 'Node.js 4.x';
    case 47: return 'Node.js 5.x';
    case 48: return 'Node.js 6.x';
    case 49: return 'Electron 1.3.x';
    case 50: return 'Electron 1.4.x';
    case 51: return 'Node.js 7.x';
    case 53: return 'Electron 1.6.x';
    case 57: return 'Node.js 8.x';
    case 59: return 'Node.js 9.x';
    case 64: return 'Node.js 10.x';
    case 67: return 'Node.js 11.x';
    case 72: return 'Node.js 12.x';
    case 79: return 'Node.js 13.x';
    case 83: return 'Node.js 14.x';
    default: return false;
  }
}

/**
 * Get a human readable description of where node-sass is running to support
 * user error reporting when something goes wrong
 *
 * @param  {string} env - The name of the native bindings that is to be parsed
 * @return {string} A description of what os, architecture, and Node version
 * that is being run
 *
 * @api public
 */
function getHumanEnvironment(env) {
  var binding = env.replace(/_binding\.node$/, ''),
    parts = binding.split('-'),
    platform = getHumanPlatform(parts[0]),
    arch = getHumanArchitecture(parts[1]),
    runtime = getHumanNodeVersion(parts[2]);

  if (parts.length !== 3) {
    return 'Unknown environment (' + binding + ')';
  }

  if (!platform) {
    platform = 'Unsupported platform (' + parts[0] + ')';
  }

  if (!arch) {
    arch = 'Unsupported architecture (' + parts[1] + ')';
  }

  if (!runtime) {
    runtime = 'Unsupported runtime (' + parts[2] + ')';
  }

  return [
    platform, arch, 'with', runtime,
  ].join(' ');
}

/**
 * Get the value of the binaries under the default path
 *
 * @return {Array} The currently installed node-sass bindings
 *
 * @api public
 */
function getInstalledBinaries() {
  return fs.readdirSync(getBinaryDir());
}

/**
 * Check that an environment matches the allowlisted values or the current
 * environment if no parameters are passed
 *
 * @param  {string} platform - The name of the OS platform(darwin, win32, etc...)
 * @param  {string} arch - The instruction set architecture of the Node environment
 * @param  {string} abi - The Node Application Binary Interface
 * @return {Boolean} True, if node-sass supports the current platform, false otherwise
 *
 * @api public
 */
function isSupportedEnvironment(platform, arch, abi) {
  return (
    false !== getHumanPlatform(platform) &&
    false !== getHumanArchitecture(arch) &&
    false !== getHumanNodeVersion(abi)
  );
}

/**
 * Get the value of a CLI argument
 *
 * @param {String} name
 * @param {Array} args
 * @api private
 */

function getArgument(name, args) {
  var flags = args || process.argv.slice(2),
    index = flags.lastIndexOf(name);

  if (index === -1 || index + 1 >= flags.length) {
    return null;
  }

  return flags[index + 1];
}

/**
 * Get binary name.
 * If environment variable SASS_BINARY_NAME,
 * .npmrc variable sass_binary_name or
 * process argument --binary-name is provided,
 * return it as is, otherwise make default binary
 * name: {platform}-{arch}-{v8 version}.node
 *
 * @api public
 */

function getBinaryName() {
  var binaryName,
    variant,
    platform = process.platform;

  if (getArgument('--sass-binary-name')) {
    binaryName = getArgument('--sass-binary-name');
  } else if (process.env.SASS_BINARY_NAME) {
    binaryName = process.env.SASS_BINARY_NAME;
  } else if (process.env.npm_config_sass_binary_name) {
    binaryName = process.env.npm_config_sass_binary_name;
  } else if (pkg.nodeSassConfig && pkg.nodeSassConfig.binaryName) {
    binaryName = pkg.nodeSassConfig.binaryName;
  } else {
    variant = getPlatformVariant();
    if (variant) {
      platform += '_' + variant;
    }

    binaryName = [
      platform, '-',
      process.arch, '-',
      process.versions.modules
    ].join('');
  }

  return [binaryName, 'binding.node'].join('_');
}

/**
 * Determine the URL to fetch binary file from.
 * By default fetch from the node-sass distribution
 * site on GitHub.
 *
 * The default URL can be overridden using
 * the environment variable SASS_BINARY_SITE,
 * .npmrc variable sass_binary_site or
 * or a command line option --sass-binary-site:
 *
 *   node scripts/install.js --sass-binary-site http://example.com/
 *
 * The URL should to the mirror of the repository
 * laid out as follows:
 *
 * SASS_BINARY_SITE/
 *
 *  v3.0.0
 *  v3.0.0/freebsd-x64-14_binding.node
 *  ....
 *  v3.0.0
 *  v3.0.0/freebsd-ia32-11_binding.node
 *  v3.0.0/freebsd-x64-42_binding.node
 *  ... etc. for all supported versions and platforms
 *
 * @api public
 */

function getBinaryUrl() {
  var site = getArgument('--sass-binary-site') ||
             process.env.SASS_BINARY_SITE  ||
             process.env.npm_config_sass_binary_site ||
             (pkg.nodeSassConfig && pkg.nodeSassConfig.binarySite) ||
             'https://github.com/sass/node-sass/releases/download';

  return [site, 'v' + pkg.version, getBinaryName()].join('/');
}

/**
 * Get binary dir.
 * If environment variable SASS_BINARY_DIR,
 * .npmrc variable sass_binary_dir or
 * process argument --sass-binary-dir is provided,
 * select it by appending binary name, otherwise
 * use default binary dir.
 * Once the primary selection is made, check if
 * callers wants to throw if file not exists before
 * returning.
 *
 * @api public
 */

function getBinaryDir() {
  var binaryDir;

  if (getArgument('--sass-binary-dir')) {
    binaryDir = getArgument('--sass-binary-dir');
  } else if (process.env.SASS_BINARY_DIR) {
    binaryDir = process.env.SASS_BINARY_DIR;
  } else if (process.env.npm_config_sass_binary_dir) {
    binaryDir = process.env.npm_config_sass_binary_dir;
  } else if (pkg.nodeSassConfig && pkg.nodeSassConfig.binaryDir) {
    binaryDir = pkg.nodeSassConfig.binaryDir;
  } else {
    binaryDir = defaultBinaryDir;
  }

  return binaryDir;
}

/**
 * Get binary path.
 * If environment variable SASS_BINARY_PATH,
 * .npmrc variable sass_binary_path or
 * process argument --sass-binary-path is provided,
 * select it by appending binary name, otherwise
 * make default binary path using binary name.
 * Once the primary selection is made, check if
 * callers wants to throw if file not exists before
 * returning.
 *
 * @api public
 */

function getBinaryPath() {
  var binaryPath;

  if (getArgument('--sass-binary-path')) {
    binaryPath = getArgument('--sass-binary-path');
  } else if (process.env.SASS_BINARY_PATH) {
    binaryPath = process.env.SASS_BINARY_PATH;
  } else if (process.env.npm_config_sass_binary_path) {
    binaryPath = process.env.npm_config_sass_binary_path;
  } else if (pkg.nodeSassConfig && pkg.nodeSassConfig.binaryPath) {
    binaryPath = pkg.nodeSassConfig.binaryPath;
  } else {
    binaryPath = path.join(getBinaryDir(), getBinaryName().replace(/_(?=binding\.node)/, '/'));
  }

  if (process.versions.modules < 46) {
    return binaryPath;
  }

  try {
    return trueCasePathSync(binaryPath) || binaryPath;
  } catch (e) {
    return binaryPath;
  }
}

/**
 * An array of paths suitable for use as a local disk cache of the binding.
 *
 * @return {[]String} an array of paths
 * @api public
 */
function getCachePathCandidates() {
  return [
    process.env.npm_config_sass_binary_cache,
    process.env.npm_config_cache,
  ].filter(function(_) { return _; });
}

/**
 * The most suitable location for caching the binding on disk.
 *
 * Given the candidates directories provided by `getCachePathCandidates()` this
 * returns the first writable directory. By treating the candidate directories
 * as a prioritised list this method is deterministic, assuming no change to the
 * local environment.
 *
 * @return {String} directory to cache binding
 * @api public
 */
function getBinaryCachePath() {
  var i,
    cachePath,
    cachePathCandidates = getCachePathCandidates();

  for (i = 0; i < cachePathCandidates.length; i++) {
    cachePath = path.join(cachePathCandidates[i], pkg.name, pkg.version);

    try {
      mkdir.sync(cachePath);
      return cachePath;
    } catch (e) {
      // Directory is not writable, try another
    }
  }

  return '';
}

/**
 * The cached binding
 *
 * Check the candidates directories provided by `getCachePathCandidates()` for
 * the binding file, if it exists. By treating the candidate directories
 * as a prioritised list this method is deterministic, assuming no change to the
 * local environment.
 *
 * @return {String} path to cached binary
 * @api public
 */
function getCachedBinary() {
  var i,
    cachePath,
    cacheBinary,
    cachePathCandidates = getCachePathCandidates(),
    binaryName = getBinaryName();

  for (i = 0; i < cachePathCandidates.length; i++) {
    cachePath = path.join(cachePathCandidates[i], pkg.name, pkg.version);
    cacheBinary = path.join(cachePath, binaryName);

    if (fs.existsSync(cacheBinary)) {
      return cacheBinary;
    }
  }

  return '';
}

/**
 * Does the supplied binary path exist
 *
 * @param {String} binaryPath
 * @api public
 */

function hasBinary(binaryPath) {
  return fs.existsSync(binaryPath);
}

/**
 * Get Sass version information
 *
 * @api public
 */

function getVersionInfo(binding) {
  return [
    ['node-sass', pkg.version, '(Wrapper)', '[JavaScript]'].join('\t'),
    ['libsass  ', binding.libsassVersion(), '(Sass Compiler)', '[C/C++]'].join('\t'),
  ].join(eol);
}

/**
 * Gets the platform variant, currently either an empty string or 'musl' for Linux/musl platforms.
 *
 * @api public
 */

function getPlatformVariant() {
  var contents = '';

  if (process.platform !== 'linux') {
    return '';
  }

  try {
    contents = fs.readFileSync(process.execPath);

    // Buffer.indexOf was added in v1.5.0 so cast to string for old node
    // Delay contents.toStrings because it's expensive
    if (!contents.indexOf) {
      contents = contents.toString();
    }

    if (contents.indexOf('libc.musl-x86_64.so.1') !== -1) {
      return 'musl';
    }
  } catch (err) { } // eslint-disable-line no-empty

  return '';
}

module.exports.hasBinary = hasBinary;
module.exports.getBinaryUrl = getBinaryUrl;
module.exports.getBinaryName = getBinaryName;
module.exports.getBinaryDir = getBinaryDir;
module.exports.getBinaryPath = getBinaryPath;
module.exports.getBinaryCachePath = getBinaryCachePath;
module.exports.getCachedBinary = getCachedBinary;
module.exports.getCachePathCandidates = getCachePathCandidates;
module.exports.getVersionInfo = getVersionInfo;
module.exports.getHumanEnvironment = getHumanEnvironment;
module.exports.getInstalledBinaries = getInstalledBinaries;
module.exports.isSupportedEnvironment = isSupportedEnvironment;
<commit_msg>Remove workarounds for old Node.js versions<commit_after>/*!
 * node-sass: lib/extensions.js
 */

var eol = require('os').EOL,
  fs = require('fs'),
  pkg = require('../package.json'),
  mkdir = require('mkdirp'),
  path = require('path'),
  defaultBinaryDir = path.join(__dirname, '..', 'vendor'),
  trueCasePathSync = require('true-case-path');

/**
 * Get the human readable name of the Platform that is running
 *
 * @param  {string} platform - An OS platform to match, or null to fallback to
 * the current process platform
 * @return {Object} The name of the platform if matched, false otherwise
 *
 * @api public
 */
function getHumanPlatform(platform) {
  switch (platform || process.platform) {
    case 'darwin': return 'OS X';
    case 'freebsd': return 'FreeBSD';
    case 'linux': return 'Linux';
    case 'linux_musl': return 'Linux/musl';
    case 'win32': return 'Windows';
    default: return false;
  }
}

/**
 * Provides a more readable version of the architecture
 *
 * @param  {string} arch - An instruction architecture name to match, or null to
 * lookup the current process architecture
 * @return {Object} The value of the process architecture, or false if unknown
 *
 * @api public
 */
function getHumanArchitecture(arch) {
  switch (arch || process.arch) {
    case 'ia32': return '32-bit';
    case 'x86': return '32-bit';
    case 'x64': return '64-bit';
    default: return false;
  }
}

/**
 * Get the friendly name of the Node environment being run
 *
 * @param  {Object} abi - A Node Application Binary Interface value, or null to
 * fallback to the current Node ABI
 * @return {Object} Returns a string name of the Node environment or false if
 * unmatched
 *
 * @api public
 */
function getHumanNodeVersion(abi) {
  switch (parseInt(abi || process.versions.modules, 10)) {
    case 11: return 'Node 0.10.x';
    case 14: return 'Node 0.12.x';
    case 42: return 'io.js 1.x';
    case 43: return 'io.js 1.1.x';
    case 44: return 'io.js 2.x';
    case 45: return 'io.js 3.x';
    case 46: return 'Node.js 4.x';
    case 47: return 'Node.js 5.x';
    case 48: return 'Node.js 6.x';
    case 49: return 'Electron 1.3.x';
    case 50: return 'Electron 1.4.x';
    case 51: return 'Node.js 7.x';
    case 53: return 'Electron 1.6.x';
    case 57: return 'Node.js 8.x';
    case 59: return 'Node.js 9.x';
    case 64: return 'Node.js 10.x';
    case 67: return 'Node.js 11.x';
    case 72: return 'Node.js 12.x';
    case 79: return 'Node.js 13.x';
    case 83: return 'Node.js 14.x';
    default: return false;
  }
}

/**
 * Get a human readable description of where node-sass is running to support
 * user error reporting when something goes wrong
 *
 * @param  {string} env - The name of the native bindings that is to be parsed
 * @return {string} A description of what os, architecture, and Node version
 * that is being run
 *
 * @api public
 */
function getHumanEnvironment(env) {
  var binding = env.replace(/_binding\.node$/, ''),
    parts = binding.split('-'),
    platform = getHumanPlatform(parts[0]),
    arch = getHumanArchitecture(parts[1]),
    runtime = getHumanNodeVersion(parts[2]);

  if (parts.length !== 3) {
    return 'Unknown environment (' + binding + ')';
  }

  if (!platform) {
    platform = 'Unsupported platform (' + parts[0] + ')';
  }

  if (!arch) {
    arch = 'Unsupported architecture (' + parts[1] + ')';
  }

  if (!runtime) {
    runtime = 'Unsupported runtime (' + parts[2] + ')';
  }

  return [
    platform, arch, 'with', runtime,
  ].join(' ');
}

/**
 * Get the value of the binaries under the default path
 *
 * @return {Array} The currently installed node-sass bindings
 *
 * @api public
 */
function getInstalledBinaries() {
  return fs.readdirSync(getBinaryDir());
}

/**
 * Check that an environment matches the allowlisted values or the current
 * environment if no parameters are passed
 *
 * @param  {string} platform - The name of the OS platform(darwin, win32, etc...)
 * @param  {string} arch - The instruction set architecture of the Node environment
 * @param  {string} abi - The Node Application Binary Interface
 * @return {Boolean} True, if node-sass supports the current platform, false otherwise
 *
 * @api public
 */
function isSupportedEnvironment(platform, arch, abi) {
  return (
    false !== getHumanPlatform(platform) &&
    false !== getHumanArchitecture(arch) &&
    false !== getHumanNodeVersion(abi)
  );
}

/**
 * Get the value of a CLI argument
 *
 * @param {String} name
 * @param {Array} args
 * @api private
 */

function getArgument(name, args) {
  var flags = args || process.argv.slice(2),
    index = flags.lastIndexOf(name);

  if (index === -1 || index + 1 >= flags.length) {
    return null;
  }

  return flags[index + 1];
}

/**
 * Get binary name.
 * If environment variable SASS_BINARY_NAME,
 * .npmrc variable sass_binary_name or
 * process argument --binary-name is provided,
 * return it as is, otherwise make default binary
 * name: {platform}-{arch}-{v8 version}.node
 *
 * @api public
 */

function getBinaryName() {
  var binaryName,
    variant,
    platform = process.platform;

  if (getArgument('--sass-binary-name')) {
    binaryName = getArgument('--sass-binary-name');
  } else if (process.env.SASS_BINARY_NAME) {
    binaryName = process.env.SASS_BINARY_NAME;
  } else if (process.env.npm_config_sass_binary_name) {
    binaryName = process.env.npm_config_sass_binary_name;
  } else if (pkg.nodeSassConfig && pkg.nodeSassConfig.binaryName) {
    binaryName = pkg.nodeSassConfig.binaryName;
  } else {
    variant = getPlatformVariant();
    if (variant) {
      platform += '_' + variant;
    }

    binaryName = [
      platform, '-',
      process.arch, '-',
      process.versions.modules
    ].join('');
  }

  return [binaryName, 'binding.node'].join('_');
}

/**
 * Determine the URL to fetch binary file from.
 * By default fetch from the node-sass distribution
 * site on GitHub.
 *
 * The default URL can be overridden using
 * the environment variable SASS_BINARY_SITE,
 * .npmrc variable sass_binary_site or
 * or a command line option --sass-binary-site:
 *
 *   node scripts/install.js --sass-binary-site http://example.com/
 *
 * The URL should to the mirror of the repository
 * laid out as follows:
 *
 * SASS_BINARY_SITE/
 *
 *  v3.0.0
 *  v3.0.0/freebsd-x64-14_binding.node
 *  ....
 *  v3.0.0
 *  v3.0.0/freebsd-ia32-11_binding.node
 *  v3.0.0/freebsd-x64-42_binding.node
 *  ... etc. for all supported versions and platforms
 *
 * @api public
 */

function getBinaryUrl() {
  var site = getArgument('--sass-binary-site') ||
             process.env.SASS_BINARY_SITE  ||
             process.env.npm_config_sass_binary_site ||
             (pkg.nodeSassConfig && pkg.nodeSassConfig.binarySite) ||
             'https://github.com/sass/node-sass/releases/download';

  return [site, 'v' + pkg.version, getBinaryName()].join('/');
}

/**
 * Get binary dir.
 * If environment variable SASS_BINARY_DIR,
 * .npmrc variable sass_binary_dir or
 * process argument --sass-binary-dir is provided,
 * select it by appending binary name, otherwise
 * use default binary dir.
 * Once the primary selection is made, check if
 * callers wants to throw if file not exists before
 * returning.
 *
 * @api public
 */

function getBinaryDir() {
  var binaryDir;

  if (getArgument('--sass-binary-dir')) {
    binaryDir = getArgument('--sass-binary-dir');
  } else if (process.env.SASS_BINARY_DIR) {
    binaryDir = process.env.SASS_BINARY_DIR;
  } else if (process.env.npm_config_sass_binary_dir) {
    binaryDir = process.env.npm_config_sass_binary_dir;
  } else if (pkg.nodeSassConfig && pkg.nodeSassConfig.binaryDir) {
    binaryDir = pkg.nodeSassConfig.binaryDir;
  } else {
    binaryDir = defaultBinaryDir;
  }

  return binaryDir;
}

/**
 * Get binary path.
 * If environment variable SASS_BINARY_PATH,
 * .npmrc variable sass_binary_path or
 * process argument --sass-binary-path is provided,
 * select it by appending binary name, otherwise
 * make default binary path using binary name.
 * Once the primary selection is made, check if
 * callers wants to throw if file not exists before
 * returning.
 *
 * @api public
 */

function getBinaryPath() {
  var binaryPath;

  if (getArgument('--sass-binary-path')) {
    binaryPath = getArgument('--sass-binary-path');
  } else if (process.env.SASS_BINARY_PATH) {
    binaryPath = process.env.SASS_BINARY_PATH;
  } else if (process.env.npm_config_sass_binary_path) {
    binaryPath = process.env.npm_config_sass_binary_path;
  } else if (pkg.nodeSassConfig && pkg.nodeSassConfig.binaryPath) {
    binaryPath = pkg.nodeSassConfig.binaryPath;
  } else {
    binaryPath = path.join(getBinaryDir(), getBinaryName().replace(/_(?=binding\.node)/, '/'));
  }

  try {
    return trueCasePathSync(binaryPath) || binaryPath;
  } catch (e) {
    return binaryPath;
  }
}

/**
 * An array of paths suitable for use as a local disk cache of the binding.
 *
 * @return {[]String} an array of paths
 * @api public
 */
function getCachePathCandidates() {
  return [
    process.env.npm_config_sass_binary_cache,
    process.env.npm_config_cache,
  ].filter(function(_) { return _; });
}

/**
 * The most suitable location for caching the binding on disk.
 *
 * Given the candidates directories provided by `getCachePathCandidates()` this
 * returns the first writable directory. By treating the candidate directories
 * as a prioritised list this method is deterministic, assuming no change to the
 * local environment.
 *
 * @return {String} directory to cache binding
 * @api public
 */
function getBinaryCachePath() {
  var i,
    cachePath,
    cachePathCandidates = getCachePathCandidates();

  for (i = 0; i < cachePathCandidates.length; i++) {
    cachePath = path.join(cachePathCandidates[i], pkg.name, pkg.version);

    try {
      mkdir.sync(cachePath);
      return cachePath;
    } catch (e) {
      // Directory is not writable, try another
    }
  }

  return '';
}

/**
 * The cached binding
 *
 * Check the candidates directories provided by `getCachePathCandidates()` for
 * the binding file, if it exists. By treating the candidate directories
 * as a prioritised list this method is deterministic, assuming no change to the
 * local environment.
 *
 * @return {String} path to cached binary
 * @api public
 */
function getCachedBinary() {
  var i,
    cachePath,
    cacheBinary,
    cachePathCandidates = getCachePathCandidates(),
    binaryName = getBinaryName();

  for (i = 0; i < cachePathCandidates.length; i++) {
    cachePath = path.join(cachePathCandidates[i], pkg.name, pkg.version);
    cacheBinary = path.join(cachePath, binaryName);

    if (fs.existsSync(cacheBinary)) {
      return cacheBinary;
    }
  }

  return '';
}

/**
 * Does the supplied binary path exist
 *
 * @param {String} binaryPath
 * @api public
 */

function hasBinary(binaryPath) {
  return fs.existsSync(binaryPath);
}

/**
 * Get Sass version information
 *
 * @api public
 */

function getVersionInfo(binding) {
  return [
    ['node-sass', pkg.version, '(Wrapper)', '[JavaScript]'].join('\t'),
    ['libsass  ', binding.libsassVersion(), '(Sass Compiler)', '[C/C++]'].join('\t'),
  ].join(eol);
}

/**
 * Gets the platform variant, currently either an empty string or 'musl' for Linux/musl platforms.
 *
 * @api public
 */

function getPlatformVariant() {
  var contents = '';

  if (process.platform !== 'linux') {
    return '';
  }

  try {
    contents = fs.readFileSync(process.execPath);

    if (contents.indexOf('libc.musl-x86_64.so.1') !== -1) {
      return 'musl';
    }
  } catch (err) { } // eslint-disable-line no-empty

  return '';
}

module.exports.hasBinary = hasBinary;
module.exports.getBinaryUrl = getBinaryUrl;
module.exports.getBinaryName = getBinaryName;
module.exports.getBinaryDir = getBinaryDir;
module.exports.getBinaryPath = getBinaryPath;
module.exports.getBinaryCachePath = getBinaryCachePath;
module.exports.getCachedBinary = getCachedBinary;
module.exports.getCachePathCandidates = getCachePathCandidates;
module.exports.getVersionInfo = getVersionInfo;
module.exports.getHumanEnvironment = getHumanEnvironment;
module.exports.getInstalledBinaries = getInstalledBinaries;
module.exports.isSupportedEnvironment = isSupportedEnvironment;
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');
const ejs = require('ejs');
const globby = require('globby');
const json = require('./json2js').json;

exports.mergeJson = function mergeJson(fileName, newContent) {
  const content = this.fs.readJSON(this.destinationPath(fileName), {});

  _.merge(content, newContent, (a, b) => {
    if (_.isArray(a)) {
      return _.uniq(a.concat(b));
    }
  });

  this.fs.writeJSON(this.destinationPath(fileName), content);
};

exports.updateJson = function mergeJson(fileName, update) {
  const content = this.fs.readJSON(this.destinationPath(fileName), {});

  const newContent = update(content);

  this.fs.writeJSON(this.destinationPath(fileName), newContent);
};

exports.replaceInFileWithTemplate = function replaceInFileWithTemplate(templateFileName, destinationFileName, regex, templateScope) {
  const scope = Object.assign({}, this.props, templateScope);

  const originalContent = this.fs.read(this.destinationPath(destinationFileName), {});
  let addContent = this.fs.read(this.templatePath(templateFileName), {});
  addContent = addContent.replace(/([\s\S]*)\n$/, '$1');
  const processedAddContent = ejs.render(addContent, scope);

  const newContent = originalContent.replace(regex, processedAddContent);

  this.fs.write(this.destinationPath(destinationFileName), newContent);
};

exports.replaceInFiles = function replaceInFile(destinationFiles, transform) {
  globby(this.destinationPath(destinationFiles)).then(files => {
    files.forEach(file => {
      const originalContent = this.fs.read(file, {});
      const newContent = transform(originalContent, file);
      this.fs.write(file, newContent);
    });
  });
};

exports.copyTemplate = function copyTemplate(templateFileName, destinationFileName, templateScope) {
  const scope = Object.assign({}, { json }, this.props, templateScope);

  const files = {
    template: templateFileName,
    destination: destinationFileName
  };

  exports.renameFiles(files, this.props);

  this.fs.copyTpl(
    this.templatePath(files.template),
    this.destinationPath(files.destination),
    scope
  );
};

exports.renameFiles = function renameFiles(files, props) {
  if (/^src.*\.js$/.test(files.template)) {
    if (props.js === 'babel') {
      files.template = files.template.replace(/\.js$/, '.babel');
    }
    if (props.js === 'typescript') {
      let ext = '.ts';
      if (props.framework === 'react') {
        ext = '.tsx';
      }
      files.template = files.template.replace(/\.js$/, ext);
      files.destination = files.destination.replace(/\.js$/, ext);
    }
  }

  if (/^src.*\.css$/.test(files.template)) {
    if (props.css === 'scss') {
      files.template = files.template.replace(/\.css$/, '.scss');
      files.destination = files.destination.replace(/\.css$/, '.scss');
    }
    if (props.css === 'less') {
      files.template = files.template.replace(/\.css$/, '.less');
      files.destination = files.destination.replace(/\.css$/, '.less');
    }
  }
};
<commit_msg>force fs commit to allow globby to work<commit_after>'use strict';

const _ = require('lodash');
const ejs = require('ejs');
const globby = require('globby');
const json = require('./json2js').json;

exports.mergeJson = function mergeJson(fileName, newContent) {
  const content = this.fs.readJSON(this.destinationPath(fileName), {});

  _.merge(content, newContent, (a, b) => {
    if (_.isArray(a)) {
      return _.uniq(a.concat(b));
    }
  });

  this.fs.writeJSON(this.destinationPath(fileName), content);
};

exports.updateJson = function mergeJson(fileName, update) {
  const content = this.fs.readJSON(this.destinationPath(fileName), {});

  const newContent = update(content);

  this.fs.writeJSON(this.destinationPath(fileName), newContent);
};

exports.replaceInFileWithTemplate = function replaceInFileWithTemplate(templateFileName, destinationFileName, regex, templateScope) {
  const scope = Object.assign({}, this.props, templateScope);

  const originalContent = this.fs.read(this.destinationPath(destinationFileName), {});
  let addContent = this.fs.read(this.templatePath(templateFileName), {});
  addContent = addContent.replace(/([\s\S]*)\n$/, '$1');
  const processedAddContent = ejs.render(addContent, scope);

  const newContent = originalContent.replace(regex, processedAddContent);

  this.fs.write(this.destinationPath(destinationFileName), newContent);
};

exports.replaceInFiles = function replaceInFile(destinationFiles, transform) {
  this.fs.commit(() => {
    globby(this.destinationPath(destinationFiles)).then(files => {
      files.forEach(file => {
        const originalContent = this.fs.read(file, {});
        const newContent = transform(originalContent, file);
        this.fs.write(file, newContent);
      });
    });
  });
};

exports.copyTemplate = function copyTemplate(templateFileName, destinationFileName, templateScope) {
  const scope = Object.assign({}, {
    json,
    version: require('../package.json').version,
    date: new Date().toString()
  }, this.props, templateScope);

  const files = {
    template: templateFileName,
    destination: destinationFileName
  };

  exports.renameFiles(files, this.props);

  this.fs.copyTpl(
    this.templatePath(files.template),
    this.destinationPath(files.destination),
    scope
  );
};

exports.renameFiles = function renameFiles(files, props) {
  if (/^src.*\.js$/.test(files.template)) {
    if (props.js === 'babel') {
      files.template = files.template.replace(/\.js$/, '.babel');
    }
    if (props.js === 'typescript') {
      let ext = '.ts';
      if (props.framework === 'react') {
        ext = '.tsx';
      }
      files.template = files.template.replace(/\.js$/, ext);
      files.destination = files.destination.replace(/\.js$/, ext);
    }
  }

  if (/^src.*\.css$/.test(files.template)) {
    if (props.css === 'scss') {
      files.template = files.template.replace(/\.css$/, '.scss');
      files.destination = files.destination.replace(/\.css$/, '.scss');
    }
    if (props.css === 'less') {
      files.template = files.template.replace(/\.css$/, '.less');
      files.destination = files.destination.replace(/\.css$/, '.less');
    }
  }
};
<|endoftext|>


<commit_before>/*
 Copyright 2012 - $Date $ by PeopleWare n.v.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

define(["dojo/_base/declare", "ppwcode-util-contracts/_Mixin", "dojo/_base/lang", "dijit/registry",
        "dojo/dom-class",
        "dijit/_WidgetBase", "../../SemanticObject",
        "dijit/form/TextBox", "dojox/mvc/Output", "dojox/form/CheckedMultiSelect", "dijit/Editor",
        "dijit/form/CheckBox", "dijit/form/Select", "dijit/InlineEditBox",
        "xstyle/css!./_SemanticObjectPane.css"],
  function(declare, _ContractMixin, lang, registry,
           domClass,
           _WidgetBase, SemanticObject,
           TextBox, Output, CheckedMultiSelect, Editor,
           CheckBox, Select, InlineEditBox) {

    var presentationModes = [
      // presentationMode and stylePresentationMode for viewing the data. No interaction allowed.
      "VIEW",

      // presentationMode and stylePresentationMode for editing the data. Interaction allowed.
      "EDIT",

      // presentationMode and stylePresentationMode while the SemanticObject is busy. No interaction allowed.
      "BUSY",

      // presentationMode and stylePresentationMode representing unacceptable data (the object is
      // not civilized, or we have other means of knowing the data is unacceptable).
      // Interaction must be allowed to reset the object, or ameliorate the data/
      // This means this is a sub-state of EDIT.
      "WILD",

      // presentationMode and stylePresentationMode representing an error occurred. We cannot proceed. The widget
      // and its object must be destroyed.
      "ERROR"];

    var stylePresentationModes = presentationModes.slice(0); // copy
    // stylePresentationMode for when there is no target
    stylePresentationModes.push("NOTARGET");

    function recursiveChildWidgets(domNode) {
      // summary:
      //   Returns an Array of all input fields in all widgets, including child widgets,
      //   that are eligible for a state change.
      // description:
      //   All input fields in the widgets are returned by defaults.
      //   Widgets on which the property `ignoreStylePresentationModeChange` is set to true are ignored.
      //   These widgets take responsibility of managing their state themselves.
      //   This option was introduced to allow overriding the default behaviour.

      return registry.findWidgets(domNode).reduce(
        function(acc, w) {
          if (!w.ignoreStylePresentationModeChange) {
            acc.push(w);
          }
          return acc.concat(recursiveChildWidgets(w.domNode));
        },
        []
      );
    }

    function setStylePresentationMode(sop, stylePresentationMode, /*Boolean?*/ created) {
      // create:
      //   Only relevant for "EDIT". Falsy if we are editing a fresh object, truthy if not.
      var domNode = sop.get("domNode");
      if (domNode) {
        var widgetState = null;
        //noinspection FallthroughInSwitchStatementJS
        switch (stylePresentationMode) {
          case _SemanticObjectPane.prototype.NOTARGET:
            widgetState = {readOnly: true, disabled: true};
            break;
          case _SemanticObjectPane.prototype.EDIT:
          case _SemanticObjectPane.prototype.WILD:
            widgetState = {readOnly: false, disabled: false};
            break;
          case _SemanticObjectPane.prototype.BUSY:
          case _SemanticObjectPane.prototype.ERROR:
            widgetState = {readOnly: false, disabled: true};
            break;
          default: // VIEW
            widgetState = {readOnly: true, disabled: false};
        }
        var innerWidgets = recursiveChildWidgets(domNode);
        innerWidgets.forEach(function(w) {
          if (w.isInstanceOf(TextBox) ||
              w.isInstanceOf(Output) ||
              w.isInstanceOf(CheckedMultiSelect) ||
              w.isInstanceOf(CheckBox) ||
              w.isInstanceOf(Select) ||
              w.stylePresentationModeDependent) {
            w.set("readOnly", widgetState.readOnly || !!(created && w.cannotBeChangedAfterCreate));
            w.set("disabled", widgetState.disabled);
          }
          else if (w.isInstanceOf(InlineEditBox) || w.isInstanceOf(Editor)) { // only supports disabled, which === readOnly
            w.set("disabled",
              widgetState.disabled ||
              widgetState.readOnly || !!(created && w.cannotBeChangedAfterCreate));
          }
        });
        if (stylePresentationMode === _SemanticObjectPane.prototype.VIEW ||
            stylePresentationMode === _SemanticObjectPane.prototype.EDIT) {
          domClass.replace(domNode,
            "SemanticObjectPane_enabled",
            "SemanticObjectPane_busy SemanticObjectPane_wild SemanticObjectPane_disabled SemanticObjectPane_error SemanticObjectPane_notarget");
        }
        else if (stylePresentationMode === _SemanticObjectPane.prototype.BUSY) {
          domClass.replace(domNode,
            "SemanticObjectPane_busy",
            "SemanticObjectPane_enabled SemanticObjectPane_wild SemanticObjectPane_disabled SemanticObjectPane_error SemanticObjectPane_notarget");
        }
        else if (stylePresentationMode === _SemanticObjectPane.prototype.WILD) {
          domClass.replace(domNode,
            "SemanticObjectPane_wild",
            "SemanticObjectPane_enabled SemanticObjectPane_busy SemanticObjectPane_disabled SemanticObjectPane_error SemanticObjectPane_notarget");
        }
        else if (stylePresentationMode === _SemanticObjectPane.prototype.ERROR) {
          domClass.replace(domNode,
            "SemanticObjectPane_error",
            "SemanticObjectPane_enabled SemanticObjectPane_busy SemanticObjectPane_wild SemanticObjectPane_disabled SemanticObjectPane_notarget");
        }
        else { // NOTARGET
          domClass.replace(domNode,
            " SemanticObjectPane_notarget",
            "SemanticObjectPane_enabled SemanticObjectPane_busy SemanticObjectPane_wild SemanticObjectPane_error SemanticObjectPane_disabled");
        }
      }
    }

    //noinspection LocalVariableNamingConventionJS
    var _SemanticObjectPane = declare([_WidgetBase, _ContractMixin], {
      // summary:
      //   Widget that represents a SemanticObject in detail, and that gives the opportunity
      //   to the user the view the details, edit the details, and create a new object.
      //   Abstract class to be extended for particular subtypes of SemanticObject.
      // description:
      //   What is common to all subtypes is that the widget:
      //   - has a `target` that is a SemanticObject; getTargetType() returns the top-most supported
      //     Constructor of supported targets. All targets must be instances of this type.
      //   - has an `presentationMode` (view, edit, busy, wild, error)
      //   - has a `stylePresentationMode`
      //
      //   The representation should reflect the presentationMode in a clear visual way to the user.
      //   This is the `stylePresentationModel`. It is the `presentationMode` if `target !== null`,
      //   and `NOTARGET` otherwise.
      //   Even when the information shown is completely read-only, widgets should extend
      //   this class, to change the representation of the displayed information consistently
      //   with other information in different presentationModes, e.g., in "busy" mode.
      //   The available presentation modes are defined in _SemanticObjectPane.prototype.presentationModes.
      //
      //   Instances can be wrapped around zero or more _SemanticObjectPanes, recursively (no loops!).
      //   We take care of propagating `presentationMode`. Subclasses need to override
      //   getWrappedDetails to return the wrapped details. All instances need to be instances of this class.
      //   The default implementation returns an empty array.
      //   The target of a wrapped detail might be the same target as our target, but it might be
      //   another related object, of a different type. set("target", ...) will call _propagateTarget, which is
      //   chained, so that subclasses can add propagation of setting the target. Our implementation only sets our
      //   target.
      //
      //   This class is concerned with presentation. Other classes might add presentation
      //   and functionality to support interaction with the user (save and cancel buttons, etc. -
      //   see e.g. ppwcode persistence).

      _c_invar: [
        function() {return this.get("presentationMode");},
        function() {return this.presentationModes.indexOf(this.get("presentationMode")) >= 0;},
        function() {return this.getTargetType();},
        function() {return this.getTargetType().prototype.isInstanceOf(SemanticObject);},
        function() {
          return this.get("target") === null ||
                 (this.get("target").isInstanceOf && this.get("target").isInstanceOf(this.getTargetType()));
        },
        function() {return this.get("stylePresentationMode");},
        function() {return this.stylePresentationModes.indexOf(this.get("stylePresentationMode")) >= 0;},
        function() {return (this.get("stylePresentationMode") === this.NOTARGET) === (this.get("target") === null);},
        function() {
          return this.get("target") !== null
            ? this.get("stylePresentationMode") === this.get("presentationMode") // jshint ignore:line
            : true;
        },
        function() {return this._wrappedDetails() !== null;},
        function() {return lang.isArray(this._wrappedDetails());},
        {
          objectSelector: function() {
            return this._wrappedDetails();
          },
          invars: [
            function(wd) {
              return wd && wd !== null &&
                     wd.isInstanceOf && wd.isInstanceOf(_SemanticObjectPane);
            },
            // wrapped details might contain other objects of other types as target,
            // or null, but the presentationMode needs to be in sync. The stylePresentationMode
            // can differ.
            function(wd) {
              return wd.get("presentationMode") === this.get("presentationMode");
            }
          ]
        }
      ],

      "-chains-": {
        _propagateTarget: "after",
        _propagateOpener: "after",
        _localPresentationModeChange: "after"
      },

      // target: SemanticObject
      //    SemanticObject that is represented.
      //    Access in declarative template with  ... data-dojo-props="value: at('rel:', BINDING_PROPERTY_NAME)
      target: null,

      // presentationMode: String
      //    The presentation mode is either view, edit, busy, wild, or error
      presentationMode: stylePresentationModes[0], // default value

      // opener: Function
      //   Function that attempts to open a new "window" or "pane" for another PersistentObject
      //   (which is mostly linked to the current one)
      opener: null,

      postCreate: function() {
        this.inherited(arguments);
        domClass.add(this.get("domNode"), "SemanticObjectPane");
      },

      // stylePresentationMode: String
      //    The stylePresentationMode is the same as the presentationMode, except when there is no target.
      //    Then it is NOTARGET.
      _getStylePresentationModeAttr: function() {
        return this.target ? this.get("presentationMode") : this.NOTARGET;
      },

      isInEditMode: function() {
        // summary:
        //    This is in a `stylePresentationMode` that allows the user to change the values, if there is a target and
        //    it is editable.
        return this.target &&
               (this.presentationMode === this.EDIT ||
                this.presentationMode === this.BUSY ||
                this.presentationMode === this.WILD);
      },

      _wrappedDetails: function() {
        // summary:
        //   Array containing the wrapped details, a subclass wants the presentationMode propagated to.
        // tags:
        //   protected

        return []; // return Array
      },

      getTargetType: function() {
        // summary:
        //    The supported type of SemanticObjects. All targets must be an instance of this type.
        // description:
        //    Subclasses should overwrite to return the correct type.

        return SemanticObject;
      },

      _propagateTarget: function(/*SemanticObject*/ so) {
        // summary:
        //   Propagate the target as appropriate to wrapped details.
        //   Chained. Subtypes could add propagation to wrapped details.
        // tags:
        //   protected
        // description:
        //   Does nothing in _SemanticObjectPane.

        this._c_NOP(so);
      },

      _setTargetAttr: function(so) {
        // summary:
        //    Sets the target of this instance. Chained. Subtypes could add propagation to wrapped details.
        this._c_pre(function() {return so === null || (so.isInstanceOf && so.isInstanceOf(this.getTargetType()));});

        if (so !== this.get("target")) {
          this._set("target", so);
        }
        this._propagateTarget(so);
        this.set("presentationMode", so && so.persistenceId === null ? this.EDIT : this.VIEW);
      },

      _propagateOpener: function(/*Function*/ opener) {
        // summary:
        //   Propagate the opener function as appropriate to wrapped details.
        //   Chained. Subtypes could add propagation to wrapped details.
        // tags:
        //   protected
        // description:
        //   Does nothing in _SemanticObjectPane.

        this._c_NOP(opener);
      },

      _setOpenerAttr: function(opener) {
        if (opener !== this.get("opener")) {
          this._set("opener", opener);
        }
        this._propagateOpener(opener);
      },

      _setPresentationModeAttr: function(value) {
        // summary:
        //    Set the presentationMode, and propagate to the wrapped details.
        //    Also makes all innerWidgets read-only in presentationMode VIEW,
        //    disabled in presentationMode BUSY, and not-read-only and enabled
        //    in the other presentationModes.

        // Called during create by _WidgetBase with default value automatically
        this._c_pre(function() {return value !== null;});
        this._c_pre(function() {return _SemanticObjectPane.prototype.presentationModes.indexOf(value) >= 0;});

        this._set("presentationMode", value);
        this._wrappedDetails().forEach(function(wd) {
          wd.set("presentationMode", value);
        });
        var stylePresentationMode = this.get("stylePresentationMode");
        var target = this.get("target");
        setStylePresentationMode(this, stylePresentationMode, target && target.get("persistenceId"));
        if (!this._destroyed) {
          // if we are destroyed, there are no more domNodes
          this._localPresentationModeChange(value);
        }
      },

      _localPresentationModeChange: function(/*String*/ presentationMode) {
        // summary:
        //   Make changes to representation to represent the
        //   new edit mode. Chained. Overwrite when needed.
        // tags:
        //   protected
        // description:
        //   Does nothing in _SemanticObjectPane

        this._c_NOP(presentationMode);
      }

    });

    // All supported presentationModes
    _SemanticObjectPane.prototype.presentationModes = presentationModes;
    // All supported stylePresentationModes
    _SemanticObjectPane.prototype.stylePresentationModes = stylePresentationModes;
    stylePresentationModes.forEach(function(em) {
      _SemanticObjectPane.prototype[em] = em;
    });

    return _SemanticObjectPane; // return _SemanticObjectPane

  }
);
<commit_msg>Code inspection. Added TODO for unresolved warning.<commit_after>/*
 Copyright 2012 - $Date $ by PeopleWare n.v.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

define(["dojo/_base/declare", "ppwcode-util-contracts/_Mixin", "dojo/_base/lang", "dijit/registry",
        "dojo/dom-class",
        "dijit/_WidgetBase", "../../SemanticObject",
        "dijit/form/TextBox", "dojox/mvc/Output", "dojox/form/CheckedMultiSelect", "dijit/Editor",
        "dijit/form/CheckBox", "dijit/form/Select", "dijit/InlineEditBox",
        "xstyle/css!./_SemanticObjectPane.css"],
  function(declare, _ContractMixin, lang, registry,
           domClass,
           _WidgetBase, SemanticObject,
           TextBox, Output, CheckedMultiSelect, Editor,
           CheckBox, Select, InlineEditBox) {

    var presentationModes = [
      // presentationMode and stylePresentationMode for viewing the data. No interaction allowed.
      "VIEW",

      // presentationMode and stylePresentationMode for editing the data. Interaction allowed.
      "EDIT",

      // presentationMode and stylePresentationMode while the SemanticObject is busy. No interaction allowed.
      "BUSY",

      // presentationMode and stylePresentationMode representing unacceptable data (the object is
      // not civilized, or we have other means of knowing the data is unacceptable).
      // Interaction must be allowed to reset the object, or ameliorate the data/
      // This means this is a sub-state of EDIT.
      "WILD",

      // presentationMode and stylePresentationMode representing an error occurred. We cannot proceed. The widget
      // and its object must be destroyed.
      "ERROR"];

    var stylePresentationModes = presentationModes.slice(0); // copy
    // stylePresentationMode for when there is no target
    stylePresentationModes.push("NOTARGET");

    function recursiveChildWidgets(domNode) {
      // summary:
      //   Returns an Array of all input fields in all widgets, including child widgets,
      //   that are eligible for a state change.
      // description:
      //   All input fields in the widgets are returned by defaults.
      //   Widgets on which the property `ignoreStylePresentationModeChange` is set to true are ignored.
      //   These widgets take responsibility of managing their state themselves.
      //   This option was introduced to allow overriding the default behaviour.

      return registry.findWidgets(domNode).reduce(
        function(acc, w) {
          if (!w.ignoreStylePresentationModeChange) {
            acc.push(w);
          }
          return acc.concat(recursiveChildWidgets(w.domNode));
        },
        []
      );
    }

    function setStylePresentationMode(sop, stylePresentationMode, /*Boolean?*/ created) {
      // create:
      //   Only relevant for "EDIT". Falsy if we are editing a fresh object, truthy if not.

      // TODO method to complex. refactor.

      var domNode = sop.get("domNode");
      if (domNode) {
        var widgetState = null;
        //noinspection FallthroughInSwitchStatementJS
        switch (stylePresentationMode) {
          case _SemanticObjectPane.prototype.NOTARGET:
            widgetState = {readOnly: true, disabled: true};
            break;
          case _SemanticObjectPane.prototype.EDIT:
          case _SemanticObjectPane.prototype.WILD:
            widgetState = {readOnly: false, disabled: false};
            break;
          case _SemanticObjectPane.prototype.BUSY:
          case _SemanticObjectPane.prototype.ERROR:
            widgetState = {readOnly: false, disabled: true};
            break;
          default: // VIEW
            widgetState = {readOnly: true, disabled: false};
        }
        var innerWidgets = recursiveChildWidgets(domNode);
        innerWidgets.forEach(function(w) {
          if (w.isInstanceOf(TextBox) ||
              w.isInstanceOf(Output) ||
              w.isInstanceOf(CheckedMultiSelect) ||
              w.isInstanceOf(CheckBox) ||
              w.isInstanceOf(Select) ||
              w.stylePresentationModeDependent) {
            w.set("readOnly", widgetState.readOnly || !!(created && w.cannotBeChangedAfterCreate));
            w.set("disabled", widgetState.disabled);
          }
          else if (w.isInstanceOf(InlineEditBox) || w.isInstanceOf(Editor)) { // only supports disabled, which === readOnly
            w.set("disabled",
              widgetState.disabled ||
              widgetState.readOnly || !!(created && w.cannotBeChangedAfterCreate));
          }
        });
        if (stylePresentationMode === _SemanticObjectPane.prototype.VIEW ||
            stylePresentationMode === _SemanticObjectPane.prototype.EDIT) {
          domClass.replace(domNode,
            "SemanticObjectPane_enabled",
            "SemanticObjectPane_busy SemanticObjectPane_wild SemanticObjectPane_disabled SemanticObjectPane_error SemanticObjectPane_notarget");
        }
        else if (stylePresentationMode === _SemanticObjectPane.prototype.BUSY) {
          domClass.replace(domNode,
            "SemanticObjectPane_busy",
            "SemanticObjectPane_enabled SemanticObjectPane_wild SemanticObjectPane_disabled SemanticObjectPane_error SemanticObjectPane_notarget");
        }
        else if (stylePresentationMode === _SemanticObjectPane.prototype.WILD) {
          domClass.replace(domNode,
            "SemanticObjectPane_wild",
            "SemanticObjectPane_enabled SemanticObjectPane_busy SemanticObjectPane_disabled SemanticObjectPane_error SemanticObjectPane_notarget");
        }
        else if (stylePresentationMode === _SemanticObjectPane.prototype.ERROR) {
          domClass.replace(domNode,
            "SemanticObjectPane_error",
            "SemanticObjectPane_enabled SemanticObjectPane_busy SemanticObjectPane_wild SemanticObjectPane_disabled SemanticObjectPane_notarget");
        }
        else { // NOTARGET
          domClass.replace(domNode,
            " SemanticObjectPane_notarget",
            "SemanticObjectPane_enabled SemanticObjectPane_busy SemanticObjectPane_wild SemanticObjectPane_error SemanticObjectPane_disabled");
        }
      }
    }

    //noinspection LocalVariableNamingConventionJS
    var _SemanticObjectPane = declare([_WidgetBase, _ContractMixin], {
      // summary:
      //   Widget that represents a SemanticObject in detail, and that gives the opportunity
      //   to the user the view the details, edit the details, and create a new object.
      //   Abstract class to be extended for particular subtypes of SemanticObject.
      // description:
      //   What is common to all subtypes is that the widget:
      //   - has a `target` that is a SemanticObject; getTargetType() returns the top-most supported
      //     Constructor of supported targets. All targets must be instances of this type.
      //   - has an `presentationMode` (view, edit, busy, wild, error)
      //   - has a `stylePresentationMode`
      //
      //   The representation should reflect the presentationMode in a clear visual way to the user.
      //   This is the `stylePresentationModel`. It is the `presentationMode` if `target !== null`,
      //   and `NOTARGET` otherwise.
      //   Even when the information shown is completely read-only, widgets should extend
      //   this class, to change the representation of the displayed information consistently
      //   with other information in different presentationModes, e.g., in "busy" mode.
      //   The available presentation modes are defined in _SemanticObjectPane.prototype.presentationModes.
      //
      //   Instances can be wrapped around zero or more _SemanticObjectPanes, recursively (no loops!).
      //   We take care of propagating `presentationMode`. Subclasses need to override
      //   getWrappedDetails to return the wrapped details. All instances need to be instances of this class.
      //   The default implementation returns an empty array.
      //   The target of a wrapped detail might be the same target as our target, but it might be
      //   another related object, of a different type. set("target", ...) will call _propagateTarget, which is
      //   chained, so that subclasses can add propagation of setting the target. Our implementation only sets our
      //   target.
      //
      //   This class is concerned with presentation. Other classes might add presentation
      //   and functionality to support interaction with the user (save and cancel buttons, etc. -
      //   see e.g. ppwcode persistence).

      _c_invar: [
        function() {return this.get("presentationMode");},
        function() {return this.presentationModes.indexOf(this.get("presentationMode")) >= 0;},
        function() {return this.getTargetType();},
        function() {return this.getTargetType().prototype.isInstanceOf(SemanticObject);},
        function() {
          return this.get("target") === null ||
                 (this.get("target").isInstanceOf && this.get("target").isInstanceOf(this.getTargetType()));
        },
        function() {return this.get("stylePresentationMode");},
        function() {return this.stylePresentationModes.indexOf(this.get("stylePresentationMode")) >= 0;},
        function() {return (this.get("stylePresentationMode") === this.NOTARGET) === (this.get("target") === null);},
        function() {
          return this.get("target") !== null
            ? this.get("stylePresentationMode") === this.get("presentationMode") // jshint ignore:line
            : true;
        },
        function() {return this._wrappedDetails() !== null;},
        function() {return lang.isArray(this._wrappedDetails());},
        {
          objectSelector: function() {
            return this._wrappedDetails();
          },
          invars: [
            function(wd) {
              return wd && wd !== null &&
                     wd.isInstanceOf && wd.isInstanceOf(_SemanticObjectPane);
            },
            // wrapped details might contain other objects of other types as target,
            // or null, but the presentationMode needs to be in sync. The stylePresentationMode
            // can differ.
            function(wd) {
              return wd.get("presentationMode") === this.get("presentationMode");
            }
          ]
        }
      ],

      "-chains-": {
        _propagateTarget: "after",
        _propagateOpener: "after",
        _localPresentationModeChange: "after"
      },

      // target: SemanticObject
      //    SemanticObject that is represented.
      //    Access in declarative template with  ... data-dojo-props="value: at('rel:', BINDING_PROPERTY_NAME)
      target: null,

      // presentationMode: String
      //    The presentation mode is either view, edit, busy, wild, or error
      presentationMode: stylePresentationModes[0], // default value

      // opener: Function
      //   Function that attempts to open a new "window" or "pane" for another PersistentObject
      //   (which is mostly linked to the current one)
      opener: null,

      postCreate: function() {
        this.inherited(arguments);
        domClass.add(this.get("domNode"), "SemanticObjectPane");
      },

      // stylePresentationMode: String
      //    The stylePresentationMode is the same as the presentationMode, except when there is no target.
      //    Then it is NOTARGET.
      _getStylePresentationModeAttr: function() {
        return this.target ? this.get("presentationMode") : this.NOTARGET;
      },

      isInEditMode: function() {
        // summary:
        //    This is in a `stylePresentationMode` that allows the user to change the values, if there is a target and
        //    it is editable.
        return this.target &&
               (this.presentationMode === this.EDIT ||
                this.presentationMode === this.BUSY ||
                this.presentationMode === this.WILD);
      },

      _wrappedDetails: function() {
        // summary:
        //   Array containing the wrapped details, a subclass wants the presentationMode propagated to.
        // tags:
        //   protected

        return []; // return Array
      },

      getTargetType: function() {
        // summary:
        //    The supported type of SemanticObjects. All targets must be an instance of this type.
        // description:
        //    Subclasses should overwrite to return the correct type.

        return SemanticObject;
      },

      _propagateTarget: function(/*SemanticObject*/ so) {
        // summary:
        //   Propagate the target as appropriate to wrapped details.
        //   Chained. Subtypes could add propagation to wrapped details.
        // tags:
        //   protected
        // description:
        //   Does nothing in _SemanticObjectPane.

        this._c_NOP(so);
      },

      _setTargetAttr: function(so) {
        // summary:
        //    Sets the target of this instance. Chained. Subtypes could add propagation to wrapped details.
        this._c_pre(function() {return so === null || (so.isInstanceOf && so.isInstanceOf(this.getTargetType()));});

        if (so !== this.get("target")) {
          this._set("target", so);
        }
        this._propagateTarget(so);
        this.set("presentationMode", so && so.persistenceId === null ? this.EDIT : this.VIEW);
      },

      _propagateOpener: function(/*Function*/ opener) {
        // summary:
        //   Propagate the opener function as appropriate to wrapped details.
        //   Chained. Subtypes could add propagation to wrapped details.
        // tags:
        //   protected
        // description:
        //   Does nothing in _SemanticObjectPane.

        this._c_NOP(opener);
      },

      _setOpenerAttr: function(opener) {
        if (opener !== this.get("opener")) {
          this._set("opener", opener);
        }
        this._propagateOpener(opener);
      },

      _setPresentationModeAttr: function(value) {
        // summary:
        //    Set the presentationMode, and propagate to the wrapped details.
        //    Also makes all innerWidgets read-only in presentationMode VIEW,
        //    disabled in presentationMode BUSY, and not-read-only and enabled
        //    in the other presentationModes.

        // Called during create by _WidgetBase with default value automatically
        this._c_pre(function() {return value !== null;});
        this._c_pre(function() {return _SemanticObjectPane.prototype.presentationModes.indexOf(value) >= 0;});

        this._set("presentationMode", value);
        this._wrappedDetails().forEach(function(wd) {
          wd.set("presentationMode", value);
        });
        var stylePresentationMode = this.get("stylePresentationMode");
        var target = this.get("target");
        setStylePresentationMode(this, stylePresentationMode, target && target.get("persistenceId"));
        if (!this._destroyed) {
          // if we are destroyed, there are no more domNodes
          this._localPresentationModeChange(value);
        }
      },

      _localPresentationModeChange: function(/*String*/ presentationMode) {
        // summary:
        //   Make changes to representation to represent the
        //   new edit mode. Chained. Overwrite when needed.
        // tags:
        //   protected
        // description:
        //   Does nothing in _SemanticObjectPane

        this._c_NOP(presentationMode);
      }

    });

    // All supported presentationModes
    _SemanticObjectPane.prototype.presentationModes = presentationModes;
    // All supported stylePresentationModes
    _SemanticObjectPane.prototype.stylePresentationModes = stylePresentationModes;
    stylePresentationModes.forEach(function(em) {
      _SemanticObjectPane.prototype[em] = em;
    });

    return _SemanticObjectPane; // return _SemanticObjectPane

  }
);
<|endoftext|>


<commit_before>/**
 * Created by theophy on 02/08/2017.
 *
 * this is used to generate our tags from our sails
 */

var _ = require("lodash");
var parsers = require("./parsers");

/**
 * this is used to parse models to tags just the globalId is picked to gather our
 * tags
 * @param models
 * @returns {Array}
 * @private
 */
function _generateModels(models) {
    var tags = [];

    _.forEach(models, function (model) {

        // Do tagging for  all models. Ignoring associative tables
        if (model.globalId) {
            tags.push({name: model.globalId});
        }
    });

    return tags;
}

/**
 * this generates our definitions from our models and returns the equivalent swagger specification
 * @param models
 * @returns {{}}
 * @private
 */
function _generateDefintions(models) {
    var defintions = {};

    _.forEach(models, function (model) {
        // Do tagging for  all models. Ignoring associative tables
        if (model.globalId) {
            defintions[model.identity] = parsers.attributes(model.attributes);
        }
    });

    return defintions;
}

/**
 * this is used to generate our default parameters and extending the ones created in our
 * sails.config[configKey].parameters to the default
 * @param config
 * @param context
 * @private
 */
function _generateParameters(config, context) {
    var params = {};

    //default parameters-> where, limit, skip, sort, populate, select, page
    params.WhereQueryParam = {
        in: 'query',
        name: 'where',
        required: false,
        type: 'string',
        description: 'This follows the standard from http://sailsjs.com/documentation/reference/blueprint-api/find-where'
    };
    params.LimitQueryParam = {
        in: 'query',
        name: 'limit',
        required: false,
        type: 'integer',
        description: 'The maximum number of records to send back (useful for pagination). Defaults to ' + config.blueprints.defaultLimit
    };
    params.SkipQueryParam = {
        in: 'query',
        name: 'skip',
        required: false,
        type: 'integer',
        description: 'The number of records to skip (useful for pagination).'
    };
    params.SortQueryParam = {
        in: 'query',
        name: 'sort',
        required: false,
        type: 'string',
        description: 'The sort order. By default, returned records are sorted by primary key value in ascending order. e.g. ?sort=lastName%20ASC'
    };

    params.PopulateQueryParam = {
        in: 'query',
        name: 'sort',
        required: false,
        type: 'string',
        description: 'check for better understanding -> http://sailsjs.com/documentation/reference/blueprint-api/find-where'
    };

    params.PageQueryParam = {
        in: 'query',
        name: 'page',
        required: false,
        type: 'integer',
        description: 'This helps with pagination and when the limit is known'
    };
    params.SelectQueryParam = {
        in: 'query',
        name: 'select',
        required: false,
        type: 'string',
        description: 'This helps with what to return for the user and its "," delimited'
    };

    //now we extend our config.swaggerDoc.parameters
    return _.merge(params, config[context.configKey].parameters);
}

module.exports = {
    tags: _generateModels,
    definitions: _generateDefintions,
    parameters: _generateParameters
};

<commit_msg>updated parameters to include token param header<commit_after>/**
 * Created by theophy on 02/08/2017.
 *
 * this is used to generate our tags from our sails
 */

var _ = require("lodash");
var parsers = require("./parsers");

/**
 * this is used to parse models to tags just the globalId is picked to gather our
 * tags
 * @param models
 * @returns {Array}
 * @private
 */
function _generateModels(models) {
    var tags = [];

    _.forEach(models, function (model) {

        // Do tagging for  all models. Ignoring associative tables
        if (model.globalId) {
            tags.push({name: model.globalId});
        }
    });

    return tags;
}

/**
 * this generates our definitions from our models and returns the equivalent swagger specification
 * @param models
 * @returns {{}}
 * @private
 */
function _generateDefintions(models) {
    var defintions = {};

    _.forEach(models, function (model) {
        // Do tagging for  all models. Ignoring associative tables
        if (model.globalId) {
            defintions[model.identity] = parsers.attributes(model.attributes);
        }
    });

    return defintions;
}

/**
 * this is used to generate our default parameters and extending the ones created in our
 * sails.config[configKey].parameters to the default
 * @param config
 * @param context
 * @private
 */
function _generateParameters(config, context) {
    var params = {};

    //default parameters-> where, limit, skip, sort, populate, select, page
    params.WhereQueryParam = {
        in: 'query',
        name: 'where',
        required: false,
        type: 'string',
        description: 'This follows the standard from http://sailsjs.com/documentation/reference/blueprint-api/find-where'
    };
    params.LimitQueryParam = {
        in: 'query',
        name: 'limit',
        required: false,
        type: 'integer',
        description: 'The maximum number of records to send back (useful for pagination). Defaults to ' + config.blueprints.defaultLimit
    };
    params.SkipQueryParam = {
        in: 'query',
        name: 'skip',
        required: false,
        type: 'integer',
        description: 'The number of records to skip (useful for pagination).'
    };
    params.SortQueryParam = {
        in: 'query',
        name: 'sort',
        required: false,
        type: 'string',
        description: 'The sort order. By default, returned records are sorted by primary key value in ascending order. e.g. ?sort=lastName%20ASC'
    };

    params.PopulateQueryParam = {
        in: 'query',
        name: 'sort',
        required: false,
        type: 'string',
        description: 'check for better understanding -> http://sailsjs.com/documentation/reference/blueprint-api/find-where'
    };

    params.PageQueryParam = {
        in: 'query',
        name: 'page',
        required: false,
        type: 'integer',
        description: 'This helps with pagination and when the limit is known'
    };
    params.SelectQueryParam = {
        in: 'query',
        name: 'select',
        required: false,
        type: 'string',
        description: 'This helps with what to return for the user and its "," delimited'
    };

    params.TokenParam = {
        in: 'header',
        name: 'token',
        required: false,
        type: 'string',
        description: 'Incase we want to send header inforamtion along our request'
    };

    //now we extend our config.swaggerDoc.parameters
    return _.merge(params, config[context.configKey].parameters);
}

module.exports = {
    tags: _generateModels,
    definitions: _generateDefintions,
    parameters: _generateParameters
};

<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var findRoot = require('find-root');

var root = findRoot(process.cwd());

function getPackage() {
  try {
    return JSON.parse(fs.readFileSync(path.resolve(root, 'package.json')));
  } catch (e) {
    throw new Error('Could not find package.json');
  }
}

module.exports = function validatePackage() {
  var pkg = getPackage();

  if (!pkg.name) {
    throw new Error('package.json must specify a `name`');
  }

  if (!pkg.version) {
    throw new Error('package.json must specify a `version`');
  }

  return pkg;
};

<commit_msg>Update getpackage<commit_after>var fs = require('fs');
var path = require('path');
var findRoot = require('find-root');
var debug = require('debug')('getPackage');

var root = findRoot(process.cwd());

function getPackage() {
  var packagePath = path.resolve(root, 'package.json');
  debug('Attempting to read ' + packagePath);
  try {
    return JSON.parse(fs.readFileSync(packagePath, { encoding: 'utf-8' }));
  } catch (e) {
    throw new Error('Could not find package.json');
  }
}

module.exports = function validatePackage() {
  var pkg = getPackage();

  if (!pkg.name) {
    throw new Error('package.json must specify a `name`');
  }

  if (!pkg.version) {
    throw new Error('package.json must specify a `version`');
  }

  return pkg;
};

<|endoftext|>


<commit_before>/**
 * @module opcua.miscellaneous
 */
var assert = require('better-assert');
var util = require("util");

/**
 * a BinaryStream can be use to perform sequential read or write
 * inside a buffer.
 * The BinaryStream maintains a cursor up to date as the caller
 * operates on the stream using the various read/write methods.
 * It uses the [Little Endian](http://en.wikipedia.org/wiki/Little_endian#Little-endian)
 * convention.
 *
 * data can either be:
 *
 * * a Buffer , in this case the BinaryStream operates on this Buffer
 * * null     , in this case a BinaryStream with 1024 bytes is created
 * * any data , in this case the object is converted into a binary buffer.
 *
 * example:
 *
 *    ``` javascript
 *    var stream = new BinaryStream(new Buffer(32))
 *    ```
 *
 * @class BinaryStream
 * @param {null|Buffer|*} data
 * @constructor
 *
 *
 *
 */
function BinaryStream(data) {
    if (data === undefined) {
        this._buffer = new Buffer(1024);
    } else {
        if (data instanceof Buffer) {
            this._buffer = data;
        } else {
            this._buffer = new Buffer(data, "binary");
        }
    }
    this.length = 0;
}

/**
 * set the cursor to the begining of the stream
 * @method BinaryStream.rewind
 * @return null
 */
BinaryStream.prototype.rewind = function () {
    this.length = 0;
};

/**
 * write a single signed byte (8 bits) to the stream.
 * value must be in the range of [-127,128]
 * @method writeInt8
 * @param {integer} value
 */
BinaryStream.prototype.writeInt8 = function (value) {
    assert(value >= -128 && value < 128);
    this._buffer.writeInt8(value, this.length);
    this.length += 1;
};

/**
 * write a single unsigned byte (8 bits) to the stream.
 * @method writeUInt8
 * @param {integer} value
 */
BinaryStream.prototype.writeUInt8 = function (value) {
    assert(value >= 0 && value < 256 && " writeUInt8 : out of bound ");
    this._buffer.writeUInt8(value, this.length);
    this.length += 1;
};

/**
 * write a single 16 bit signed integer to the stream.
 * @method writeInt16
 * @param {integer} value
 */
BinaryStream.prototype.writeInt16 = function (value) {
    this._buffer.writeInt16LE(value, this.length);
    this.length += 2;
};

/**
 * write a single 16 bit unsigned integer to the stream.
 * @method writeUInt16
 * @param value
 */
BinaryStream.prototype.writeUInt16 = function (value) {
    this._buffer.writeUInt16LE(value, this.length);
    this.length += 2;
};

/**
 * write a single 32 bit signed integer to the stream.
 * @method writeInteger
 * @param value
 */
BinaryStream.prototype.writeInteger = function (value) {
    this._buffer.writeInt32LE(value, this.length);
    this.length += 4;
};

/**
 * write a single 32 bit unsigned integer to the stream.
 * @method writeUInt32
 * @param value
 */
BinaryStream.prototype.writeUInt32 = function (value) {
    this._buffer.writeUInt32LE(value, this.length);
    this.length += 4;
};

/**
 * write a single 32 bit floating number to the stream.
 * @method writeFloat
 * @param value
 */
BinaryStream.prototype.writeFloat = function (value) {
    this._buffer.writeFloatLE(value, this.length);
    this.length += 4;
};

/**
 * write a single 64 bit floating number to the stream.
 * @method writeDouble
 * @param value
 */
BinaryStream.prototype.writeDouble = function (value) {
    this._buffer.writeDoubleLE(value, this.length);
    this.length += 8;
};

/**
 * read a single signed byte  (8 bits) from the stream.
 * @method readByte
 * @return {Number}
 */
BinaryStream.prototype.readByte = function () {
    var retVal = this._buffer.readInt8(this.length);
    this.length += 1;
    return retVal;
};
BinaryStream.prototype.readInt8 = BinaryStream.prototype.readByte;
/**
 * read a single unsigned byte (8 bits) from the stream.
 * @method readUInt8
 * @return {Number}
 */
BinaryStream.prototype.readUInt8 = function () {
    var retVal = this._buffer.readUInt8(this.length);
    this.length += 1;
    return retVal;
};

/**
 * read a single signed 16-bit integer from the stream.
 * @method readInt16
 * @return {Number}
 */
BinaryStream.prototype.readInt16 = function () {
    var retVal = this._buffer.readInt16LE(this.length);
    this.length += 2;
    return retVal;
};

/**
 * read a single unsigned 16-bit integer from the stream.
 * @method readUInt16
 * @return {Number}  q
 */
BinaryStream.prototype.readUInt16 = function () {
    var retVal = this._buffer.readUInt16LE(this.length);
    this.length += 2;
    return retVal;
};

/**
 * read a single signed 32-bit integer from the stream.
 * @method readInteger
 * @return {Number}
 */
BinaryStream.prototype.readInteger = function () {
    var retVal = this._buffer.readInt32LE(this.length);
    this.length += 4;
    return retVal;
};

/**
 * read a single unsigned 32-bit integer from the stream.
 * @method readUInt32
 * @return {Number} the value read from the stream
 */
BinaryStream.prototype.readUInt32 = function () {
    var retVal = this._buffer.readUInt32LE(this.length);
    this.length += 4;
    return retVal;
};

/**
 * read a single  32-bit floating point number from the stream.
 * @method readFloat
 * @return {Number} the value read from the stream
 */
BinaryStream.prototype.readFloat = function () {
    var retVal = this._buffer.readFloatLE(this.length);
    this.length += 4;
    return retVal;
};

/**
 * read a single 64-bit floating point number from the stream.
 * @method readDouble
 * @return {Number} the value read from the stream
 */
BinaryStream.prototype.readDouble = function () {
    var retVal = this._buffer.readDoubleLE(this.length);
    this.length += 8;
    return retVal;
};

/**
 * write a set of byte to the stream
 *
 * @method writeRaw
 * @param {buffer} buf the buffer to write
 * @param length   the number of byte to write
 */
BinaryStream.prototype.writeRaw = function (buf, length) {

    this._buffer.write(buf, this.length, length);
    this.length += length;
};

/**
 * write a byte stream to the stream.
 * The method writes the length of the byte array into the stream as a 32 bits integer before the byte stream.
 *
 * @method writeByteStream
 * @param {Buffer} buf the    buffer to write.
 *   the buffer buf.length the buffer to write
 */
BinaryStream.prototype.writeByteStream = function (buf) {

    if (!buf) {
        this.writeUInt32(0xFFFFFFFF);
        return;
    }
    this.writeUInt32(buf.length);
    buf.copy(this._buffer, this.length, 0, buf.length);
    this.length += buf.length;
};

/**
 * read a byte stream to the stream.
 * The method reads the length of the byte array from the stream as a 32 bits integer before reading the byte stream.
 *
 * @method readByteStream
 * @return {Buffer}
 */
BinaryStream.prototype.readByteStream = function () {
    var bufLen = this.readUInt32();
    if (bufLen === 0xFFFFFFFF) {
        return null;
    }
    if (bufLen === 0) {
        return new Buffer(0);
    }
    var buf = new Buffer(bufLen);
    this._buffer.copy(buf, 0, this.length, this.length + bufLen);
    this.length += bufLen;
    return buf;
};

exports.BinaryStream = BinaryStream;

/**
 * a BinaryStreamSizeCalculator can be used to quickly evaluate the required size
 * of a buffer by performing the same sequence of write operation.
 *
 * a BinaryStreamSizeCalculator has the same writeXXX methods as the BinaryStream stream
 * object.
 *
 * @class BinaryStreamSizeCalculator
 * @extends BinaryStream
 * @constructor
 *
 */
function BinaryStreamSizeCalculator() {
    this.length = 0;
}

BinaryStreamSizeCalculator.prototype.rewind = function () {
    this.length = 0;
};

BinaryStreamSizeCalculator.prototype.writeInt8 = function (value) {
    this.length += 1;
};

BinaryStreamSizeCalculator.prototype.writeUInt8 = function (value) {
    this.length += 1;
};

BinaryStreamSizeCalculator.prototype.writeInt16 = function (value) {
    this.length += 2;
};

BinaryStreamSizeCalculator.prototype.writeInteger = function (value) {
    this.length += 4;
};

BinaryStreamSizeCalculator.prototype.writeUInt32 = function (value) {
    this.length += 4;
};

BinaryStreamSizeCalculator.prototype.writeUInt16 = function (value) {
    this.length += 2;
};

BinaryStreamSizeCalculator.prototype.writeFloat = function (value) {
    this.length += 4;
};

BinaryStreamSizeCalculator.prototype.writeDouble = function (value) {
    this.length += 8;
};

BinaryStreamSizeCalculator.prototype.writeByteStream = function (buf) {
    if (!buf) {
        this.writeUInt32(0);
    } else {
        this.writeUInt32(buf.length);
        this.length += buf.length;

    }
};
BinaryStreamSizeCalculator.prototype.writeRaw = function (buf, length) {
    this.length += length;
};

exports.BinaryStreamSizeCalculator = BinaryStreamSizeCalculator;
<commit_msg>- detect invalid buffer length<commit_after>/**
 * @module opcua.miscellaneous
 */
var assert = require('better-assert');
var util = require("util");

/**
 * a BinaryStream can be use to perform sequential read or write
 * inside a buffer.
 * The BinaryStream maintains a cursor up to date as the caller
 * operates on the stream using the various read/write methods.
 * It uses the [Little Endian](http://en.wikipedia.org/wiki/Little_endian#Little-endian)
 * convention.
 *
 * data can either be:
 *
 * * a Buffer , in this case the BinaryStream operates on this Buffer
 * * null     , in this case a BinaryStream with 1024 bytes is created
 * * any data , in this case the object is converted into a binary buffer.
 *
 * example:
 *
 *    ``` javascript
 *    var stream = new BinaryStream(new Buffer(32))
 *    ```
 *
 * @class BinaryStream
 * @param {null|Buffer|*} data
 * @constructor
 *
 *
 *
 */
function BinaryStream(data) {
    if (data === undefined) {
        this._buffer = new Buffer(1024);
    } else {
        if (data instanceof Buffer) {
            this._buffer = data;
        } else {
            this._buffer = new Buffer(data, "binary");
        }
    }
    this.length = 0;
}

/**
 * set the cursor to the begining of the stream
 * @method BinaryStream.rewind
 * @return null
 */
BinaryStream.prototype.rewind = function () {
    this.length = 0;
};

/**
 * write a single signed byte (8 bits) to the stream.
 * value must be in the range of [-127,128]
 * @method writeInt8
 * @param {integer} value
 */
BinaryStream.prototype.writeInt8 = function (value) {
    assert(value >= -128 && value < 128);
    this._buffer.writeInt8(value, this.length);
    this.length += 1;
};

/**
 * write a single unsigned byte (8 bits) to the stream.
 * @method writeUInt8
 * @param {integer} value
 */
BinaryStream.prototype.writeUInt8 = function (value) {
    assert(value >= 0 && value < 256 && " writeUInt8 : out of bound ");
    this._buffer.writeUInt8(value, this.length);
    this.length += 1;
};

/**
 * write a single 16 bit signed integer to the stream.
 * @method writeInt16
 * @param {integer} value
 */
BinaryStream.prototype.writeInt16 = function (value) {
    this._buffer.writeInt16LE(value, this.length);
    this.length += 2;
};

/**
 * write a single 16 bit unsigned integer to the stream.
 * @method writeUInt16
 * @param value
 */
BinaryStream.prototype.writeUInt16 = function (value) {
    this._buffer.writeUInt16LE(value, this.length);
    this.length += 2;
};

/**
 * write a single 32 bit signed integer to the stream.
 * @method writeInteger
 * @param value
 */
BinaryStream.prototype.writeInteger = function (value) {
    this._buffer.writeInt32LE(value, this.length);
    this.length += 4;
};

/**
 * write a single 32 bit unsigned integer to the stream.
 * @method writeUInt32
 * @param value
 */
BinaryStream.prototype.writeUInt32 = function (value) {
    this._buffer.writeUInt32LE(value, this.length);
    this.length += 4;
};

/**
 * write a single 32 bit floating number to the stream.
 * @method writeFloat
 * @param value
 */
BinaryStream.prototype.writeFloat = function (value) {
    this._buffer.writeFloatLE(value, this.length);
    this.length += 4;
};

/**
 * write a single 64 bit floating number to the stream.
 * @method writeDouble
 * @param value
 */
BinaryStream.prototype.writeDouble = function (value) {
    this._buffer.writeDoubleLE(value, this.length);
    this.length += 8;
};

/**
 * read a single signed byte  (8 bits) from the stream.
 * @method readByte
 * @return {Number}
 */
BinaryStream.prototype.readByte = function () {
    var retVal = this._buffer.readInt8(this.length);
    this.length += 1;
    return retVal;
};
BinaryStream.prototype.readInt8 = BinaryStream.prototype.readByte;
/**
 * read a single unsigned byte (8 bits) from the stream.
 * @method readUInt8
 * @return {Number}
 */
BinaryStream.prototype.readUInt8 = function () {
    var retVal = this._buffer.readUInt8(this.length);
    this.length += 1;
    return retVal;
};

/**
 * read a single signed 16-bit integer from the stream.
 * @method readInt16
 * @return {Number}
 */
BinaryStream.prototype.readInt16 = function () {
    var retVal = this._buffer.readInt16LE(this.length);
    this.length += 2;
    return retVal;
};

/**
 * read a single unsigned 16-bit integer from the stream.
 * @method readUInt16
 * @return {Number}  q
 */
BinaryStream.prototype.readUInt16 = function () {
    var retVal = this._buffer.readUInt16LE(this.length);
    this.length += 2;
    return retVal;
};

/**
 * read a single signed 32-bit integer from the stream.
 * @method readInteger
 * @return {Number}
 */
BinaryStream.prototype.readInteger = function () {
    var retVal = this._buffer.readInt32LE(this.length);
    this.length += 4;
    return retVal;
};

/**
 * read a single unsigned 32-bit integer from the stream.
 * @method readUInt32
 * @return {Number} the value read from the stream
 */
BinaryStream.prototype.readUInt32 = function () {
    var retVal = this._buffer.readUInt32LE(this.length);
    this.length += 4;
    return retVal;
};

/**
 * read a single  32-bit floating point number from the stream.
 * @method readFloat
 * @return {Number} the value read from the stream
 */
BinaryStream.prototype.readFloat = function () {
    var retVal = this._buffer.readFloatLE(this.length);
    this.length += 4;
    return retVal;
};

/**
 * read a single 64-bit floating point number from the stream.
 * @method readDouble
 * @return {Number} the value read from the stream
 */
BinaryStream.prototype.readDouble = function () {
    var retVal = this._buffer.readDoubleLE(this.length);
    this.length += 8;
    return retVal;
};

/**
 * write a set of byte to the stream
 *
 * @method writeRaw
 * @param {buffer} buf the buffer to write
 * @param length   the number of byte to write
 */
BinaryStream.prototype.writeRaw = function (buf, length) {

    this._buffer.write(buf, this.length, length);
    this.length += length;
};

/**
 * write a byte stream to the stream.
 * The method writes the length of the byte array into the stream as a 32 bits integer before the byte stream.
 *
 * @method writeByteStream
 * @param {Buffer} buf the    buffer to write.
 *   the buffer buf.length the buffer to write
 */
BinaryStream.prototype.writeByteStream = function (buf) {

    if (!buf) {
        this.writeUInt32(0xFFFFFFFF);
        return;
    }
    this.writeUInt32(buf.length);
    buf.copy(this._buffer, this.length, 0, buf.length);
    this.length += buf.length;
};

/**
 * read a byte stream to the stream.
 * The method reads the length of the byte array from the stream as a 32 bits integer before reading the byte stream.
 *
 * @method readByteStream
 * @return {Buffer}
 */
BinaryStream.prototype.readByteStream = function () {
    var bufLen = this.readUInt32();
    if (bufLen === 0xFFFFFFFF) {
        return null;
    }
    if (bufLen === 0) {
        return new Buffer(0);
    }

    // check that there is enough space in the buffer
    var remaining_bytes= this._buffer.length - this.length;
    if (remaining_bytes<bufLen) {
        throw new Error("BinaryStream.readByteStream error : not enough bytes left in buffer :  bufferLength is " + bufLen + " but only " + remaining_bytes + " left");
    }

    var buf = new Buffer(bufLen);
    this._buffer.copy(buf, 0, this.length, this.length + bufLen);
    this.length += bufLen;
    return buf;
};

exports.BinaryStream = BinaryStream;

/**
 * a BinaryStreamSizeCalculator can be used to quickly evaluate the required size
 * of a buffer by performing the same sequence of write operation.
 *
 * a BinaryStreamSizeCalculator has the same writeXXX methods as the BinaryStream stream
 * object.
 *
 * @class BinaryStreamSizeCalculator
 * @extends BinaryStream
 * @constructor
 *
 */
function BinaryStreamSizeCalculator() {
    this.length = 0;
}

BinaryStreamSizeCalculator.prototype.rewind = function () {
    this.length = 0;
};

BinaryStreamSizeCalculator.prototype.writeInt8 = function (value) {
    this.length += 1;
};

BinaryStreamSizeCalculator.prototype.writeUInt8 = function (value) {
    this.length += 1;
};

BinaryStreamSizeCalculator.prototype.writeInt16 = function (value) {
    this.length += 2;
};

BinaryStreamSizeCalculator.prototype.writeInteger = function (value) {
    this.length += 4;
};

BinaryStreamSizeCalculator.prototype.writeUInt32 = function (value) {
    this.length += 4;
};

BinaryStreamSizeCalculator.prototype.writeUInt16 = function (value) {
    this.length += 2;
};

BinaryStreamSizeCalculator.prototype.writeFloat = function (value) {
    this.length += 4;
};

BinaryStreamSizeCalculator.prototype.writeDouble = function (value) {
    this.length += 8;
};

BinaryStreamSizeCalculator.prototype.writeByteStream = function (buf) {
    if (!buf) {
        this.writeUInt32(0);
    } else {
        this.writeUInt32(buf.length);
        this.length += buf.length;

    }
};
BinaryStreamSizeCalculator.prototype.writeRaw = function (buf, length) {
    this.length += length;
};

exports.BinaryStreamSizeCalculator = BinaryStreamSizeCalculator;
<|endoftext|>