warp-drive
Version:
WarpDrive is the data framework for ambitious web applications
245 lines (235 loc) • 7.42 kB
JavaScript
import chalk from 'chalk';
import fs from 'fs';
import path from 'path';
import { a as getInfo, e as exec } from './warp-drive-pO7pDWOi.js';
function adjustForWords(str, max_length) {
// The string iterator that is used here iterates over characters,
// not mere code units
let count = 0;
let len = 0;
let lastWhitespaceLen = 0;
let isColorChar = false;
let isMaybeStartingWhitespace = true;
// color chars follow the pattern
// \u001b[<number>m
for (const char of str) {
const charIndex = len;
len++;
if (isMaybeStartingWhitespace) {
if (char === ' ' || char === '\t') {
// increment len but not count
lastWhitespaceLen = charIndex;
continue;
} else {
isMaybeStartingWhitespace = false;
}
}
if (isColorChar && char === 'm') {
isColorChar = false;
} else if (char === '\u001b') {
isColorChar = true;
} else if (!isColorChar) {
count++;
if (count > max_length) {
return lastWhitespaceLen;
}
if (char === ' ' || char === '\t') {
lastWhitespaceLen = charIndex;
}
}
}
return len;
}
function indent(str, depth = 1) {
const indentStr = getPadding(depth);
return str.split('\n').map(line => {
return indentStr + line;
}).join('\n');
}
function getPadding(depth, filler = '\t') {
return new Array(depth).fill(filler).join('');
}
function isKeyOf(key, obj) {
return key in obj;
}
/**
* colorizes a string based on color<<>> syntax
* where color is one of the following:
* - gr (grey)
* - bg (brightGreen)
* - bm (brightMagenta)
* - cy (cyan)
* - ye (yellow)
*
* e.g.
*
* color`This is gr<<grey>> and this is bg<<bright green>> and this is bm<<bright magenta>> and this is cy<<cyan>> and this is ye<<yellow>>`
*/
function color(str) {
const colors = {
gr: 'grey',
gb: 'greenBright',
mb: 'magentaBright',
cy: 'cyan',
ye: 'yellow'
};
const colorized = str.replace(/(\w+)<<(.+?)>>/g, (match, possibleColor, text) => {
const c = isKeyOf(possibleColor, colors) ? colors[possibleColor] : null;
if (!c) {
throw new Error(`Unknown color ${possibleColor}`);
}
return chalk[c](text);
});
return colorized;
}
// TODO if the last line of a context is too long we don't always
// end up rebalancing correctly. We need to splice an additional
// line in in this case. If we do this on a rolling basis its
// probably easier.
function rebalanceLines(str, max_length = 75) {
const lines = str.split('\n');
let inContext = false;
let contextIndent = '';
let contextHasBullet = false;
let contextIndex = 0;
let contextBulletIndent = '';
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line === '') {
inContext = false;
continue;
}
if (line.trim() === '---') {
lines[i] = chalk.grey(getPadding(max_length, '-'));
inContext = false;
continue;
}
if (line.trim() === '===') {
lines[i] = chalk.grey(getPadding(max_length, '='));
inContext = false;
continue;
}
const indentMatch = line.match(/^\s+/);
// eslint-disable-next-line no-useless-escape
const hasBullet = line.match(/^\s*[-\*]\s+/) || line.match(/^\s*\d+\)?\.\s+/);
const bulletIndent = hasBullet ? hasBullet[0] : '';
let strIndent = '';
if (indentMatch) {
strIndent = indentMatch[0];
}
// if we have our own bullet, this is a new context
// so nothing can be rebalanced
if (hasBullet || !inContext) {
contextIndex = i;
inContext = true;
contextIndent = strIndent;
contextHasBullet = Boolean(hasBullet);
contextBulletIndent = bulletIndent;
continue;
}
const isBulletContinuation = contextHasBullet && strIndent.startsWith(contextIndent) && strIndent.length === contextBulletIndent.length;
const isNonBulletContinuation = !contextHasBullet && strIndent === contextIndent;
// determine if we match
if (isBulletContinuation || isNonBulletContinuation) {
// we are in the same context
// rebalance if needed
const fullText = lines[contextIndex] + ' ' + line.slice(strIndent.length);
const len = adjustForWords(fullText, max_length);
const prevLine = fullText.slice(0, len).trimEnd();
const thisLine = strIndent + fullText.slice(len).trim();
lines[contextIndex] = prevLine;
lines[i] = thisLine || null;
if (thisLine) {
// only update if we have content on the line
contextIndex = i;
}
} else {
// we are a new context
contextIndex = i;
inContext = true;
contextIndent = strIndent || '';
contextHasBullet = false;
contextBulletIndent = '';
continue;
}
}
return lines.filter(l => l !== null).join('\n');
}
function write(out) {
// eslint-disable-next-line no-console
console.log(out);
}
function getPkgJson() {
const file = fs.readFileSync(path.join(process.cwd(), 'package.json'), {
encoding: 'utf-8'
});
const json = JSON.parse(file);
return json;
}
function writePkgJson(json) {
fs.writeFileSync(path.join(process.cwd(), 'package.json'), JSON.stringify(json, null, 2) + '\n');
}
const pkgJsonCache = {};
function getLocalPkgJson(name, version) {
if (pkgJsonCache[`${name}@${version}`]) {
return pkgJsonCache[`${name}@${version}`];
}
const file = fs.readFileSync(path.join(process.cwd(), 'node_modules', name, 'package.json'), {
encoding: 'utf-8'
});
const json = JSON.parse(file);
pkgJsonCache[`${name}@${json.version}`] = json;
if (json.version === version) {
return json;
}
return null;
}
async function getRemotePkgJson(name, version) {
if (pkgJsonCache[`${name}@${version}`]) {
return pkgJsonCache[`${name}@${version}`];
}
const dir = path.join(process.cwd(), 'tmp');
fs.mkdirSync(dir, {
recursive: true
});
// get the tarball path
const info = await getInfo(`${name}@${version}`);
const remoteTarball = info.dist.tarball;
const tarballName = `${name}-${version}`.replace('/', '_');
// download the package if needed
if (!fs.existsSync(path.join(dir, tarballName, 'package.json'))) {
await exec(`curl -L ${remoteTarball} -o ${tarballName}.tgz`, {
cwd: dir
});
await exec(`tar -xzf ${tarballName}.tgz && mv package ${tarballName}`, {
cwd: dir
});
}
const file = fs.readFileSync(path.join(dir, tarballName, 'package.json'), {
encoding: 'utf-8'
});
const json = JSON.parse(file);
pkgJsonCache[`${name}@${json.version}`] = json;
return json;
}
async function getPkgJsonFor(name, version) {
try {
const pkg = getLocalPkgJson(name, version);
if (pkg) {
return pkg;
}
} catch {
// ignore
}
return getRemotePkgJson(name, version);
}
async function getTypePathFor(name, version) {
const pkg = await getPkgJsonFor(name, version);
const isAlpha = pkg.files?.includes('unstable-preview-types');
const isBeta = pkg.files?.includes('preview-types');
const base = pkg.exports?.['.'];
const isStable = !isAlpha && !isBeta && typeof base === 'object' && base?.['types'] !== undefined;
return isAlpha ? 'unstable-preview-types' : isBeta ? 'preview-types' : isStable ? 'types' : null;
}
export { writePkgJson as a, getTypePathFor as b, color as c, getPkgJson as g, indent as i, rebalanceLines as r, write as w };
//# sourceMappingURL=utils-C3XozAKL.js.map