Files
Robert Fleischmann 22fc59cbf5 fix(types): correct the declarations for CJS and ESM consumers
Three defects, all caught by typechecking a packed tarball from a consumer
project rather than only building in-repo:

The UMD bundle sets module.exports to the constructor itself, an `export =`
shape the generated ESM declarations cannot express, so `require()` consumers
got the wrong type. The "require" condition now points at hand-written
.d.cts files that derive their types from the generated ones.

Without "type": "module", Node and TypeScript inferred dist/index.d.ts as
CommonJS while the bundle it describes is ESM. TypeScript then resolved the
default import to the module namespace, so `new EasyPieChart(...)` failed to
typecheck for every ESM consumer. The package is ESM again and the UMD build
is emitted as .cjs for the require path; the minified bundle keeps .js since
script tags ignore the type field.

tsc emitted extensionless relative imports in the declarations, which are
unresolvable under node16/nodenext. Consumers with skipLibCheck — the common
case — silently got `any` for every exported type, so bad options such as
`{ size: 'big' }` typechecked. Source imports now carry .js extensions and
tsconfig uses nodenext so tsc catches any regression itself.

Verified against a packed tarball under node16, nodenext and bundler
resolution with skipLibCheck off, plus require() and import at runtime.
2026-07-22 10:27:29 -04:00

67 lines
2.2 KiB
TypeScript

import { resolve } from 'path';
import { defineConfig } from 'vite';
// One pass per artifact, driven by --mode. The default (`production`) pass
// clears dist; every later pass appends to it.
//
// (default) dist/easypiechart.mjs
// umd / umd-min dist/easypiechart.js, dist/easypiechart.min.js
// jquery* the same three for the jQuery plugin
//
// UMD builds use a dedicated entry so the browser global is the constructor
// itself instead of a module namespace object.
const TARGETS = {
production: { entry: 'src/index.ts', base: 'easypiechart', format: 'es' },
umd: { entry: 'src/umd.ts', base: 'easypiechart', format: 'umd' },
'umd-min': { entry: 'src/umd.ts', base: 'easypiechart', format: 'umd' },
jquery: { entry: 'src/jquery.ts', base: 'jquery.easypiechart', format: 'es' },
'jquery-umd': {
entry: 'src/jquery-umd.ts',
base: 'jquery.easypiechart',
format: 'umd',
},
'jquery-umd-min': {
entry: 'src/jquery-umd.ts',
base: 'jquery.easypiechart',
format: 'umd',
},
} as const;
const test = {
environment: 'jsdom',
setupFiles: ['./test/setup.ts'],
} as const;
export default defineConfig(({ mode }) => {
const target = TARGETS[mode as keyof typeof TARGETS];
// vitest runs with mode "test" and needs no lib config
if (!target) {
return { test };
}
const min = mode.endsWith('min');
const isEs = target.format === 'es';
return {
build: {
emptyOutDir: mode === 'production',
minify: min ? 'esbuild' : false,
lib: {
entry: resolve(__dirname, target.entry),
name: target.base === 'easypiechart' ? 'EasyPieChart' : 'easyPieChartJQuery',
formats: [target.format],
// .cjs so Node reads the UMD bundle as CommonJS despite "type": "module";
// the minified build keeps .js because it is loaded via a script tag,
// where the package.json type field does not apply.
fileName: () =>
isEs ? `${target.base}.mjs` : `${target.base}.${min ? 'min.js' : 'cjs'}`,
},
rollupOptions: {
// UMD gets a single default export so the global is the value itself
output: isEs ? {} : { exports: 'default' },
},
},
test,
};
});