UNPKG

@stencil/core

Version:

A Compiler for Web Components and Progressive Web Apps

1,539 lines (1,475 loc) 1.26 MB
'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}[^\\\/