UNPKG

tshy

Version:

TypeScript HYbridizer - Hybrid (CommonJS/ESM) TypeScript node package builder

185 lines 7.14 kB
import { relative, resolve } from 'node:path/posix'; import config from './config.js'; import dialects from './dialects.js'; import fail from './fail.js'; import pkg from './package.js'; import polyfills from './polyfills.js'; import { resolveExport } from './resolve-export.js'; const { esmDialects = [], commonjsDialects = [] } = config; const liveDev = config.liveDev && process.env.npm_command !== 'publish' && process.env.npm_command !== 'pack'; const getTargetForDialectCondition = (s, dialect, condition, type, polyfills = new Map()) => { if (s === undefined) return undefined; if (typeof s === 'string') { // the excluded filename pattern const xts = type === 'commonjs' ? '.mts' : '.cts'; if (s.endsWith(xts)) return undefined; const pf = dialect === 'commonjs' ? 'cjs' : dialect; const rel = relative(resolve('./src'), resolve(polyfills.get(pf)?.map.get(s) ?? s)); const target = liveDev ? rel : rel.replace(/\.([mc]?)tsx?$/, '.$1js'); return (!s || !s.startsWith('./src/') ? s : dialects.includes(type) ? `./dist/${dialect}/${target}` : undefined); } return resolveExport(s, [condition]); }; export const getImpTarget = (s, polyfills = new Map()) => getTargetForDialectCondition(s, 'esm', 'import', 'esm', polyfills); export const getReqTarget = (s, polyfills = new Map()) => getTargetForDialectCondition(s, 'commonjs', 'require', 'commonjs', polyfills); const getExports = (c, pkgType) => { // by this time it always exports, will get the default if missing /* c8 ignore start */ if (!c.exports) { fail('no exports on tshy config (is there code in ./src?)'); return process.exit(1); } /* c8 ignore stop */ const e = {}; for (const [sub, s] of Object.entries(c.exports)) { // external export, not built by us if (s !== null && (typeof s !== 'string' || !s.startsWith('./src/'))) { // already been validated, just accept as-is e[sub] = s; continue; } /* c8 ignore next - already guarded */ if (s === null) continue; const impTarget = getImpTarget(s, polyfills); const reqTarget = getReqTarget(s, polyfills); // should be impossible /* c8 ignore start */ if (!impTarget && !reqTarget) continue; /* c8 ignore stop */ const exp = (e[sub] = {}); if (impTarget) { for (const d of esmDialects) { const source = s && (polyfills.get(d)?.map.get(s) ?? s); const target = getTargetForDialectCondition(s, d, d, 'esm', polyfills); if (target) { exp[d] = liveDev ? { ...(pkgType === 'commonjs' ? getSourceDialects(source, c) : {}), default: target, } : { ...(pkgType === 'commonjs' ? getSourceDialects(source, c) : {}), types: target.replace(/\.js$/, '.d.ts'), default: target, }; } } } if (reqTarget) { for (const d of commonjsDialects) { const source = s && (polyfills.get(d)?.map.get(s) ?? s); const target = getTargetForDialectCondition(s, d, d, 'commonjs', polyfills); if (target) { exp[d] = liveDev ? { ...(pkgType === 'module' ? getSourceDialects(source, c) : {}), default: target, } : { ...(pkgType === 'module' ? getSourceDialects(source, c) : {}), types: target.replace(/\.js$/, '.d.ts'), default: target, }; } } } // put the default import/require after all the other special ones. if (impTarget) { exp.import = liveDev ? { ...(pkgType === 'module' ? getSourceDialects(s, c) : {}), default: impTarget, } : { ...(pkgType === 'module' ? getSourceDialects(s, c) : {}), types: impTarget.replace(/\.(m?)js$/, '.d.$1ts'), default: impTarget, }; } if (reqTarget) { exp.require = liveDev ? { ...(pkgType === 'commonjs' ? getSourceDialects(s, c) : {}), default: reqTarget, } : { ...(pkgType === 'commonjs' ? getSourceDialects(s, c) : {}), types: reqTarget.replace(/\.(c?)js$/, '.d.$1ts'), default: reqTarget, }; } } return e; }; const getSourceDialects = (source, c) => { const { sourceDialects } = c; if (!sourceDialects) return {}; return Object.fromEntries(sourceDialects.map(s => [s, source])); }; export const setMain = (c, pkg) => { pkg.type = pkg.type === 'commonjs' ? 'commonjs' : 'module'; const mod = resolveExport(pkg.exports['.'], ['require']); const main = c?.main ?? !!mod; if (main) { if (!mod) { fail(`could not resolve exports['.'] for tshy.main 'require'`); return process.exit(1); } const types = resolveExport(pkg.exports['.'], [ 'require', 'types', ]); pkg.main = mod; if (types && types !== mod) pkg.types = types; else delete pkg.types; } else { if (c && c.main !== false) delete c.main; delete pkg.main; delete pkg.types; } // Set the package module to exports["."] const importMod = resolveExport(pkg.exports['.'], ['import']); const module = c?.module ?? !!importMod; if (module) { if (!importMod) { fail(`could not resolve exports['.'] for tshy.module 'import'`); return process.exit(1); } pkg.module = importMod; } else { if (c && c.module !== false) delete c.module; delete pkg.module; } }; pkg.exports = getExports(config, pkg.type); setMain(config, pkg); export default pkg.exports; //# sourceMappingURL=exports.js.map