148 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
const fs = require('fs');
 | 
						|
const path = require('path');
 | 
						|
const types = require('./types');
 | 
						|
 | 
						|
// https://github.com/npm/npm/blob/latest/lib/config/core.js#L409-L423
 | 
						|
const envReplace = str => {
 | 
						|
	if (typeof str !== 'string' || !str) {
 | 
						|
		return str;
 | 
						|
	}
 | 
						|
 | 
						|
	// Replace any ${ENV} values with the appropriate environment
 | 
						|
	const regex = /(\\*)\$\{([^}]+)\}/g;
 | 
						|
 | 
						|
	return str.replace(regex, (orig, esc, name) => {
 | 
						|
		esc = esc.length > 0 && esc.length % 2;
 | 
						|
 | 
						|
		if (esc) {
 | 
						|
			return orig;
 | 
						|
		}
 | 
						|
 | 
						|
		if (process.env[name] === undefined) {
 | 
						|
			throw new Error(`Failed to replace env in config: ${orig}`);
 | 
						|
		}
 | 
						|
 | 
						|
		return process.env[name];
 | 
						|
	});
 | 
						|
};
 | 
						|
 | 
						|
// https://github.com/npm/npm/blob/latest/lib/config/core.js#L362-L407
 | 
						|
const parseField = (field, key) => {
 | 
						|
	if (typeof field !== 'string') {
 | 
						|
		return field;
 | 
						|
	}
 | 
						|
 | 
						|
	const typeList = [].concat(types[key]);
 | 
						|
	const isPath = typeList.indexOf(path) !== -1;
 | 
						|
	const isBool = typeList.indexOf(Boolean) !== -1;
 | 
						|
	const isString = typeList.indexOf(String) !== -1;
 | 
						|
	const isNumber = typeList.indexOf(Number) !== -1;
 | 
						|
 | 
						|
	field = `${field}`.trim();
 | 
						|
 | 
						|
	if (/^".*"$/.test(field)) {
 | 
						|
		try {
 | 
						|
			field = JSON.parse(field);
 | 
						|
		} catch (err) {
 | 
						|
			throw new Error(`Failed parsing JSON config key ${key}: ${field}`);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (isBool && !isString && field === '') {
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	switch (field) { // eslint-disable-line default-case
 | 
						|
		case 'true': {
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
		case 'false': {
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
		case 'null': {
 | 
						|
			return null;
 | 
						|
		}
 | 
						|
 | 
						|
		case 'undefined': {
 | 
						|
			return undefined;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	field = envReplace(field);
 | 
						|
 | 
						|
	if (isPath) {
 | 
						|
		const regex = process.platform === 'win32' ? /^~(\/|\\)/ : /^~\//;
 | 
						|
 | 
						|
		if (regex.test(field) && process.env.HOME) {
 | 
						|
			field = path.resolve(process.env.HOME, field.substr(2));
 | 
						|
		}
 | 
						|
 | 
						|
		field = path.resolve(field);
 | 
						|
	}
 | 
						|
 | 
						|
	if (isNumber && !field.isNan()) {
 | 
						|
		field = Number(field);
 | 
						|
	}
 | 
						|
 | 
						|
	return field;
 | 
						|
};
 | 
						|
 | 
						|
// https://github.com/npm/npm/blob/latest/lib/config/find-prefix.js
 | 
						|
const findPrefix = name => {
 | 
						|
	name = path.resolve(name);
 | 
						|
 | 
						|
	let walkedUp = false;
 | 
						|
 | 
						|
	while (path.basename(name) === 'node_modules') {
 | 
						|
		name = path.dirname(name);
 | 
						|
		walkedUp = true;
 | 
						|
	}
 | 
						|
 | 
						|
	if (walkedUp) {
 | 
						|
		return name;
 | 
						|
	}
 | 
						|
 | 
						|
	const find = (name, original) => {
 | 
						|
		const regex = /^[a-zA-Z]:(\\|\/)?$/;
 | 
						|
 | 
						|
		if (name === '/' || (process.platform === 'win32' && regex.test(name))) {
 | 
						|
			return original;
 | 
						|
		}
 | 
						|
 | 
						|
		try {
 | 
						|
			const files = fs.readdirSync(name);
 | 
						|
 | 
						|
			if (files.indexOf('node_modules') !== -1 || files.indexOf('package.json') !== -1) {
 | 
						|
				return name;
 | 
						|
			}
 | 
						|
 | 
						|
			const dirname = path.dirname(name);
 | 
						|
 | 
						|
			if (dirname === name) {
 | 
						|
				return original;
 | 
						|
			}
 | 
						|
 | 
						|
			return find(dirname, original);
 | 
						|
		} catch (err) {
 | 
						|
			if (name === original) {
 | 
						|
				if (err.code === 'ENOENT') {
 | 
						|
					return original;
 | 
						|
				}
 | 
						|
 | 
						|
				throw err;
 | 
						|
			}
 | 
						|
 | 
						|
			return original;
 | 
						|
		}
 | 
						|
	};
 | 
						|
 | 
						|
	return find(name, name);
 | 
						|
};
 | 
						|
 | 
						|
exports.envReplace = envReplace;
 | 
						|
exports.findPrefix = findPrefix;
 | 
						|
exports.parseField = parseField;
 |