UNPKG

kotori-bot

Version:

Cross-platform chatbot framework base on Node.js and TypeScript

215 lines (214 loc) 8.58 kB
/** * @Package kotori-bot * @Version 1.7.0 * @Author Arimura Sena <me@hotaru.icu> * @Copyright 2024-2025 Hotaru. All rights reserved. * @License BAN-ZHINESE-USING * @Link https://github.com/kotorijs/kotori * @Date 17:26:14 */ "use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var build_exports = {}; __export(build_exports, { default: () => build }); module.exports = __toCommonJS(build_exports); var import_get_packages = require("@manypkg/get-packages"); var import_shelljs = __toESM(require("shelljs")); var import_node_path = __toESM(require("node:path")); var import_node_fs = require("node:fs"); var import_node_events = require("node:events"); var import_common = require("./common"); var import_picomatch = require("picomatch"); var BuildType = /* @__PURE__ */ ((BuildType2) => { BuildType2[BuildType2["Tsup"] = 0] = "Tsup"; BuildType2[BuildType2["ReScript"] = 1] = "ReScript"; BuildType2[BuildType2["None"] = 2] = "None"; return BuildType2; })(BuildType || {}); const state = { succeed: 0, failed: 0 }; const defaultConfig = { buildOptions: { "*": { clean: true, // dts: true, entryPoints: ["./src"], bundle: false // format: ['cjs', 'esm'], // target: 'es2020', // sourcemap: true, } }, banner: "", include: [], exclude: [], ignoreError: false, types: false, onlyTypes: false, silent: false }; function generateBanner(template, pkg) { return Object.entries({ name: pkg.name ?? "", version: pkg.version ?? "", author: Array.isArray(pkg.author) ? pkg.author.join(", ") : pkg.author ?? "", license: pkg.license ?? "BAN-ZHINESE-USING", date: (/* @__PURE__ */ new Date()).toLocaleTimeString() }).reduce((acc, [key, value]) => acc.replaceAll(`%${key}%`, value), template); } function getBuildType(pkg, config) { const hasRescript = (0, import_node_fs.existsSync)(import_node_path.default.join(pkg.dir, "rescript.json")); if (hasRescript) { return config.include.some((pattern) => (0, import_picomatch.isMatch)(pattern, pkg.packageJson.name)) ? 0 /* Tsup */ : 1 /* ReScript */; } return config.exclude.some((pattern) => (0, import_picomatch.isMatch)(pattern, pkg.packageJson.name)) ? 2 /* None */ : 0 /* Tsup */; } function getBuildConfig(pkg, config) { const baseConfig = config.buildOptions["*"] || {}; const [tsconfig, _] = ["tsconfig.json", "package.json"].map((file) => { const filepath = import_node_path.default.join(pkg.dir, file); if (!(0, import_node_fs.existsSync)(filepath)) return {}; const str = (0, import_node_fs.readFileSync)(filepath, "utf-8"); try { return JSON.parse(str); } catch (e) { throw new Error(`Parse Error at ${filepath}: ${String(e)}`); } }); const pkgConfig = { outDir: tsconfig?.compilerOptions?.outDir ?? "./dist", banner: { // biome-ignore lint: js: generateBanner(config.banner, pkg.packageJson) } }; const matchingConfigs = Object.entries(config.buildOptions).filter(([pattern]) => pattern !== "*" && (0, import_picomatch.isMatch)(pattern, pkg.packageJson.name)).map(([, config2]) => config2); const options = { ...baseConfig, ...pkgConfig, ...matchingConfigs }; return options; } async function buildPackageByTsup(pkg, config) { import_shelljs.default.cd(pkg.dir); const tsupFile = import_node_path.default.resolve(import_common.CWD, "tsup.config.json"); try { const cfg = getBuildConfig(pkg, config); if (cfg.outDir && (0, import_node_fs.existsSync)(cfg.outDir)) (0, import_node_fs.rmSync)(cfg.outDir, { recursive: true }); (0, import_node_fs.writeFileSync)(tsupFile, JSON.stringify(cfg, null, 2)); if (!config.onlyTypes && import_shelljs.default.exec("pnpm exec tsup", { silent: config.silent }).code !== 0) { throw new Error(`Failed to build ${pkg.packageJson.name}`); } const isMainPack = pkg.packageJson.name === "kotori-bot"; if ((config.types || config.onlyTypes) && (!pkg.dir.includes("packages") || isMainPack)) { const child = import_shelljs.default.exec("tsc --build", {}, () => { }); if (!config.silent) process.stdin.on("data", (data) => child.stdin?.write(data)); await new Promise( (resolve, reject) => child.on( "exit", (code) => code === 0 ? resolve(null) : reject(new Error(`Failed to build ${pkg.packageJson.name} types`)) ) ); } state.succeed += 1; } catch (err) { state.failed += 1; console.error(err); if (!config.ignoreError) import_shelljs.default.exit(1); } finally { if ((0, import_node_fs.existsSync)(tsupFile)) (0, import_node_fs.rmSync)(tsupFile); import_shelljs.default.cd(import_common.CWD); } } async function buildPackageByReScript(pkg, config) { import_shelljs.default.cd(pkg.dir); try { if (import_shelljs.default.exec("pnpm exec rescript", { silent: config.silent }).code !== 0) { throw new Error(`Failed to build ${pkg.packageJson.name} with rescript`); } state.succeed += 1; } catch (err) { state.failed += 1; console.error(err); if (!config.ignoreError) import_shelljs.default.exit(1); } finally { import_shelljs.default.cd(import_common.CWD); } } async function build(initConfig, filters) { const start = Date.now(); try { (0, import_common.ensureWorkspaceRoot)(); const config = { ...defaultConfig, ...initConfig, buildOptions: { ...defaultConfig.buildOptions, ...initConfig.buildOptions } }; if (config.silent) globalThis.console.log = () => { }; const pkgs = /* @__PURE__ */ ((pkgs2) => pkgs2)((0, import_get_packages.getPackagesSync)(import_common.CWD).packages.filter((pkg) => (0, import_common.matchesFilter)(pkg, filters))); if (pkgs.length === 0) { console.log("No packages matched the filter criteria"); return; } if (config.onlyTypes || config.types) { pkgs.map((pkg) => import_node_path.default.join(pkg.dir, "tsconfig.tsbuildinfo")).filter(import_node_fs.existsSync).map((file) => (0, import_node_fs.rmSync)(file)); } console.log(`Building ${pkgs.length} packages...`); (0, import_node_events.setMaxListeners)(Number.POSITIVE_INFINITY); await Promise.all( pkgs.map((pkg) => { switch (getBuildType(pkg, config)) { case 0 /* Tsup */: console.log(`Building ${pkg.packageJson.name} ...`); return buildPackageByTsup(pkg, config); case 1 /* ReScript */: if (config.onlyTypes) { console.log(`Skiped to build ${pkg.packageJson.name} with rescript`); return; } console.log(`Building ${pkg.packageJson.name} with rescript...`); return buildPackageByReScript(pkg, config); default: console.log(`Skipping ${pkg.packageJson.name}...`); return Promise.resolve(); } }) ); console.log( `Build summary: ${state.succeed} succeed, ${state.failed} failed, ${pkgs.length - state.succeed - state.failed} skipped, in ${(Date.now() - start) / 1e3}s.` ); import_shelljs.default.exit(0); } catch (error) { console.error("Build failed:", error); import_shelljs.default.exit(1); } }