typescript-cp
Version:
Copy non-typescript files to outDir
534 lines (533 loc) • 23.1 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.definitely_posix = exports.sleep = exports.copy_file_or_directory = exports.remove_file_or_directory = exports.get_file_stats = exports.validate_path = exports.color_log = exports.get_ignore_list = exports.get_ts_projects_paths = exports.get_ts_project_paths = exports.get_ts_config = exports.get_config = exports.console_colors = void 0;
var path = __importStar(require("path"));
var fs = __importStar(require("fs"));
var commander_1 = require("commander");
var typescript_1 = __importDefault(require("typescript"));
var fs_extra_1 = __importDefault(require("fs-extra"));
var rimraf_1 = require("rimraf");
var cosmiconfig_1 = require("cosmiconfig");
// https://stackoverflow.com/a/41407246/3111787
// https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
var console_colors;
(function (console_colors) {
console_colors["Reset"] = "\u001B[0m";
console_colors["Bright"] = "\u001B[1m";
console_colors["Dim"] = "\u001B[2m";
console_colors["Underscore"] = "\u001B[4m";
console_colors["Blink"] = "\u001B[5m";
console_colors["Reverse"] = "\u001B[7m";
console_colors["Hidden"] = "\u001B[8m";
console_colors["FgBlack"] = "\u001B[30m";
console_colors["FgRed"] = "\u001B[31m";
console_colors["FgGreen"] = "\u001B[32m";
console_colors["FgYellow"] = "\u001B[33m";
console_colors["FgBlue"] = "\u001B[34m";
console_colors["FgMagenta"] = "\u001B[35m";
console_colors["FgCyan"] = "\u001B[36m";
console_colors["FgWhite"] = "\u001B[37m";
console_colors["BgBlack"] = "\u001B[40m";
console_colors["BgRed"] = "\u001B[41m";
console_colors["BgGreen"] = "\u001B[42m";
console_colors["BgYellow"] = "\u001B[43m";
console_colors["BgBlue"] = "\u001B[44m";
console_colors["BgMagenta"] = "\u001B[45m";
console_colors["BgCyan"] = "\u001B[46m";
console_colors["BgWhite"] = "\u001B[47m";
console_colors["FgBrightBlack"] = "\u001B[90m";
console_colors["FgBrightRed"] = "\u001B[91m";
console_colors["FgBrightGreen"] = "\u001B[92m";
console_colors["FgBrightYellow"] = "\u001B[93m";
console_colors["FgBrightBlue"] = "\u001B[94m";
console_colors["FgBrightMagenta"] = "\u001B[95m";
console_colors["FgBrightCyan"] = "\u001B[96m";
console_colors["FgBrightWhite"] = "\u001B[97m";
console_colors["BgBrightBlack"] = "\u001B[100m";
console_colors["BgBrightRed"] = "\u001B[101m";
console_colors["BgBrightGreen"] = "\u001B[102m";
console_colors["BgBrightYellow"] = "\u001B[103m";
console_colors["BgBrightBlue"] = "\u001B[104m";
console_colors["BgBrightMagenta"] = "\u001B[105m";
console_colors["BgBrightCyan"] = "\u001B[106m";
console_colors["BgBrightWhite"] = "\u001B[107m";
})(console_colors = exports.console_colors || (exports.console_colors = {}));
var version = require('../package.json').version;
var defaultProject = (function () {
// process.argv = ['node_path', 'script_path', ...args]
var lastArg = process.argv.slice(2).slice(-1)[0];
if (lastArg && !lastArg.startsWith('-')) {
return lastArg;
}
return 'tsconfig.json';
})();
var program = new commander_1.Command();
program
.option('-w, --watch', 'Watch input files.')
.option('-b, --build', 'Build one or more projects and their dependencies, if out of date')
.option('-p , --project <path>', 'FILE OR DIRECTORY Compile the project given the path to its configuration file, or to a folder with a \'tsconfig.json\'', defaultProject)
.version(version, '-v, --version');
program.parse(process.argv);
// @ts-ignore
var options = program.opts();
/**
* Returns the complete, resolved configuration object
*/
function get_config() {
return __awaiter(this, void 0, void 0, function () {
var cwd, ts_config, explorer, result, project_config, default_config, config;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
cwd = definitely_posix(process.cwd());
ts_config = get_ts_config(cwd, options.project);
explorer = (0, cosmiconfig_1.cosmiconfig)('tscp');
return [4 /*yield*/, explorer.search(cwd)];
case 1:
result = _a.sent();
project_config = (result || {}).config;
default_config = {
cwd: cwd,
cli_options: options,
ts_config: ts_config,
use_ts_exclude: true,
compiled_files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
ignored_files: ['node_modules'],
rules: [],
};
config = __assign(__assign({}, default_config), project_config);
config.ignored_files = __spreadArray(__spreadArray([], __read(config.compiled_files), false), __read(config.ignored_files), false);
return [2 /*return*/, config];
}
});
});
}
exports.get_config = get_config;
/**
* Finds the `project` config file in `currentDir` and parses it with Typescript's own parser
* @param currentDir
* @param project
*/
function get_ts_config(currentDir, project) {
var configFile = typescript_1.default.findConfigFile(currentDir, typescript_1.default.sys.fileExists, project);
if (!configFile)
throw Error('tsconfig.json not found');
var config = typescript_1.default.readConfigFile(configFile, typescript_1.default.sys.readFile).config;
return typescript_1.default.parseJsonConfigFileContent(config, typescript_1.default.sys, currentDir);
}
exports.get_ts_config = get_ts_config;
/**
* Creates an internal project descriptor for one Typescript project
* @param cwd
* @param project_path
* @param ts_config
*/
function build_project_path(cwd, project_path, ts_config) {
var currentDirName = path.basename(path.resolve());
var referenceName = path.relative(process.cwd(), cwd);
var projectName = path.join(currentDirName, referenceName);
var exclude = ts_config.raw.exclude;
var _a = ts_config.options, rootDir = _a.rootDir, outDir = _a.outDir, noEmit = _a.noEmit;
if (!rootDir) {
throw new Error("No 'rootDir' configured in reference '".concat(referenceName, "'"));
}
if (!outDir) {
throw new Error("No 'outDir' configured in reference '".concat(referenceName, "'"));
}
return {
project_name: projectName,
base_path: cwd,
ts_config_path: project_path,
root_dir: rootDir,
out_dir: outDir,
exclude: exclude || [],
no_emit: noEmit !== null && noEmit !== void 0 ? noEmit : false,
};
}
/**
* Returns the internal project descriptor of a TS project that doesn't have project references
* @param options
*/
function get_ts_project_paths(options) {
var cwd = options.cwd, cli_options = options.cli_options, ts_config = options.ts_config;
var project = build_project_path(cwd, cli_options.project, ts_config);
if (project.no_emit) {
throw new Error('Project must have emitting enabled');
}
return project;
}
exports.get_ts_project_paths = get_ts_project_paths;
/**
* Returns the internal project descriptor of a TS project that has project references
* @param options
*/
function get_ts_projects_paths(options) {
var ts_config = options.ts_config;
if (!ts_config.projectReferences) {
throw new Error('No project references configured');
}
var projects = ts_config.projectReferences.map(function (reference) {
if (!reference.path) {
throw new Error('Could not find project reference path');
}
if (!reference.originalPath) {
throw new Error('Could not find project reference originalPath');
}
var cwd = path.dirname(reference.path);
var referenceConfig = get_ts_config(cwd, reference.originalPath);
return build_project_path(cwd, reference.originalPath, referenceConfig);
});
var projects_with_emit = projects.filter(function (project) { return !project.no_emit; });
if (projects_with_emit.length === 0) {
throw new Error('At least one project must have emitting enabled');
}
return projects_with_emit;
}
exports.get_ts_projects_paths = get_ts_projects_paths;
/**
* Combines the exclude pattern in the tsconfig file and the TSCP `config.ignored_files`
* @param config
* @param projects
*/
function get_ignore_list(config, projects) {
var ignore_list = [];
if (config.use_ts_exclude) {
var safe_projects = !Array.isArray(projects) ? [projects] : projects;
var ts_exclude_list = safe_projects.map(function (project) {
return project.exclude.map(function (rule) {
// Handle if the exclude pattern contains the name of the root directory
var rootDirName = project.root_dir.replace(project.base_path + '/', '') + '/';
if (rule.startsWith(rootDirName)) {
return rule.replace(rootDirName, '');
}
return rule;
});
}).flat();
ignore_list.push.apply(ignore_list, __spreadArray([], __read(ts_exclude_list), false));
}
ignore_list.push.apply(ignore_list, __spreadArray([], __read(config.ignored_files), false));
return ignore_list;
}
exports.get_ignore_list = get_ignore_list;
/**
* Displays a colored log in the stdout
* @param msg
* @param color
*/
function color_log(msg, color) {
return "".concat(color).concat(msg).concat(console_colors.Reset);
}
exports.color_log = color_log;
/**
* Makes sure that the given folder (or the parent folder of a file) exists - creates if not
* @param p {string}
*/
function validate_path(p) {
return __awaiter(this, void 0, void 0, function () {
var dirname;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
dirname = path.dirname(p);
return [4 /*yield*/, get_file_stats(dirname)];
case 1:
if (!!(_a.sent())) return [3 /*break*/, 3];
return [4 /*yield*/, fs.promises.mkdir(dirname, { recursive: true })];
case 2:
_a.sent();
_a.label = 3;
case 3: return [2 /*return*/];
}
});
});
}
exports.validate_path = validate_path;
/**
* Error-safe `fs.lstat` - returns stats if the file exists, otherwise null
* @param file_path
*/
function get_file_stats(file_path) {
return __awaiter(this, void 0, void 0, function () {
var e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, fs_extra_1.default.lstat(file_path)];
case 1: return [2 /*return*/, _a.sent()];
case 2:
e_1 = _a.sent();
return [2 /*return*/, Promise.resolve()];
case 3: return [2 /*return*/];
}
});
});
}
exports.get_file_stats = get_file_stats;
/**
* Deletes the `file_path` file. Doesn't throw error if the file doesn't exist.
* @param file_path
*/
function remove_file_or_directory(file_path) {
return __awaiter(this, void 0, void 0, function () {
var stats;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, get_file_stats(file_path)];
case 1:
stats = _a.sent();
if (!stats) {
return [2 /*return*/, Promise.resolve(false)];
}
// console.log('DELETE', file_path);
return [2 /*return*/, (0, rimraf_1.rimraf)(file_path)];
}
});
});
}
exports.remove_file_or_directory = remove_file_or_directory;
var files_without_loaders = [];
/**
* Reads the content of the `source_path` file, applies the loaders on its content, and writes the processed content to `destination_path`
* @param source_path
* @param destination_path
* @param config
*/
function copy_file_or_directory(source_path, destination_path, config) {
return __awaiter(this, void 0, void 0, function () {
var stats, is_directory, raw_content, processed_content;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, get_file_stats(source_path)];
case 1:
stats = _a.sent();
if (!stats) {
return [2 /*return*/];
}
is_directory = stats.isDirectory();
if (is_directory) {
return [2 /*return*/, fs.promises.mkdir(destination_path)];
}
return [4 /*yield*/, fs_extra_1.default.readFile(source_path)];
case 2:
raw_content = _a.sent();
return [4 /*yield*/, apply_loaders(raw_content, source_path, destination_path, config)];
case 3:
processed_content = _a.sent();
return [4 /*yield*/, validate_path(destination_path)];
case 4:
_a.sent();
return [2 /*return*/, fs_extra_1.default.writeFile(destination_path, processed_content)];
}
});
});
}
exports.copy_file_or_directory = copy_file_or_directory;
/**
* Tests the given `source_path` against a given rule condition
* @param source_path
* @param rule_condition
* @param config
*/
function test_rule_condition(source_path, rule_condition, config) {
if (Array.isArray(rule_condition)) {
return rule_condition.every(function (sub_condition) { return test_rule_condition(source_path, sub_condition, config); });
}
// An exact absolute path string
if (typeof rule_condition === 'string') {
return rule_condition === source_path;
}
if (rule_condition instanceof RegExp) {
return rule_condition.test(source_path);
}
if (typeof rule_condition === 'function') {
return rule_condition(source_path);
}
return false;
}
/**
* Tests the given `source_path` against every rule conditions
* @param source_path
* @param rule
* @param config
*/
function apply_rule_condition(source_path, rule, config) {
var isMatching = rule.test !== undefined ? test_rule_condition(source_path, rule.test, config) : null;
var isIncluded = rule.include !== undefined ? test_rule_condition(source_path, rule.include, config) : null;
var isExcluded = rule.exclude !== undefined ? test_rule_condition(source_path, rule.exclude, config) : null;
if (isIncluded === true) {
return true;
}
if (isExcluded === true) {
return false;
}
if (isMatching === true) {
return true;
}
return false;
}
/**
* Passes the content of the source file to each loader in sequence and returns a Promise with the final content
* @param raw_content
* @param source_path
* @param destination_path
* @param config
*/
function apply_loaders(raw_content, source_path, destination_path, config) {
return __awaiter(this, void 0, void 0, function () {
var processed_content, should_process_file, used_rules, loaderMeta_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
processed_content = raw_content;
should_process_file = files_without_loaders.indexOf(source_path) === -1;
if (!should_process_file) return [3 /*break*/, 2];
used_rules = config.rules.filter(function (rule) { return apply_rule_condition(source_path, rule, config); });
if (!used_rules.length) {
files_without_loaders.push(source_path);
return [2 /*return*/, raw_content];
}
loaderMeta_1 = {
source_path: source_path,
destination_path: destination_path,
config: config,
};
return [4 /*yield*/, used_rules.reduce(function (content, rule) {
return __spreadArray([], __read(rule.use), false).reverse().reduce(function (content, loader) {
var loaderFn;
switch (typeof loader.loader) {
case 'function':
loaderFn = loader.loader;
break;
case 'string':
loaderFn = require(path.resolve(loader.loader));
break;
default:
throw new Error('Invalid loader type');
}
return loaderFn(content, loaderMeta_1);
}, processed_content);
}, processed_content)];
case 1:
processed_content = _a.sent();
_a.label = 2;
case 2: return [2 /*return*/, processed_content];
}
});
});
}
/**
* Returns a Promise that resolves automatically after `ms`
* @param ms
*/
function sleep(ms) {
return new Promise(function (resolve) { return setTimeout(resolve, ms); });
}
exports.sleep = sleep;
/**
* Converts your path `p` to POSIX format irrespective of whether you're already on POSIX platforms, or on win32
* @param p path string
* @see https://stackoverflow.com/a/63251716/3111787
*/
function definitely_posix(p) {
return p.split(path.sep).join(path.posix.sep);
}
exports.definitely_posix = definitely_posix;