UNPKG

typle

Version:

📦 Scan and install missing Typescript type definitions for your dependencies.

342 lines (327 loc) • 15.7 kB
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 = (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()); }); // ../../node_modules/.pnpm/tsup@8.3.0_jiti@1.21.6_postcss@8.4.31_typescript@5.6.2/node_modules/tsup/assets/esm_shims.js import { fileURLToPath } from "url"; import path from "path"; var import_meta = {}, getFilename = () => fileURLToPath(import_meta.url), getDirname = () => path.dirname(getFilename()), __dirname = /* @__PURE__ */ getDirname(), __filename = /* @__PURE__ */ getFilename(); // src/utils/util.ts import path2 from "node:path"; import semver from "semver"; import spawn from "cross-spawn"; // ../../node_modules/.pnpm/is-unicode-supported@2.1.0/node_modules/is-unicode-supported/index.js import process2 from "node:process"; function isUnicodeSupported() { let { env } = process2, { TERM, TERM_PROGRAM } = env; return process2.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 import { createSpinner } from "nanospinner"; import { getDependencies, readPkg } from "typle-util"; var joincwd = path2.join.bind(void 0, process.cwd()), spinner = createSpinner(), 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 readPkg(path2.join(__dirname, "../package.json")); }); } function getVersion() { return __async(this, null, function* () { return (yield getPkgJson()).version; }); } function cleanSemver(version) { return semver.clean(version, { loose: !0 }) || semver.valid(semver.coerce(version)); } function getTypescriptVersion() { return __async(this, null, function* () { let pkgJson = (yield niceTryPromise(readPkg)) || {}, localTypescriptVersion = getDependencies(pkgJson).typescript; return localTypescriptVersion ? cleanSemver(localTypescriptVersion) : new Promise((resolve, reject) => { var _a; let proc = spawn("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 (semver.satisfies(version, semver.validRange(dep.version) || "^" + semver.major(cleanSemver(dep.version) || dep.version), { includePrerelease: !0 }) || semver.satisfies(version, "^" + semver.major(cleanSemver(dep.version) || dep.version), { includePrerelease: !0 })) && !("deprecated" in packument.versions[version]); } catch (e) { return !1; } }).sort((a, b) => semver.rcompare(a, b))[0]; } function getUnicode(str, alt = "") { return isUnicodeSupported() ? str : alt; } // src/utils/logger.ts import pc from "picocolors"; var logger = {}, levels = { info: pc.cyan("info"), warn: pc.yellow("warn"), error: pc.red("error"), success: pc.bold(pc.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 import fs2 from "node:fs"; import path4 from "node:path"; import semver2 from "semver"; import pc5 from "picocolors"; import { glob } from "tinyglobby"; // src/scanner.ts import fs from "node:fs"; import path3 from "node:path"; import pc3 from "picocolors"; import detectIndent from "detect-indent"; import { detectPackageManager, installPackage } from "@antfu/install-pkg"; import { convertToTypes, readPkg as readPkg2 } from "typle-util"; import { fetchPackage, filterTypes } from "typle-core"; // src/utils/session.ts var session = { install_count: 0 }; // src/utils/generate-list.ts import pc2 from "picocolors"; import { TYPES_PREFIX } from "typle-util"; function generateList(pkgs, filepath) { let list = `${" ".repeat(process.stdout.columns || 30)} ${getUnicode("\u{1F4E6} ")}typle ${pc2.gray(pc2.italic("- " + filepath))} ${pc2.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 += ` ` + pc2.white(c) + pc2.gray(TYPES_PREFIX) + pc2.blue(pc2.bold(pkg.replace(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 = path3.resolve(pkgPath), pkgDir = path3.relative(process.cwd(), cwd), prettyPkgPath = cwd === pkgCwd ? "" : pc3.gray(pc3.italic(" (" + pkgDir + ")")); spinner.start({ text: `scanning ${cwd === pkgCwd ? pc3.blue("package.json") : pc3.blue(pkgDir)} for typings\r`, color: "blue" }); let pkgJson = yield readPkg2(pkgPath), types = [], libraries = []; try { types.push(...yield filterTypes(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 = convertToTypes(lib.name), packument = yield fetchPackage(dtlib); if (!packument) { logger_default.warn(pc3.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 detectPackageManager(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 ${pc3.cyan(pkgs.length + " package" + (pkgs.length > 1 ? "s" : ""))} via ${pkgManager}\r`, color: "cyan" }); try { yield installPackage(pkgs, { dev: !0, silent: options.silent, additionalArgs, cwd: path3.dirname(cwd), packageManager: pkgManager }); } catch (e) { logger_default.error("Something went wrong while installing dependencies. Try running the following command yourself:", pc3.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 = detectIndent(yield fs.promises.readFile(pkgPath, "utf8")).amount || 2; yield fs.promises.writeFile(pkgPath, JSON.stringify(pkgJson, void 0, indent), "utf8"), logger_default.info("successfully updated package.json"), logger_default.info(`run ${pc3.cyan(`${pkgManager} ${installCmd}`)} to install newly added packages`); } session.install_count += libraries.length; }); } // src/updater.ts import updateNotifier from "tiny-update-notifier"; import pc4 from "picocolors"; function updater() { return __async(this, null, function* () { let pkg = yield getPkgJson(); try { let update = yield updateNotifier({ pkg }); update && logger_default.info(`update available: ${pc4.gray(update.current)} ${getUnicode("\u2192", "->")} ${pc4.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.major(typescriptVersion) + "." + semver2.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( pc5.bold(options.pkgManager), "is not a valid or supported package manager", pc5.gray(pc5.italic(`(supported: ${pc5.bold("npm")}, ${pc5.bold("yarn")}, ${pc5.bold("pnpm")} and ${pc5.bold("bun")})`)) ), delete options.pkgManager), yield updater(); let pkgPath = joincwd("package.json"); if (!((_a = options.patterns) != null && _a.length)) fs2.existsSync(pkgPath) || (logger_default.error("couldn't find 'package.json' in this directory"), exit2(1)), yield scan(pkgPath, tsTag, options); else { let files = yield glob(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 = path4.join(file, "package.json"); if (!fs2.existsSync(pkgPath2)) { logger_default.warn("couldn't find 'package.json' in ", path4.dirname(pkgPath2)); return; } yield scan(pkgPath2, tsTag, options); } } options.dryRun && logger_default.info(`no changes made ${pc5.gray(pc5.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 import fs3 from "node:fs"; import semver3 from "semver"; import pc6 from "picocolors"; import { installPackage as installPackage2 } from "@antfu/install-pkg"; import { convertToTypes as convertToTypes2 } from "typle-util"; import { fetchPackage as fetchPackage2, hasOwnTypes } from "typle-core"; function install(_0) { return __async(this, arguments, function* (libs, options = {}) { fs3.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" + semver3.major(typescriptVersion) + "." + semver3.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", pc6.gray(pc6.italic(`(we only support ${pc6.underline("npm")} ${pc6.underline("yarn")} ${pc6.underline("pnpm")} and ${pc6.underline("bun")})`)) ), delete options.pkgManager), logger_default.warn("this feature is experimental"), yield updater(), logger_default.info("installing libraries"), yield installPackage2(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 hasOwnTypes(lib)) return; } catch (error) { logger_default.error(error.message), process.exit(1); } let dtlib = convertToTypes2(lib), packument = yield fetchPackage2(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 installPackage2(libraries.map((lib) => lib.name + "@^" + lib.version), { dev: !0, additionalArgs })); }); } export { __spreadValues, __async, __filename, joincwd, getVersion, logger_default, run, install };