You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					206 lines
				
				7.9 KiB
			
		
		
			
		
	
	
					206 lines
				
				7.9 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const fs = require('fs');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = exports;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const versionArray = process.version
							 | 
						||
| 
								 | 
							
								  .substr(1)
							 | 
						||
| 
								 | 
							
								  .replace(/-.*$/, '')
							 | 
						||
| 
								 | 
							
								  .split('.')
							 | 
						||
| 
								 | 
							
								  .map((item) => {
							 | 
						||
| 
								 | 
							
								    return +item;
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const napi_multiple_commands = [
							 | 
						||
| 
								 | 
							
								  'build',
							 | 
						||
| 
								 | 
							
								  'clean',
							 | 
						||
| 
								 | 
							
								  'configure',
							 | 
						||
| 
								 | 
							
								  'package',
							 | 
						||
| 
								 | 
							
								  'publish',
							 | 
						||
| 
								 | 
							
								  'reveal',
							 | 
						||
| 
								 | 
							
								  'testbinary',
							 | 
						||
| 
								 | 
							
								  'testpackage',
							 | 
						||
| 
								 | 
							
								  'unpublish'
							 | 
						||
| 
								 | 
							
								];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const napi_build_version_tag = 'napi_build_version=';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.get_napi_version = function() {
							 | 
						||
| 
								 | 
							
								  // returns the non-zero numeric napi version or undefined if napi is not supported.
							 | 
						||
| 
								 | 
							
								  // correctly supporting target requires an updated cross-walk
							 | 
						||
| 
								 | 
							
								  let version = process.versions.napi; // can be undefined
							 | 
						||
| 
								 | 
							
								  if (!version) { // this code should never need to be updated
							 | 
						||
| 
								 | 
							
								    if (versionArray[0] === 9 && versionArray[1] >= 3) version = 2; // 9.3.0+
							 | 
						||
| 
								 | 
							
								    else if (versionArray[0] === 8) version = 1; // 8.0.0+
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return version;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.get_napi_version_as_string = function(target) {
							 | 
						||
| 
								 | 
							
								  // returns the napi version as a string or an empty string if napi is not supported.
							 | 
						||
| 
								 | 
							
								  const version = module.exports.get_napi_version(target);
							 | 
						||
| 
								 | 
							
								  return version ? '' + version : '';
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.validate_package_json = function(package_json, opts) { // throws Error
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const binary = package_json.binary;
							 | 
						||
| 
								 | 
							
								  const module_path_ok = pathOK(binary.module_path);
							 | 
						||
| 
								 | 
							
								  const remote_path_ok = pathOK(binary.remote_path);
							 | 
						||
| 
								 | 
							
								  const package_name_ok = pathOK(binary.package_name);
							 | 
						||
| 
								 | 
							
								  const napi_build_versions = module.exports.get_napi_build_versions(package_json, opts, true);
							 | 
						||
| 
								 | 
							
								  const napi_build_versions_raw = module.exports.get_napi_build_versions_raw(package_json);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (napi_build_versions) {
							 | 
						||
| 
								 | 
							
								    napi_build_versions.forEach((napi_build_version)=> {
							 | 
						||
| 
								 | 
							
								      if (!(parseInt(napi_build_version, 10) === napi_build_version && napi_build_version > 0)) {
							 | 
						||
| 
								 | 
							
								        throw new Error('All values specified in napi_versions must be positive integers.');
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (napi_build_versions && (!module_path_ok || (!remote_path_ok && !package_name_ok))) {
							 | 
						||
| 
								 | 
							
								    throw new Error('When napi_versions is specified; module_path and either remote_path or ' +
							 | 
						||
| 
								 | 
							
											"package_name must contain the substitution string '{napi_build_version}`.");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ((module_path_ok || remote_path_ok || package_name_ok) && !napi_build_versions_raw) {
							 | 
						||
| 
								 | 
							
								    throw new Error("When the substitution string '{napi_build_version}` is specified in " +
							 | 
						||
| 
								 | 
							
											'module_path, remote_path, or package_name; napi_versions must also be specified.');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (napi_build_versions && !module.exports.get_best_napi_build_version(package_json, opts) &&
							 | 
						||
| 
								 | 
							
									module.exports.build_napi_only(package_json)) {
							 | 
						||
| 
								 | 
							
								    throw new Error(
							 | 
						||
| 
								 | 
							
								      'The Node-API version of this Node instance is ' + module.exports.get_napi_version(opts ? opts.target : undefined) + '. ' +
							 | 
						||
| 
								 | 
							
											'This module supports Node-API version(s) ' + module.exports.get_napi_build_versions_raw(package_json) + '. ' +
							 | 
						||
| 
								 | 
							
											'This Node instance cannot run this module.');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (napi_build_versions_raw && !napi_build_versions && module.exports.build_napi_only(package_json)) {
							 | 
						||
| 
								 | 
							
								    throw new Error(
							 | 
						||
| 
								 | 
							
								      'The Node-API version of this Node instance is ' + module.exports.get_napi_version(opts ? opts.target : undefined) + '. ' +
							 | 
						||
| 
								 | 
							
											'This module supports Node-API version(s) ' + module.exports.get_napi_build_versions_raw(package_json) + '. ' +
							 | 
						||
| 
								 | 
							
											'This Node instance cannot run this module.');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function pathOK(path) {
							 | 
						||
| 
								 | 
							
								  return path && (path.indexOf('{napi_build_version}') !== -1 || path.indexOf('{node_napi_label}') !== -1);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.expand_commands = function(package_json, opts, commands) {
							 | 
						||
| 
								 | 
							
								  const expanded_commands = [];
							 | 
						||
| 
								 | 
							
								  const napi_build_versions = module.exports.get_napi_build_versions(package_json, opts);
							 | 
						||
| 
								 | 
							
								  commands.forEach((command)=> {
							 | 
						||
| 
								 | 
							
								    if (napi_build_versions && command.name === 'install') {
							 | 
						||
| 
								 | 
							
								      const napi_build_version = module.exports.get_best_napi_build_version(package_json, opts);
							 | 
						||
| 
								 | 
							
								      const args = napi_build_version ? [napi_build_version_tag + napi_build_version] : [];
							 | 
						||
| 
								 | 
							
								      expanded_commands.push({ name: command.name, args: args });
							 | 
						||
| 
								 | 
							
								    } else if (napi_build_versions && napi_multiple_commands.indexOf(command.name) !== -1) {
							 | 
						||
| 
								 | 
							
								      napi_build_versions.forEach((napi_build_version)=> {
							 | 
						||
| 
								 | 
							
								        const args = command.args.slice();
							 | 
						||
| 
								 | 
							
								        args.push(napi_build_version_tag + napi_build_version);
							 | 
						||
| 
								 | 
							
								        expanded_commands.push({ name: command.name, args: args });
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      expanded_commands.push(command);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  return expanded_commands;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.get_napi_build_versions = function(package_json, opts, warnings) { // opts may be undefined
							 | 
						||
| 
								 | 
							
								  const log = require('npmlog');
							 | 
						||
| 
								 | 
							
								  let napi_build_versions = [];
							 | 
						||
| 
								 | 
							
								  const supported_napi_version = module.exports.get_napi_version(opts ? opts.target : undefined);
							 | 
						||
| 
								 | 
							
								  // remove duplicates, verify each napi version can actaully be built
							 | 
						||
| 
								 | 
							
								  if (package_json.binary && package_json.binary.napi_versions) {
							 | 
						||
| 
								 | 
							
								    package_json.binary.napi_versions.forEach((napi_version) => {
							 | 
						||
| 
								 | 
							
								      const duplicated = napi_build_versions.indexOf(napi_version) !== -1;
							 | 
						||
| 
								 | 
							
								      if (!duplicated && supported_napi_version && napi_version <= supported_napi_version) {
							 | 
						||
| 
								 | 
							
								        napi_build_versions.push(napi_version);
							 | 
						||
| 
								 | 
							
								      } else if (warnings && !duplicated && supported_napi_version) {
							 | 
						||
| 
								 | 
							
								        log.info('This Node instance does not support builds for Node-API version', napi_version);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (opts && opts['build-latest-napi-version-only']) {
							 | 
						||
| 
								 | 
							
								    let latest_version = 0;
							 | 
						||
| 
								 | 
							
								    napi_build_versions.forEach((napi_version) => {
							 | 
						||
| 
								 | 
							
								      if (napi_version > latest_version) latest_version = napi_version;
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								    napi_build_versions = latest_version ? [latest_version] : [];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return napi_build_versions.length ? napi_build_versions : undefined;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.get_napi_build_versions_raw = function(package_json) {
							 | 
						||
| 
								 | 
							
								  const napi_build_versions = [];
							 | 
						||
| 
								 | 
							
								  // remove duplicates
							 | 
						||
| 
								 | 
							
								  if (package_json.binary && package_json.binary.napi_versions) {
							 | 
						||
| 
								 | 
							
								    package_json.binary.napi_versions.forEach((napi_version) => {
							 | 
						||
| 
								 | 
							
								      if (napi_build_versions.indexOf(napi_version) === -1) {
							 | 
						||
| 
								 | 
							
								        napi_build_versions.push(napi_version);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return napi_build_versions.length ? napi_build_versions : undefined;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.get_command_arg = function(napi_build_version) {
							 | 
						||
| 
								 | 
							
								  return napi_build_version_tag + napi_build_version;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.get_napi_build_version_from_command_args = function(command_args) {
							 | 
						||
| 
								 | 
							
								  for (let i = 0; i < command_args.length; i++) {
							 | 
						||
| 
								 | 
							
								    const arg = command_args[i];
							 | 
						||
| 
								 | 
							
								    if (arg.indexOf(napi_build_version_tag) === 0) {
							 | 
						||
| 
								 | 
							
								      return parseInt(arg.substr(napi_build_version_tag.length), 10);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return undefined;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.swap_build_dir_out = function(napi_build_version) {
							 | 
						||
| 
								 | 
							
								  if (napi_build_version) {
							 | 
						||
| 
								 | 
							
								    const rm = require('rimraf');
							 | 
						||
| 
								 | 
							
								    rm.sync(module.exports.get_build_dir(napi_build_version));
							 | 
						||
| 
								 | 
							
								    fs.renameSync('build', module.exports.get_build_dir(napi_build_version));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.swap_build_dir_in = function(napi_build_version) {
							 | 
						||
| 
								 | 
							
								  if (napi_build_version) {
							 | 
						||
| 
								 | 
							
								    const rm = require('rimraf');
							 | 
						||
| 
								 | 
							
								    rm.sync('build');
							 | 
						||
| 
								 | 
							
								    fs.renameSync(module.exports.get_build_dir(napi_build_version), 'build');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.get_build_dir = function(napi_build_version) {
							 | 
						||
| 
								 | 
							
								  return 'build-tmp-napi-v' + napi_build_version;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.get_best_napi_build_version = function(package_json, opts) {
							 | 
						||
| 
								 | 
							
								  let best_napi_build_version = 0;
							 | 
						||
| 
								 | 
							
								  const napi_build_versions = module.exports.get_napi_build_versions(package_json, opts);
							 | 
						||
| 
								 | 
							
								  if (napi_build_versions) {
							 | 
						||
| 
								 | 
							
								    const our_napi_version = module.exports.get_napi_version(opts ? opts.target : undefined);
							 | 
						||
| 
								 | 
							
								    napi_build_versions.forEach((napi_build_version)=> {
							 | 
						||
| 
								 | 
							
								      if (napi_build_version > best_napi_build_version &&
							 | 
						||
| 
								 | 
							
												napi_build_version <= our_napi_version) {
							 | 
						||
| 
								 | 
							
								        best_napi_build_version = napi_build_version;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return best_napi_build_version === 0 ? undefined : best_napi_build_version;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.build_napi_only = function(package_json) {
							 | 
						||
| 
								 | 
							
								  return package_json.binary && package_json.binary.package_name &&
							 | 
						||
| 
								 | 
							
									package_json.binary.package_name.indexOf('{node_napi_label}') === -1;
							 | 
						||
| 
								 | 
							
								};
							 |