typle
Version:
📦 Scan and install missing Typescript type definitions for your dependencies.
336 lines (298 loc) • 16.8 kB
JavaScript
;Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var __defProp = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty, __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues = exports.__spreadValues = (a, b) => {
for (var prop in b || (b = {}))
__hasOwnProp.call(b, prop) && __defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b))
__propIsEnum.call(b, prop) && __defNormalProp(a, prop, b[prop]);
return a;
};
var __async = (__this, __arguments, generator) => new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}, rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
}, step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
// src/utils/util.ts
var _path = require('path'); var _path2 = _interopRequireDefault(_path);
var _semver = require('semver'); var _semver2 = _interopRequireDefault(_semver);
var _crossspawn = require('cross-spawn'); var _crossspawn2 = _interopRequireDefault(_crossspawn);
// ../../node_modules/.pnpm/is-unicode-supported@2.1.0/node_modules/is-unicode-supported/index.js
var _process = require('process'); var _process2 = _interopRequireDefault(_process);
function isUnicodeSupported() {
let { env } = _process2.default, { TERM, TERM_PROGRAM } = env;
return _process2.default.platform !== "win32" ? TERM !== "linux" : !!env.WT_SESSION || !!env.TERMINUS_SUBLIME || env.ConEmuTask === "{cmd::Cmder}" || TERM_PROGRAM === "Terminus-Sublime" || TERM_PROGRAM === "vscode" || TERM === "xterm-256color" || TERM === "alacritty" || TERM === "rxvt-unicode" || TERM === "rxvt-unicode-256color" || env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
}
// src/utils/util.ts
var _nanospinner = require('nanospinner');
var _typleutil = require('typle-util');
var joincwd = _path2.default.join.bind(void 0, process.cwd()), spinner = _nanospinner.createSpinner.call(void 0, ), allowedPackageManagers = ["npm", "yarn", "pnpm", "bun"], defaultOptions = {
silent: !0,
install: !0,
dryRun: !1,
pkgManager: void 0,
patterns: [],
ignorePackages: [],
ignoreDeps: [],
additionalArgs: []
};
function clearSpinner() {
spinner.stop(), process.stdout.moveCursor(0, -1), process.stdout.write(" ".repeat(process.stdout.columns || 50) + "\r");
}
function niceTryPromise(fn) {
return __async(this, null, function* () {
try {
return yield fn();
} catch (e) {
}
});
}
function getPkgJson() {
return __async(this, null, function* () {
return yield _typleutil.readPkg.call(void 0, _path2.default.join(__dirname, "../package.json"));
});
}
function getVersion() {
return __async(this, null, function* () {
return (yield getPkgJson()).version;
});
}
function cleanSemver(version) {
return _semver2.default.clean(version, { loose: !0 }) || _semver2.default.valid(_semver2.default.coerce(version));
}
function getTypescriptVersion() {
return __async(this, null, function* () {
let pkgJson = (yield niceTryPromise(_typleutil.readPkg)) || {}, localTypescriptVersion = _typleutil.getDependencies.call(void 0, pkgJson).typescript;
return localTypescriptVersion ? cleanSemver(localTypescriptVersion) : new Promise((resolve, reject) => {
var _a;
let proc = _crossspawn2.default.call(void 0, "tsc -v");
(_a = proc.stdout) == null || _a.on("data", (version) => {
resolve(cleanSemver(version.toString())), proc.kill();
}), proc.once("error", reject), proc.once("exit", reject);
});
});
}
function matchVersion(dep, packument) {
return Object.keys(packument.versions).filter((version) => {
try {
return (_semver2.default.satisfies(version, _semver2.default.validRange(dep.version) || "^" + _semver2.default.major(cleanSemver(dep.version) || dep.version), { includePrerelease: !0 }) || _semver2.default.satisfies(version, "^" + _semver2.default.major(cleanSemver(dep.version) || dep.version), { includePrerelease: !0 })) && !("deprecated" in packument.versions[version]);
} catch (e) {
return !1;
}
}).sort((a, b) => _semver2.default.rcompare(a, b))[0];
}
function getUnicode(str, alt = "") {
return isUnicodeSupported() ? str : alt;
}
// src/utils/logger.ts
var _picocolors = require('picocolors'); var _picocolors2 = _interopRequireDefault(_picocolors);
var logger = {}, levels = {
info: _picocolors2.default.cyan("info"),
warn: _picocolors2.default.yellow("warn"),
error: _picocolors2.default.red("error"),
success: _picocolors2.default.bold(_picocolors2.default.green(getUnicode("\u2714", "\u221A")))
};
function log(...msg) {
console.log(...msg);
}
logger.info = (...msg) => {
log(levels.info, ...msg);
};
logger.success = (...msg) => {
log(levels.success, ...msg);
};
logger.warn = (...msg) => {
log(levels.warn, ...msg);
};
logger.error = (...msg) => {
log(levels.error, ...msg);
};
var logger_default = logger;
// src/cli/runner.ts
var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);
var _tinyglobby = require('tinyglobby');
// src/scanner.ts
var _detectindent = require('detect-indent'); var _detectindent2 = _interopRequireDefault(_detectindent);
var _installpkg = require('@antfu/install-pkg');
var _typlecore = require('typle-core');
// src/utils/session.ts
var session = {
install_count: 0
};
// src/utils/generate-list.ts
function generateList(pkgs, filepath) {
let list = `${" ".repeat(process.stdout.columns || 30)}
${getUnicode("\u{1F4E6} ")}typle ${_picocolors2.default.gray(_picocolors2.default.italic("- " + filepath))} ${_picocolors2.default.italic(`(added ${pkgs.length} package${pkgs.length > 1 ? "s" : ""})`)}`;
return pkgs.forEach((pkg, i) => {
let c = getUnicode(i === pkgs.length - 1 ? "\u2514\u2574" : "\u251C\u2574", "- ");
list += `
` + _picocolors2.default.white(c) + _picocolors2.default.gray(_typleutil.TYPES_PREFIX) + _picocolors2.default.blue(_picocolors2.default.bold(pkg.replace(_typleutil.TYPES_PREFIX, "")));
}), list + `
`;
}
// src/scanner.ts
var { exit } = process, pkgCwd = joincwd("package.json");
function scan() {
return __async(this, arguments, function* (pkgPath = pkgCwd, tsTag = "latest", options) {
let cwd = _path2.default.resolve(pkgPath), pkgDir = _path2.default.relative(process.cwd(), cwd), prettyPkgPath = cwd === pkgCwd ? "" : _picocolors2.default.gray(_picocolors2.default.italic(" (" + pkgDir + ")"));
spinner.start({ text: `scanning ${cwd === pkgCwd ? _picocolors2.default.blue("package.json") : _picocolors2.default.blue(pkgDir)} for typings\r`, color: "blue" });
let pkgJson = yield _typleutil.readPkg.call(void 0, pkgPath), types = [], libraries = [];
try {
types.push(...yield _typlecore.filterTypes.call(void 0, pkgJson, cwd));
} catch (error) {
logger_default.error(error.message), exit(1);
}
if (yield Promise.all(
types.map((lib) => __async(this, null, function* () {
if (options.ignorePackages.includes(lib.name) || options.ignoreDeps.some((deps) => {
deps === "deps" && (deps = "dependencies");
let pkgEl = pkgJson[deps] || pkgJson[deps + "Dependencies"];
return pkgEl == null ? void 0 : pkgEl[lib.name];
})) return;
let dtlib = _typleutil.convertToTypes.call(void 0, lib.name), packument = yield _typlecore.fetchPackage.call(void 0, dtlib);
if (!packument) {
logger_default.warn(_picocolors2.default.bold(lib.name), "doesn't provide any type definitions");
return;
}
let tags = packument["dist-tags"], version = matchVersion(lib, packument) || tsTag && tags[tsTag] || tags.latest;
if (!version || !packument.versions[version]) {
logger_default.error(`No valid release tag found for ${packument.name}`);
return;
}
let pkg = packument.versions[version];
libraries.push(pkg);
}))
), clearSpinner(), !libraries.length) {
logger_default.info("no typings to add" + prettyPkgPath);
return;
}
if (console.log(
generateList(libraries.map(({ name }) => name).sort(), cwd === pkgCwd ? "package.json" : pkgDir)
), options.dryRun) return;
let pkgManager = options.pkgManager || ((yield _installpkg.detectPackageManager.call(void 0, cwd)) || "npm").split("@")[0], installCmd = pkgManager === "yarn" ? "add" : "install";
if (options.install) {
let pkgs = libraries.map((pkg) => pkg.name.trim() + "@^" + pkg.version.trim()), additionalArgs = options.additionalArgs;
Object.keys(options).filter((option) => !Object.keys(defaultOptions).includes(option)).forEach((option) => {
let opt = options[option];
Array.isArray(opt) || (additionalArgs.push("--" + option), /^(true|false)$/i.test(opt) || additionalArgs.push(opt));
});
let cmd = `${pkgManager} ${installCmd} --save-dev ${pkgs.join(" ")} ${additionalArgs.join(" ")}`;
logger_default.info(`$ ${cmd}`), options.silent && spinner.start({ text: `installing ${_picocolors2.default.cyan(pkgs.length + " package" + (pkgs.length > 1 ? "s" : ""))} via ${pkgManager}\r`, color: "cyan" });
try {
yield _installpkg.installPackage.call(void 0, pkgs, { dev: !0, silent: options.silent, additionalArgs, cwd: _path2.default.dirname(cwd), packageManager: pkgManager });
} catch (e) {
logger_default.error("Something went wrong while installing dependencies. Try running the following command yourself:", _picocolors2.default.gray(cmd)), exit(1);
}
options.silent && clearSpinner();
} else {
pkgJson.devDependencies = pkgJson.devDependencies || {}, libraries.forEach((lib) => {
pkgJson.devDependencies[lib.name] = `^${lib.version}`;
}), pkgJson.devDependencies = Object.fromEntries(Object.keys(pkgJson.devDependencies).sort().map((key) => [key, pkgJson.devDependencies[key]]));
let indent = _detectindent2.default.call(void 0, yield _fs2.default.promises.readFile(pkgPath, "utf8")).amount || 2;
yield _fs2.default.promises.writeFile(pkgPath, JSON.stringify(pkgJson, void 0, indent), "utf8"), logger_default.info("successfully updated package.json"), logger_default.info(`run ${_picocolors2.default.cyan(`${pkgManager} ${installCmd}`)} to install newly added packages`);
}
session.install_count += libraries.length;
});
}
// src/updater.ts
var _tinyupdatenotifier = require('tiny-update-notifier'); var _tinyupdatenotifier2 = _interopRequireDefault(_tinyupdatenotifier);
function updater() {
return __async(this, null, function* () {
let pkg = yield getPkgJson();
try {
let update = yield _tinyupdatenotifier2.default.call(void 0, { pkg });
update && logger_default.info(`update available: ${_picocolors2.default.gray(update.current)} ${getUnicode("\u2192", "->")} ${_picocolors2.default.green(update.latest)} (${update.type})`);
} catch (e) {
logger_default.warn("couldn't fetch new updates");
}
});
}
// src/cli/runner.ts
var { exit: exit2 } = process;
function run() {
return __async(this, arguments, function* (options_ = {}) {
var _a;
let options = __spreadValues(__spreadValues({}, defaultOptions), options_), start = Date.now(), typescriptVersion = yield niceTryPromise(getTypescriptVersion), tsTag = typescriptVersion ? "ts" + _semver2.default.major(typescriptVersion) + "." + _semver2.default.minor(typescriptVersion) : void 0;
typescriptVersion ? logger_default.info("typescript: v" + typescriptVersion) : logger_default.warn("couldn't find any typescript version, is it installed?"), options.pkgManager && !allowedPackageManagers.includes(options.pkgManager) && (logger_default.warn(
_picocolors2.default.bold(options.pkgManager),
"is not a valid or supported package manager",
_picocolors2.default.gray(_picocolors2.default.italic(`(supported: ${_picocolors2.default.bold("npm")}, ${_picocolors2.default.bold("yarn")}, ${_picocolors2.default.bold("pnpm")} and ${_picocolors2.default.bold("bun")})`))
), delete options.pkgManager), yield updater();
let pkgPath = joincwd("package.json");
if (!((_a = options.patterns) != null && _a.length))
_fs2.default.existsSync(pkgPath) || (logger_default.error("couldn't find 'package.json' in this directory"), exit2(1)), yield scan(pkgPath, tsTag, options);
else {
let files = yield _tinyglobby.glob.call(void 0, options.patterns, { dot: !0, absolute: !0 });
if (!files.length) {
logger_default.info("no matching patterns found");
return;
}
logger_default.info(`found ${files.length} matching patterns`);
for (let file of files) {
let pkgPath2 = _path2.default.join(file, "package.json");
if (!_fs2.default.existsSync(pkgPath2)) {
logger_default.warn("couldn't find 'package.json' in ", _path2.default.dirname(pkgPath2));
return;
}
yield scan(pkgPath2, tsTag, options);
}
}
options.dryRun && logger_default.info(`no changes made ${_picocolors2.default.gray(_picocolors2.default.italic("(--dry-run)"))}`);
let time = ((Date.now() - start) / 1e3).toFixed(1) + "s";
session.install_count ? logger_default.success(`added ${session.install_count} new typings in ${time}`) : logger_default.success(`no typings added in ${time}`);
});
}
// src/cli/installer.ts
function install(_0) {
return __async(this, arguments, function* (libs, options = {}) {
_fs2.default.existsSync(joincwd("package.json")) || (logger_default.error("could't find 'package.json' in this directory"), process.exit(1));
let args = options, additionalArgs = [];
Object.keys(args).forEach((arg) => {
let opt = args[arg];
Array.isArray(opt) || (additionalArgs.push("--" + arg), /^(true|false)$/i.test(opt) || additionalArgs.push(opt));
});
let typescriptVersion = yield niceTryPromise(getTypescriptVersion), tsTag = typescriptVersion && "ts" + _semver2.default.major(typescriptVersion) + "." + _semver2.default.minor(typescriptVersion);
typescriptVersion ? logger_default.info("typescript: v" + typescriptVersion) : logger_default.warn("couldn't find any typescript version, is it installed?"), options.pkgManager && !allowedPackageManagers.includes(options.pkgManager) && (logger_default.warn(
options.pkgManager,
"is not a valid or supported package manager",
_picocolors2.default.gray(_picocolors2.default.italic(`(we only support ${_picocolors2.default.underline("npm")} ${_picocolors2.default.underline("yarn")} ${_picocolors2.default.underline("pnpm")} and ${_picocolors2.default.underline("bun")})`))
), delete options.pkgManager), logger_default.warn("this feature is experimental"), yield updater(), logger_default.info("installing libraries"), yield _installpkg.installPackage.call(void 0, libs, { additionalArgs });
let libraries = [];
yield Promise.all(
libs.map((lib) => __async(this, null, function* () {
let lastindex = lib.lastIndexOf("@");
lastindex !== -1 && (lib = lib.slice(0, Math.max(0, lastindex)));
try {
if (yield _typlecore.hasOwnTypes.call(void 0, lib)) return;
} catch (error) {
logger_default.error(error.message), process.exit(1);
}
let dtlib = _typleutil.convertToTypes.call(void 0, lib), packument = yield _typlecore.fetchPackage.call(void 0, dtlib);
if (!packument) {
logger_default.warn(lib, "doesn't provide any type definitions");
return;
}
let tags = packument["dist-tags"], tag = tsTag && tags[tsTag] || tags.latest;
if (!tag || !packument.versions[tag]) {
logger_default.error(`No valid release tag found for ${packument.name}`);
return;
}
let pkg = packument.versions[tag];
libraries.push(pkg);
}))
), libraries.length && (logger_default.info("installing types"), yield _installpkg.installPackage.call(void 0, libraries.map((lib) => lib.name + "@^" + lib.version), { dev: !0, additionalArgs }));
});
}
exports.__spreadValues = __spreadValues; exports.__async = __async; exports.joincwd = joincwd; exports.getVersion = getVersion; exports.logger_default = logger_default; exports.run = run; exports.install = install;