@stencil/core
Version:
A Compiler for Web Components and Progressive Web Apps
1,539 lines (1,475 loc) • 1.26 MB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var fs$1 = require('./graceful-fs.js');
var fs$1__default = _interopDefault(fs$1);
var path$2 = require('path');
var path$2__default = _interopDefault(path$2);
var fs$2 = require('fs');
var fs$2__default = _interopDefault(fs$2);
var mockDoc = require('../../mock-doc');
var utils$4 = require('../../utils');
var crypto$1 = require('crypto');
var crypto$1__default = _interopDefault(crypto$1);
var ts = _interopDefault(require('typescript'));
var https$1 = require('https');
var util$1 = _interopDefault(require('util'));
var events$1 = require('events');
var events$1__default = _interopDefault(events$1);
var assert$2 = _interopDefault(require('assert'));
var child_process$1 = require('child_process');
var child_process$1__default = _interopDefault(child_process$1);
var module$1$1 = _interopDefault(require('module'));
var os$1 = require('os');
var os$1__default = _interopDefault(os$1);
var _0777 = parseInt('0777', 8);
var mkdirp = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
function mkdirP (p, opts, f, made) {
if (typeof opts === 'function') {
f = opts;
opts = {};
}
else if (!opts || typeof opts !== 'object') {
opts = { mode: opts };
}
var mode = opts.mode;
var xfs = opts.fs || fs$2__default;
if (mode === undefined) {
mode = _0777 & (~process.umask());
}
if (!made) made = null;
var cb = f || function () {};
p = path$2__default.resolve(p);
xfs.mkdir(p, mode, function (er) {
if (!er) {
made = made || p;
return cb(null, made);
}
switch (er.code) {
case 'ENOENT':
mkdirP(path$2__default.dirname(p), opts, function (er, made) {
if (er) cb(er, made);
else mkdirP(p, opts, cb, made);
});
break;
// In the case of any other error, just see if there's a dir
// there already. If so, then hooray! If not, then something
// is borked.
default:
xfs.stat(p, function (er2, stat) {
// if the stat fails, then that's super weird.
// let the original error be the failure reason.
if (er2 || !stat.isDirectory()) cb(er, made);
else cb(null, made);
});
break;
}
});
}
mkdirP.sync = function sync (p, opts, made) {
if (!opts || typeof opts !== 'object') {
opts = { mode: opts };
}
var mode = opts.mode;
var xfs = opts.fs || fs$2__default;
if (mode === undefined) {
mode = _0777 & (~process.umask());
}
if (!made) made = null;
p = path$2__default.resolve(p);
try {
xfs.mkdirSync(p, mode);
made = made || p;
}
catch (err0) {
switch (err0.code) {
case 'ENOENT' :
made = sync(path$2__default.dirname(p), opts, made);
sync(p, opts, made);
break;
// In the case of any other error, just see if there's a dir
// there already. If so, then hooray! If not, then something
// is borked.
default:
var stat;
try {
stat = xfs.statSync(p);
}
catch (err1) {
throw err0;
}
if (!stat.isDirectory()) throw err0;
break;
}
}
return made;
};
class NodeFs {
constructor(process) {
this.supportsMkdirRecursive = false;
this.supportsCOPYFILE_FICLONE = false;
try {
const segments = process.version.split('.').map(v => parseInt(v, 10));
const major = segments[0];
const minor = segments[1];
// mkdir recursive support started in v10.12.0
this.supportsMkdirRecursive = (major >= 11 || (major === 10 && minor >= 12));
this.supportsCOPYFILE_FICLONE = (major >= 12);
}
catch (e) { }
}
access(path) {
return new Promise((resolve, reject) => {
fs$1__default.access(path, err => {
if (err) {
reject(err);
}
else {
resolve();
}
});
});
}
copyFile(src, dest) {
return new Promise((resolve, reject) => {
const flags = this.supportsCOPYFILE_FICLONE
? fs$1__default.constants.COPYFILE_FICLONE
: 0;
return fs$1__default.copyFile(src, dest, flags, (err) => {
if (err) {
reject(err);
}
else {
resolve();
}
});
});
}
createReadStream(filePath) {
return fs$1__default.createReadStream(filePath);
}
mkdir(dirPath, opts = {}) {
if (opts.recursive) {
if (this.supportsMkdirRecursive) {
// supports mkdir recursive
return new Promise((resolve, reject) => {
fs$1__default.mkdir(dirPath, opts, err => {
if (err) {
reject(err);
}
else {
resolve();
}
});
});
}
else {
// does NOT support mkdir recursive
// use good ol' mkdirp
return new Promise((resolve, reject) => {
mkdirp(dirPath, err => {
if (err) {
reject(err);
}
else {
resolve();
}
});
});
}
}
// not doing recursive
return new Promise((resolve, reject) => {
fs$1__default.mkdir(dirPath, opts, err => {
if (err) {
reject(err);
}
else {
resolve();
}
});
});
}
mkdirSync(dirPath, opts = {}) {
if (opts.recursive) {
if (this.supportsMkdirRecursive) {
// supports mkdir recursive
fs$1__default.mkdirSync(dirPath, opts);
}
else {
// does NOT support mkdir recursive
// use good ol' mkdirp
mkdirp.sync(dirPath, opts);
}
}
else {
// not doing recursive
fs$1__default.mkdirSync(dirPath, opts);
}
}
readdir(dirPath) {
return new Promise((resolve, reject) => {
fs$1__default.readdir(dirPath, (err, files) => {
if (err) {
reject(err);
}
else {
resolve(files);
}
});
});
}
readdirSync(dirPath) {
return fs$1__default.readdirSync(dirPath);
}
readFile(filePath, format = 'utf8') {
return new Promise((resolve, reject) => {
fs$1__default.readFile(filePath, format, (err, content) => {
if (err) {
reject(err);
}
else {
resolve(content);
}
});
});
}
exists(filePath) {
return new Promise(resolve => {
fs$1__default.exists(filePath, resolve);
});
}
existsSync(filePath) {
return fs$1__default.existsSync(filePath);
}
readFileSync(filePath, format = 'utf8') {
return fs$1__default.readFileSync(filePath, format);
}
rmdir(dirPath) {
return new Promise((resolve, reject) => {
fs$1__default.rmdir(dirPath, (err) => {
if (err) {
reject(err);
}
else {
resolve();
}
});
});
}
stat(itemPath) {
return new Promise((resolve, reject) => {
fs$1__default.stat(itemPath, (err, stats) => {
if (err) {
reject(err);
}
else {
resolve(stats);
}
});
});
}
statSync(itemPath) {
return fs$1__default.statSync(itemPath);
}
unlink(filePath) {
return new Promise((resolve, reject) => {
fs$1__default.unlink(filePath, (err) => {
if (err) {
reject(err);
}
else {
resolve();
}
});
});
}
writeFile(filePath, content) {
return new Promise((resolve, reject) => {
fs$1__default.writeFile(filePath, content, { encoding: 'utf8' }, (err) => {
if (err) {
reject(err);
}
else {
resolve();
}
});
});
}
writeFileSync(filePath, content) {
return fs$1__default.writeFileSync(filePath, content, { encoding: 'utf8' });
}
}
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
function getCjsExportFromNamespace (n) {
return n && n['default'] || n;
}
var symbols = createCommonjsModule(function (module) {
const isHyper = process.env.TERM_PROGRAM === 'Hyper';
const isWindows = process.platform === 'win32';
const isLinux = process.platform === 'linux';
const common = {
ballotDisabled: '☒',
ballotOff: '☐',
ballotOn: '☑',
bullet: '•',
bulletWhite: '◦',
fullBlock: '█',
heart: '❤',
identicalTo: '≡',
line: '─',
mark: '※',
middot: '·',
minus: '-',
multiplication: '×',
obelus: '÷',
pencilDownRight: '✎',
pencilRight: '✏',
pencilUpRight: '✐',
percent: '%',
pilcrow2: '❡',
pilcrow: '¶',
plusMinus: '±',
section: '§',
starsOff: '☆',
starsOn: '★',
upDownArrow: '↕'
};
const windows = {
...common,
check: '√',
cross: '×',
ellipsisLarge: '...',
ellipsis: '...',
info: 'i',
question: '?',
questionSmall: '?',
pointer: '>',
pointerSmall: '»',
radioOff: '( )',
radioOn: '(*)',
warning: '‼'
};
const other = {
...common,
ballotCross: '✘',
check: '✔',
cross: '✖',
ellipsisLarge: '⋯',
ellipsis: '…',
info: 'ℹ',
question: '?',
questionFull: '?',
questionSmall: '﹖',
pointer: isLinux ? '▸' : '❯',
pointerSmall: isLinux ? '‣' : '›',
radioOff: '◯',
radioOn: '◉',
warning: '⚠'
};
module.exports = (isWindows && !isHyper) ? windows : other;
Reflect.defineProperty(module.exports, 'common', { enumerable: false, value: common });
Reflect.defineProperty(module.exports, 'windows', { enumerable: false, value: windows });
Reflect.defineProperty(module.exports, 'other', { enumerable: false, value: other });
});
const create = () => {
const colors = { enabled: true, visible: true, styles: {}, keys: {} };
if ('FORCE_COLOR' in process.env) {
colors.enabled = process.env.FORCE_COLOR !== '0';
}
const ansi = style => {
style.open = `\u001b[${style.codes[0]}m`;
style.close = `\u001b[${style.codes[1]}m`;
style.regex = new RegExp(`\\u001b\\[${style.codes[1]}m`, 'g');
return style;
};
const wrap = (style, str, nl) => {
let { open, close, regex } = style;
str = open + (str.includes(close) ? str.replace(regex, close + open) : str) + close;
// see https://github.com/chalk/chalk/pull/92, thanks to the
// chalk contributors for this fix. However, we've confirmed that
// this issue is also present in Windows terminals
return nl ? str.replace(/\r*\n/g, `${close}$&${open}`) : str;
};
const style = (input, stack) => {
if (input === '' || input == null) return '';
if (colors.enabled === false) return input;
if (colors.visible === false) return '';
let str = '' + input;
let nl = str.includes('\n');
let n = stack.length;
while (n-- > 0) str = wrap(colors.styles[stack[n]], str, nl);
return str;
};
const define = (name, codes, type) => {
colors.styles[name] = ansi({ name, codes });
let t = colors.keys[type] || (colors.keys[type] = []);
t.push(name);
Reflect.defineProperty(colors, name, {
configurable: true,
enumerable: true,
set(value) {
colors.alias(name, value);
},
get() {
let color = input => style(input, color.stack);
Reflect.setPrototypeOf(color, colors);
color.stack = this.stack ? this.stack.concat(name) : [name];
return color;
}
});
};
define('reset', [0, 0], 'modifier');
define('bold', [1, 22], 'modifier');
define('dim', [2, 22], 'modifier');
define('italic', [3, 23], 'modifier');
define('underline', [4, 24], 'modifier');
define('inverse', [7, 27], 'modifier');
define('hidden', [8, 28], 'modifier');
define('strikethrough', [9, 29], 'modifier');
define('black', [30, 39], 'color');
define('red', [31, 39], 'color');
define('green', [32, 39], 'color');
define('yellow', [33, 39], 'color');
define('blue', [34, 39], 'color');
define('magenta', [35, 39], 'color');
define('cyan', [36, 39], 'color');
define('white', [37, 39], 'color');
define('gray', [90, 39], 'color');
define('grey', [90, 39], 'color');
define('bgBlack', [40, 49], 'bg');
define('bgRed', [41, 49], 'bg');
define('bgGreen', [42, 49], 'bg');
define('bgYellow', [43, 49], 'bg');
define('bgBlue', [44, 49], 'bg');
define('bgMagenta', [45, 49], 'bg');
define('bgCyan', [46, 49], 'bg');
define('bgWhite', [47, 49], 'bg');
define('blackBright', [90, 39], 'bright');
define('redBright', [91, 39], 'bright');
define('greenBright', [92, 39], 'bright');
define('yellowBright', [93, 39], 'bright');
define('blueBright', [94, 39], 'bright');
define('magentaBright', [95, 39], 'bright');
define('cyanBright', [96, 39], 'bright');
define('whiteBright', [97, 39], 'bright');
define('bgBlackBright', [100, 49], 'bgBright');
define('bgRedBright', [101, 49], 'bgBright');
define('bgGreenBright', [102, 49], 'bgBright');
define('bgYellowBright', [103, 49], 'bgBright');
define('bgBlueBright', [104, 49], 'bgBright');
define('bgMagentaBright', [105, 49], 'bgBright');
define('bgCyanBright', [106, 49], 'bgBright');
define('bgWhiteBright', [107, 49], 'bgBright');
/* eslint-disable no-control-regex */
// this is a modified, optimized version of
// https://github.com/chalk/ansi-regex (MIT License)
const re = colors.ansiRegex = /[\u001b\u009b][[\]#;?()]*(?:(?:(?:[^\W_]*;?[^\W_]*)\u0007)|(?:(?:[0-9]{1,4}(;[0-9]{0,4})*)?[~0-9=<>cf-nqrtyA-PRZ]))/g;
colors.hasColor = colors.hasAnsi = str => {
re.lastIndex = 0;
return !!str && typeof str === 'string' && re.test(str);
};
colors.unstyle = str => {
re.lastIndex = 0;
return typeof str === 'string' ? str.replace(re, '') : str;
};
colors.alias = (name, color) => {
let fn = typeof color === 'string' ? colors[color] : color;
Reflect.defineProperty(colors, name, {
configurable: true,
enumerable: true,
set(value) {
colors.alias(name, value);
},
get() {
let color = input => style(input, color.stack);
Reflect.setPrototypeOf(color, colors);
color.stack = this.stack ? this.stack.concat(fn.stack) : fn.stack;
return color;
}
});
};
colors.theme = obj => {
for (let name of Object.keys(obj)) {
colors.alias(name, obj[name]);
}
return colors;
};
colors.none = colors.clear = colors.noop = str => str; // no-op, for programmatic usage
colors.stripColor = colors.unstyle;
colors.symbols = symbols;
colors.define = define;
return colors;
};
var ansiColors = create();
var create_1 = create;
ansiColors.create = create_1;
class NodeLogger {
constructor() {
this._level = 'info';
this.writeLogQueue = [];
this.buildLogFilePath = null;
}
get level() {
return this._level;
}
set level(l) {
if (typeof l === 'string') {
l = l.toLowerCase().trim();
if (LOG_LEVELS.indexOf(l) === -1) {
this.error(`Invalid log level '${ansiColors.bold(l)}' (choose from: ${LOG_LEVELS.map(l => ansiColors.bold(l)).join(', ')})`);
}
else {
this._level = l;
}
}
}
info(...msg) {
if (this.shouldLog('info')) {
const lines = wordWrap(msg, getColumns());
this.infoPrefix(lines);
console.log(lines.join('\n'));
}
this.queueWriteLog('I', msg);
}
infoPrefix(lines) {
if (lines.length) {
const d = new Date();
const prefix = '[' +
('0' + d.getMinutes()).slice(-2) + ':' +
('0' + d.getSeconds()).slice(-2) + '.' +
Math.floor((d.getMilliseconds() / 1000) * 10) + ']';
lines[0] = this.dim(prefix) + lines[0].substr(prefix.length);
}
}
warn(...msg) {
if (this.shouldLog('warn')) {
const lines = wordWrap(msg, getColumns());
this.warnPrefix(lines);
console.warn('\n' + lines.join('\n') + '\n');
}
this.queueWriteLog('W', msg);
}
warnPrefix(lines) {
if (lines.length) {
const prefix = '[ WARN ]';
lines[0] = this.bold(ansiColors.yellow(prefix)) + lines[0].substr(prefix.length);
}
}
error(...msg) {
for (let i = 0; i < msg.length; i++) {
if (msg[i] instanceof Error) {
const err = msg[i];
msg[i] = err.message;
if (err.stack) {
msg[i] += '\n' + err.stack;
}
}
}
if (this.shouldLog('error')) {
const lines = wordWrap(msg, getColumns());
this.errorPrefix(lines);
console.error('\n' + lines.join('\n') + '\n');
}
this.queueWriteLog('E', msg);
}
errorPrefix(lines) {
if (lines.length) {
const prefix = '[ ERROR ]';
lines[0] = this.bold(ansiColors.red(prefix)) + lines[0].substr(prefix.length);
}
}
debug(...msg) {
if (this.shouldLog('debug')) {
msg.push(this.dim(` MEM: ${(process.memoryUsage().rss / 1000000).toFixed(1)}MB`));
const lines = wordWrap(msg, getColumns());
this.debugPrefix(lines);
console.log(lines.join('\n'));
}
this.queueWriteLog('D', msg);
}
debugPrefix(lines) {
if (lines.length) {
const d = new Date();
const prefix = '[' +
('0' + d.getMinutes()).slice(-2) + ':' +
('0' + d.getSeconds()).slice(-2) + '.' +
Math.floor((d.getMilliseconds() / 1000) * 10) + ']';
lines[0] = ansiColors.cyan(prefix) + lines[0].substr(prefix.length);
}
}
timespanStart(startMsg, debug, appendTo) {
const msg = [`${startMsg} ${this.dim('...')}`];
if (debug) {
if (this.shouldLog('debug')) {
msg.push(this.dim(` MEM: ${(process.memoryUsage().rss / 1000000).toFixed(1)}MB`));
const lines = wordWrap(msg, getColumns());
this.debugPrefix(lines);
console.log(lines.join('\n'));
this.queueWriteLog('D', [`${startMsg} ...`]);
}
}
else {
const lines = wordWrap(msg, getColumns());
this.infoPrefix(lines);
console.log(lines.join('\n'));
this.queueWriteLog('I', [`${startMsg} ...`]);
if (appendTo) {
appendTo.push(`${startMsg} ...`);
}
}
}
timespanFinish(finishMsg, timeSuffix, color, bold, newLineSuffix, debug, appendTo) {
let msg = finishMsg;
if (color) {
msg = this.color(finishMsg, color);
}
if (bold) {
msg = this.bold(msg);
}
msg += ' ' + this.dim(timeSuffix);
if (debug) {
if (this.shouldLog('debug')) {
const m = [msg];
m.push(this.dim(` MEM: ${(process.memoryUsage().rss / 1000000).toFixed(1)}MB`));
const lines = wordWrap(m, getColumns());
this.debugPrefix(lines);
console.log(lines.join('\n'));
}
this.queueWriteLog('D', [`${finishMsg} ${timeSuffix}`]);
}
else {
const lines = wordWrap([msg], getColumns());
this.infoPrefix(lines);
console.log(lines.join('\n'));
this.queueWriteLog('I', [`${finishMsg} ${timeSuffix}`]);
if (appendTo) {
appendTo.push(`${finishMsg} ${timeSuffix}`);
}
}
if (newLineSuffix) {
console.log('');
}
}
queueWriteLog(prefix, msg) {
if (this.buildLogFilePath) {
const d = new Date();
const log = '' +
('0' + d.getHours()).slice(-2) + ':' +
('0' + d.getMinutes()).slice(-2) + ':' +
('0' + d.getSeconds()).slice(-2) + '.' +
('0' + Math.floor((d.getMilliseconds() / 1000) * 10)) +
' ' +
('000' + (process.memoryUsage().rss / 1000000).toFixed(1)).slice(-6) + 'MB' +
' ' + prefix +
' ' +
msg.join(', ');
this.writeLogQueue.push(log);
}
}
writeLogs(append) {
if (this.buildLogFilePath) {
try {
this.queueWriteLog('F', ['--------------------------------------']);
const log = this.writeLogQueue.join('\n');
if (append) {
try {
fs$1__default.accessSync(this.buildLogFilePath);
}
catch (e) {
append = false;
}
}
if (append) {
fs$1__default.appendFileSync(this.buildLogFilePath, log);
}
else {
fs$1__default.writeFileSync(this.buildLogFilePath, log);
}
}
catch (e) { }
}
this.writeLogQueue.length = 0;
}
color(msg, colorName) {
return ansiColors[colorName](msg);
}
red(msg) {
return ansiColors.red(msg);
}
green(msg) {
return ansiColors.green(msg);
}
yellow(msg) {
return ansiColors.yellow(msg);
}
blue(msg) {
return ansiColors.blue(msg);
}
magenta(msg) {
return ansiColors.magenta(msg);
}
cyan(msg) {
return ansiColors.cyan(msg);
}
gray(msg) {
return ansiColors.gray(msg);
}
bold(msg) {
return ansiColors.bold(msg);
}
dim(msg) {
return ansiColors.dim(msg);
}
shouldLog(level) {
return LOG_LEVELS.indexOf(level) >= LOG_LEVELS.indexOf(this.level);
}
createTimeSpan(startMsg, debug = false, appendTo) {
return new CmdTimeSpan(this, startMsg, debug, appendTo);
}
printDiagnostics(diagnostics, cwd) {
if (!diagnostics || diagnostics.length === 0)
return;
let outputLines = [''];
diagnostics.forEach(d => {
outputLines = outputLines.concat(this.printDiagnostic(d, cwd));
});
console.log(outputLines.join('\n'));
}
printDiagnostic(diagnostic, cwd) {
const outputLines = wordWrap([diagnostic.messageText], getColumns());
let header = '';
if (diagnostic.header && diagnostic.header !== 'Build Error') {
header += diagnostic.header;
}
if (typeof diagnostic.absFilePath === 'string' && typeof diagnostic.relFilePath !== 'string') {
if (typeof cwd !== 'string') {
cwd = process.cwd();
}
diagnostic.relFilePath = path$2__default.relative(cwd, diagnostic.absFilePath);
if (!diagnostic.relFilePath.includes('/')) {
diagnostic.relFilePath = './' + diagnostic.relFilePath;
}
}
let filePath = diagnostic.relFilePath;
if (typeof filePath !== 'string') {
filePath = diagnostic.absFilePath;
}
if (typeof filePath === 'string') {
if (header.length > 0) {
header += ': ';
}
header += ansiColors.cyan(filePath);
if (typeof diagnostic.lineNumber === 'number' && diagnostic.lineNumber > -1) {
header += ansiColors.dim(`:`);
header += ansiColors.yellow(`${diagnostic.lineNumber}`);
if (typeof diagnostic.columnNumber === 'number' && diagnostic.columnNumber > -1) {
header += ansiColors.dim(`:`);
header += ansiColors.yellow(`${diagnostic.columnNumber}`);
}
}
}
if (header.length > 0) {
outputLines.unshift(INDENT + header);
}
outputLines.push('');
if (diagnostic.lines && diagnostic.lines.length) {
const lines = prepareLines(diagnostic.lines);
lines.forEach(l => {
if (!isMeaningfulLine(l.text)) {
return;
}
let msg = ``;
if (l.lineNumber > -1) {
msg = `L${l.lineNumber}: `;
}
while (msg.length < INDENT.length) {
msg = ' ' + msg;
}
let text = l.text;
if (l.errorCharStart > -1) {
text = this.highlightError(text, l.errorCharStart, l.errorLength);
}
msg = this.dim(msg);
if (diagnostic.language === 'typescript' || diagnostic.language === 'javascript') {
msg += this.javaScriptSyntaxHighlight(text);
}
else if (diagnostic.language === 'scss' || diagnostic.language === 'css') {
msg += this.cssSyntaxHighlight(text);
}
else {
msg += text;
}
outputLines.push(msg);
});
outputLines.push('');
}
if (diagnostic.level === 'error') {
this.errorPrefix(outputLines);
}
else if (diagnostic.level === 'warn') {
this.warnPrefix(outputLines);
}
else if (diagnostic.level === 'debug') {
this.debugPrefix(outputLines);
}
else {
this.infoPrefix(outputLines);
}
if (diagnostic.debugText != null && this.level === 'debug') {
outputLines.push(diagnostic.debugText);
this.debugPrefix(wordWrap([diagnostic.debugText], getColumns()));
}
return outputLines;
}
highlightError(errorLine, errorCharStart, errorLength) {
let rightSideChars = errorLine.length - errorCharStart + errorLength - 1;
while (errorLine.length + INDENT.length > MAX_COLUMNS) {
if (errorCharStart > (errorLine.length - errorCharStart + errorLength) && errorCharStart > 5) {
// larger on left side
errorLine = errorLine.substr(1);
errorCharStart--;
}
else if (rightSideChars > 1) {
// larger on right side
errorLine = errorLine.substr(0, errorLine.length - 1);
rightSideChars--;
}
else {
break;
}
}
const lineChars = [];
const lineLength = Math.max(errorLine.length, errorCharStart + errorLength);
for (var i = 0; i < lineLength; i++) {
var chr = errorLine.charAt(i);
if (i >= errorCharStart && i < errorCharStart + errorLength) {
chr = ansiColors.bgRed(chr === '' ? ' ' : chr);
}
lineChars.push(chr);
}
return lineChars.join('');
}
javaScriptSyntaxHighlight(text) {
if (text.trim().startsWith('//')) {
return this.dim(text);
}
const words = text.split(' ').map(word => {
if (JS_KEYWORDS.indexOf(word) > -1) {
return ansiColors.cyan(word);
}
return word;
});
return words.join(' ');
}
cssSyntaxHighlight(text) {
let cssProp = true;
const safeChars = 'abcdefghijklmnopqrstuvwxyz-_';
const notProp = '.#,:}@$[]/*';
const chars = [];
for (var i = 0; i < text.length; i++) {
const c = text.charAt(i);
if (c === ';' || c === '{') {
cssProp = true;
}
else if (notProp.indexOf(c) > -1) {
cssProp = false;
}
if (cssProp && safeChars.indexOf(c.toLowerCase()) > -1) {
chars.push(ansiColors.cyan(c));
continue;
}
chars.push(c);
}
return chars.join('');
}
}
class CmdTimeSpan {
constructor(logger, startMsg, debug, appendTo) {
this.debug = debug;
this.appendTo = appendTo;
this.logger = logger;
this.start = Date.now();
this.logger.timespanStart(startMsg, debug, this.appendTo);
}
duration() {
return Date.now() - this.start;
}
finish(msg, color, bold, newLineSuffix) {
const duration = this.duration();
let time;
if (duration > 1000) {
time = 'in ' + (duration / 1000).toFixed(2) + ' s';
}
else {
const ms = parseFloat((duration).toFixed(3));
if (ms > 0) {
time = 'in ' + duration + ' ms';
}
else {
time = 'in less than 1 ms';
}
}
this.logger.timespanFinish(msg, time, color, bold, newLineSuffix, this.debug, this.appendTo);
return duration;
}
}
const LOG_LEVELS = ['debug', 'info', 'warn', 'error'];
function getColumns() {
const terminalWidth = (process.stdout && process.stdout.columns) || 80;
return Math.max(Math.min(MAX_COLUMNS, terminalWidth), MIN_COLUMNS);
}
function wordWrap(msg, columns) {
const lines = [];
const words = [];
msg.forEach(m => {
if (m === null) {
words.push('null');
}
else if (typeof m === 'undefined') {
words.push('undefined');
}
else if (typeof m === 'string') {
m.replace(/\s/gm, ' ').split(' ').forEach(strWord => {
if (strWord.trim().length) {
words.push(strWord.trim());
}
});
}
else if (typeof m === 'number' || typeof m === 'boolean' || typeof m === 'function') {
words.push(m.toString());
}
else if (Array.isArray(m)) {
words.push(() => {
return m.toString();
});
}
else if (Object(m) === m) {
words.push(() => {
return m.toString();
});
}
else {
words.push(m.toString());
}
});
let line = INDENT;
words.forEach(word => {
if (lines.length > 25) {
return;
}
if (typeof word === 'function') {
if (line.trim().length) {
lines.push(line);
}
lines.push(word());
line = INDENT;
}
else if (INDENT.length + word.length > columns - 1) {
// word is too long to play nice, just give it its own line
if (line.trim().length) {
lines.push(line);
}
lines.push(INDENT + word);
line = INDENT;
}
else if ((word.length + line.length) > columns - 1) {
// this word would make the line too long
// print the line now, then start a new one
lines.push(line);
line = INDENT + word + ' ';
}
else {
line += word + ' ';
}
});
if (line.trim().length) {
lines.push(line);
}
return lines.map(line => {
return line.trimRight();
});
}
function prepareLines(orgLines) {
const lines = JSON.parse(JSON.stringify(orgLines));
for (let i = 0; i < 100; i++) {
if (!eachLineHasLeadingWhitespace(lines)) {
return lines;
}
for (let i = 0; i < lines.length; i++) {
lines[i].text = lines[i].text.substr(1);
lines[i].errorCharStart--;
if (!(lines[i]).text.length) {
return lines;
}
}
}
return lines;
}
function eachLineHasLeadingWhitespace(lines) {
if (!lines.length) {
return false;
}
for (var i = 0; i < lines.length; i++) {
if (!lines[i].text || lines[i].text.length < 1) {
return false;
}
const firstChar = lines[i].text.charAt(0);
if (firstChar !== ' ' && firstChar !== '\t') {
return false;
}
}
return true;
}
function isMeaningfulLine(line) {
if (line) {
line = line.trim();
return line.length > 0;
}
return false;
}
const JS_KEYWORDS = [
'abstract', 'any', 'as', 'break', 'boolean', 'case', 'catch', 'class',
'console', 'const', 'continue', 'debugger', 'declare', 'default', 'delete',
'do', 'else', 'enum', 'export', 'extends', 'false', 'finally', 'for', 'from',
'function', 'get', 'if', 'import', 'in', 'implements', 'Infinity',
'instanceof', 'let', 'module', 'namespace', 'NaN', 'new', 'number', 'null',
'public', 'private', 'protected', 'require', 'return', 'static', 'set',
'string', 'super', 'switch', 'this', 'throw', 'try', 'true', 'type',
'typeof', 'undefined', 'var', 'void', 'with', 'while', 'yield',
];
const INDENT = ' ';
const MIN_COLUMNS = 60;
const MAX_COLUMNS = 120;
const GENERATED_DTS = 'components.d.ts';
class FsWatcher {
constructor(config, fs, events) {
this.config = config;
this.fs = fs;
this.events = events;
this.dirsAdded = [];
this.dirsDeleted = [];
this.filesAdded = [];
this.filesDeleted = [];
this.filesUpdated = new Map();
this.dirWatchers = new Map();
this.fileWatchers = new Map();
this.dirItems = new Map();
}
async addDirectory(dirPath, emit = false) {
const shouldQueue = await this.addDirectoryRecursive(dirPath, emit);
if (emit && shouldQueue) {
this.queue();
}
return shouldQueue;
}
async addDirectoryRecursive(dirPath, emit = false) {
dirPath = utils$4.normalizePath(dirPath);
if (this.shouldIgnore(dirPath)) {
return false;
}
let hasChanges = false;
if (emit && !this.dirsAdded.includes(dirPath)) {
this.dirsAdded.push(dirPath);
this.log('directory added', dirPath);
}
if (!this.dirWatchers.has(dirPath)) {
const watcher = ts.sys.watchDirectory(dirPath, this.onDirectoryWatch.bind(this), false);
this.dirWatchers.set(dirPath, watcher);
hasChanges = true;
}
const subItems = await this.fs.readdir(dirPath);
await Promise.all(subItems.map(async (fileName) => {
const itemPath = path$2__default.join(dirPath, fileName);
const stat = await this.fs.stat(itemPath);
if (stat.isFile()) {
const fileHasChanges = await this.addFile(itemPath, emit, false);
if (fileHasChanges) {
hasChanges = true;
}
}
else if (stat.isDirectory()) {
this.addDirItem(dirPath, itemPath);
const dirHasChanges = await this.addDirectoryRecursive(itemPath, emit);
if (dirHasChanges) {
hasChanges = true;
}
}
}));
return hasChanges;
}
removeDirectory(dirPath, emit = false) {
this.removeDirectoryRecursive(dirPath);
if (emit && !this.dirsDeleted.includes(dirPath)) {
this.log('directory deleted', dirPath);
this.dirsDeleted.push(dirPath);
this.queue();
}
}
removeDirectoryRecursive(dirPath) {
dirPath = utils$4.normalizePath(dirPath);
const dirWatcher = this.dirWatchers.get(dirPath);
if (dirWatcher != null) {
this.dirWatchers.delete(dirPath);
dirWatcher.close();
}
const fileWatcher = this.fileWatchers.get(dirPath);
if (fileWatcher != null) {
this.fileWatchers.delete(dirPath);
fileWatcher.close();
}
const dirItems = this.dirItems.get(dirPath);
if (dirItems != null) {
dirItems.forEach(subDirItem => {
this.removeDirectoryRecursive(subDirItem);
});
this.dirItems.delete(dirPath);
}
}
addDirItem(dirPath, dirItem) {
const dirItems = this.dirItems.get(dirPath);
if (dirItems == null) {
this.dirItems.set(dirPath, new Set([dirItem]));
}
else {
dirItems.add(dirItem);
}
}
async addFile(filePath, emit = false, queue = true) {
filePath = utils$4.normalizePath(filePath);
if (this.shouldIgnore(filePath)) {
return false;
}
let hasChanges = false;
if (!this.fileWatchers.has(filePath)) {
const watcher = ts.sys.watchFile(filePath, this.onFileWatch.bind(this));
this.fileWatchers.set(filePath, watcher);
this.addDirItem(utils$4.normalizePath(path$2__default.dirname(filePath)), filePath);
}
if (emit && !this.filesAdded.includes(filePath)) {
const buffer = await this.fs.readFile(filePath);
const hash = crypto$1__default
.createHash('md5')
.update(buffer)
.digest('base64');
const existingHash = this.filesUpdated.get(filePath);
if (existingHash === hash) {
this.log('file already added', filePath);
}
else {
this.log('file added', filePath);
this.filesUpdated.set(filePath, hash);
this.filesAdded.push(filePath);
if (queue) {
this.queue();
}
hasChanges = true;
}
}
return hasChanges;
}
removeFile(filePath, emit = false) {
filePath = utils$4.normalizePath(filePath);
const watcher = this.fileWatchers.get(filePath);
if (watcher != null) {
this.fileWatchers.delete(filePath);
watcher.close();
}
if (emit && !this.filesDeleted.includes(filePath)) {
this.log('file deleted', filePath);
this.filesDeleted.push(filePath);
this.queue();
}
}
async onFileChanged(fsPath) {
fsPath = utils$4.normalizePath(fsPath);
if (this.filesUpdated.has(fsPath)) {
this.log('file already queued to update', fsPath);
return;
}
try {
const buffer = await this.fs.readFile(fsPath);
const hash = crypto$1__default
.createHash('md5')
.update(buffer)
.digest('base64');
const existingHash = this.filesUpdated.get(fsPath);
if (existingHash === hash) {
this.log('file unchanged', fsPath);
}
else {
this.log('file updated', fsPath);
this.filesUpdated.set(fsPath, hash);
this.queue();
}
}
catch (e) {
this.log(`onFileChanged: ${e}`, fsPath);
}
}
async onDirectoryWatch(fsPath) {
fsPath = utils$4.normalizePath(fsPath);
const dirWatcher = this.dirWatchers.get(fsPath);
if (dirWatcher != null) {
// already a directory we're watching
try {
await this.fs.access(fsPath);
// and there's still access, so do nothing
}
catch (e) {
// but there's no longer access
// so let's remove it
this.removeDirectory(fsPath, true);
}
return;
}
const fileWatcher = this.fileWatchers.get(fsPath);
if (fileWatcher != null) {
// already a file we're watching
try {
await this.fs.access(fsPath);
// and there's still access, so do nothing
}
catch (e) {
// but there's no longer access
// so let's remove it
this.removeFile(fsPath, true);
}
return;
}
try {
// not already a known watcher
const stat = await this.fs.stat(fsPath);
if (stat.isDirectory()) {
this.addDirectory(fsPath, true);
}
else if (stat.isFile()) {
this.addFile(fsPath, true);
}
}
catch (e) {
this.log('onDirectoryWatch, no access', fsPath);
}
}
onFileWatch(fsPath, fsEvent) {
switch (fsEvent) {
case ts.FileWatcherEventKind.Changed:
this.onFileChanged(fsPath);
break;
case ts.FileWatcherEventKind.Deleted:
this.removeFile(fsPath, true);
break;
case ts.FileWatcherEventKind.Created:
this.addFile(fsPath, true);
break;
default:
this.log(`onFileWatch, unknown event: ${fsEvent}`, fsPath);
}
}
queue() {
// let's chill out for a few moments to see if anything else
// comes in as something that changed in the file system
clearTimeout(this.flushTmrId);
this.flushTmrId = setTimeout(this.flush.bind(this), FLUSH_TIMEOUT);
}
flush() {
if (this.dirsAdded.length === 0 && this.dirsDeleted.length === 0 && this.filesAdded.length === 0 && this.filesDeleted.length === 0 && this.filesUpdated.size === 0) {
this.log(`flush, empty queue`, this.config.rootDir);
return;
}
// create the watch results from all that we've learned today
const fsWatchResults = {
dirsAdded: this.dirsAdded.slice(),
dirsDeleted: this.dirsDeleted.slice(),
filesAdded: this.filesAdded.slice(),
filesDeleted: this.filesDeleted.slice(),
filesUpdated: Array.from(this.filesUpdated.keys())
};
this.reset();
// send out the event of what we've learend
this.events.emit('fsChange', fsWatchResults);
}
reset() {
// reset the data for next time
this.dirsAdded.length = 0;
this.dirsDeleted.length = 0;
this.filesAdded.length = 0;
this.filesDeleted.length = 0;
this.filesUpdated.clear();
}
close() {
clearTimeout(this.flushTmrId);
this.reset();
this.dirWatchers.forEach(watcher => {
watcher.close();
});
this.dirWatchers.clear();
this.fileWatchers.forEach(watcher => {
watcher.close();
});
this.fileWatchers.clear();
}
shouldIgnore(filePath) {
for (let i = 0; i < IGNORES.length; i++) {
if (filePath.endsWith(IGNORES[i])) {
return true;
}
}
if (this.config.watchIgnoredRegex != null) {
if (this.config.watchIgnoredRegex.test(filePath)) {
return true;
}
}
return false;
}
log(msg, filePath) {
if (this.config.logger != null) {
const relPath = path$2__default.relative(this.config.rootDir, filePath);
this.config.logger.debug(`fs-watcher, ${msg}: ${relPath}, ${Date.now().toString().substring(6)}`);
}
}
}
const FLUSH_TIMEOUT = 50;
const IGNORES = [
GENERATED_DTS,
'.log',
'.sql',
'.sqlite',
'.DS_Store',
'.Spotlight-V100',
'.Trashes',
'ehthumbs.db',
'Thumbs.db',
'.gitignore',
'package-lock.json'
];
async function getLatestCompilerVersion(storage, logger, forceCheck) {
try {
if (!forceCheck) {
const lastCheck = await getLastCheck(storage);
if (lastCheck == null) {
// we've never check before, so probably first install, so don't bother
// save that we did just do a check though
await setLastCheck(storage);
return null;
}
if (!requiresCheck(Date.now(), lastCheck, CHECK_INTERVAL)) {
// within the range that we did a check recently, so don't bother
return null;
}
}
// remember we just did a check
await setLastCheck(storage);
const body = await requestUrl(REGISTRY_URL);
const data = JSON.parse(body);
const latestVersion = data['dist-tags'].latest;
return latestVersion;
}
catch (e) {
// quietly catch, could have no network connection which is fine
logger.debug(`checkVersion error: ${e}`);
}
return null;
}
async function requestUrl(url) {
return new Promise((resolve, reject) => {
const req = https$1.request(url, res => {
if (res.statusCode > 299) {
reject(`url: ${url}, staus: ${res.statusCode}`);
return;
}
res.once('error', reject);
const ret = [];
res.once('end', () => {
resolve(ret.join(''));
});
res.on('data', data => {
ret.push(data);
});
});
req.once('error', reject);
req.end();
});
}
const REGISTRY_URL = `https://registry.npmjs.org/@stencil/core`;
function requiresCheck(now, lastCheck, checkInterval) {
return ((lastCheck + checkInterval) < now);
}
const CHECK_INTERVAL = (1000 * 60 * 60 * 24 * 7);
function getLastCheck(storage) {
return storage.get(STORAGE_KEY);
}
function setLastCheck(storage) {
return storage.set(STORAGE_KEY, Date.now());
}
const STORAGE_KEY = 'last_version_check';
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var isWindows = process.platform === 'win32';
// JavaScript implementation of realpath, ported from node pre-v6
var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
function rethrow() {
// Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and
// is fairly slow to generate.
var callback;
if (DEBUG) {
var backtrace = new Error;
callback = debugCallback;
} else
callback = missingCallback;
return callback;
function debugCallback(err) {
if (err) {
backtrace.message = err.message;
err = backtrace;
missingCallback(err);
}
}
function missingCallback(err) {
if (err) {
if (process.throwDeprecation)
throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs
else if (!process.noDeprecation) {
var msg = 'fs: missing callback ' + (err.stack || err.message);
if (process.traceDeprecation)
console.trace(msg);
else
console.error(msg);
}
}
}
}
function maybeCallback(cb) {
return typeof cb === 'function' ? cb : rethrow();
}
var normalize = path$2__default.normalize;
// Regexp that finds the next partion of a (partial) path
// result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
if (isWindows) {
var nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
} else {
var nextPartRe = /(.*?)(?:[\/]+|$)/g;
}
// Regex to find the device root, including trailing slash. E.g. 'c:\\'.
if (isWindows) {
var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/