UNPKG

radashi-helper

Version:
188 lines (182 loc) 5.9 kB
import { dedent } from "./chunk-V32CUL4H.js"; import { isBabelNode, loadRewired, require_lib, rewire } from "./chunk-OCHPTCP5.js"; import { findSources } from "./chunk-652CQLOF.js"; import { debug } from "./chunk-DSXY7YVB.js"; import { __toESM, flat, select, traverse } from "./chunk-VOEQFXI5.js"; // src/util/generateUmbrella.ts import { existsSync } from "node:fs"; import { join as join2, relative } from "node:path"; // src/rewired/updateRewired.ts import { copyFile } from "node:fs/promises"; import { join } from "node:path"; async function updateRewired(env) { const prevRewired = await loadRewired(env); if (prevRewired.length) { debug(`Updating ${prevRewired.length} rewired files...`); await Promise.all( prevRewired.map(async (funcPath) => { await rewire(funcPath, env); }) ); await copyFile( join(env.root, "overrides/src/tsconfig.json"), join(env.root, "overrides/rewired/tsconfig.json") ); } } // src/util/exports.ts var import_parser = __toESM(require_lib(), 1); import { readFileSync } from "node:fs"; function printExports(options) { const names = options.names.concat(options.types.map((name) => `type ${name}`)); return `export { ${names.join(", ")} } from '${options.from}'`; } function extractExports(file, options = {}) { const typesOption = options.types ?? true; let fileContents; try { fileContents = readFileSync(file, "utf8"); } catch { return []; } const parseResult = (0, import_parser.parse)(fileContents, { plugins: [["typescript", { dts: file.endsWith(".d.ts") }]], sourceType: "module", sourceFilename: file }); const names = /* @__PURE__ */ new Set(); const { program } = parseResult; function isAllowed(node) { return typesOption !== "only" && (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration" || node.type === "ExportSpecifier" && node.exportKind !== "type") || typesOption !== false && (node.type === "TSInterfaceDeclaration" || node.type === "TSTypeAliasDeclaration" || node.type === "ExportSpecifier" && node.exportKind === "type"); } traverse(program, (node, _key, _parent, context) => { if (isBabelNode(node)) { context.skip(); if (node.type === "ExportNamedDeclaration") { if (node.declaration) { if (node.declaration.type === "VariableDeclaration") { if (typesOption === "only") { return; } for (const declarator of node.declaration.declarations) { if (declarator.id.type === "Identifier") { names.add(declarator.id.name); } } } else if (isAllowed(node.declaration)) { if (node.declaration.id && node.declaration.id.type === "Identifier") { names.add(node.declaration.id.name); } } } else if (node.specifiers) { for (const specifier of node.specifiers) { if (specifier.type === "ExportSpecifier") { if (isAllowed(specifier)) { names.add(specifier.exported.name); } } } } } else if (node.type === "ExportDefaultDeclaration") { if (typesOption !== "only") { names.add("default"); } } } }); return Array.from(names).sort(); } // src/util/generateUmbrella.ts async function generateUmbrella(env) { await updateRewired(env); const typesPath = join2(env.root, "src/types.ts"); const overrideTypesPath = join2(env.root, "overrides/src/types.ts"); const pathsInside = await findSources(env); const namesBlocked = flat(Object.values(pathsInside)).concat(typesPath, overrideTypesPath).flatMap((sourcePath) => { return extractExports(sourcePath); }); const filterBlockedNames = (exportName) => !namesBlocked.includes(exportName); const upstreamPath = join2(env.root, "node_modules/radashi/dist/radashi.d.ts"); const upstreamTypes = extractExports(upstreamPath, { types: "only" }).filter( filterBlockedNames ); const upstreamExports = extractExports(upstreamPath).filter(filterBlockedNames); let code = printExports({ from: "./node_modules/radashi/dist/radashi", names: upstreamExports.filter((name) => !upstreamTypes.includes(name)), types: upstreamTypes }); const srcExports = printLocalExports(pathsInside.src, env); if (srcExports.length) { code += dedent` \n // Our custom functions. ${srcExports} `; } const overrideExports = printLocalExports(pathsInside.overrides, env); if (overrideExports.length) { code += dedent` \n // Our overrides. ${overrideExports} `; } const userTypeExports = existsSync(typesPath) ? printLocalExports([typesPath], env) : void 0; const overrideTypeExports = existsSync(overrideTypesPath) ? printLocalExports([overrideTypesPath], env) : void 0; if (userTypeExports?.length || overrideTypeExports?.length) { code += dedent` \n // Our types.\n `; if (overrideTypeExports?.length) { code += overrideTypeExports; } if (userTypeExports?.length) { code += userTypeExports; } } const rewiredExports = printLocalExports(pathsInside.rewired, env); if (rewiredExports.length) { code += dedent` \n // Rewired to use our overrides. ${rewiredExports} `; } return code + "\n"; } function printLocalExports(files, env) { return select( files.map((file) => ({ file, exports: extractExports(file), types: extractExports(file, { types: "only" }) })), (mod) => printExports({ from: "./" + relative(env.root, mod.file), names: mod.exports.filter((name) => !mod.types.includes(name)), types: mod.types }), (mod) => mod.exports.length > 0 ).join("\n"); } export { generateUmbrella };