Comparing version 4.3.3 to 4.3.4
@@ -143,5 +143,6 @@ #!/usr/bin/env node | ||
const hasAvailableExtension = (filename)=>availableExtensions.has(path__default.default.extname(filename).slice(1)); | ||
// TODO: add unit test | ||
const baseNameWithoutExtension = (filename)=>path__default.default.basename(filename, path__default.default.extname(filename)); | ||
var version = "4.3.3"; | ||
var version = "4.3.4"; | ||
@@ -169,4 +170,6 @@ function relativify(path) { | ||
let cjsExtension = 'js'; | ||
let esmExtension = 'mjs'; | ||
if (moduleType === 'module') { | ||
cjsExtension = 'cjs'; | ||
esmExtension = 'js'; | ||
} | ||
@@ -176,4 +179,4 @@ if (isTsSourceFile) { | ||
import: { | ||
types: getDistPath('es', `${exportName}.d.mts`), | ||
default: getDistPath('es', `${exportName}.mjs`) | ||
types: getDistPath('es', `${exportName}.${dtsExtensionsMap[esmExtension]}`), | ||
default: getDistPath('es', `${exportName}.${esmExtension}`) | ||
}, | ||
@@ -298,4 +301,4 @@ require: { | ||
await fsp__default.default.writeFile(tsconfigPath, JSON.stringify(DEFAULT_TS_CONFIG, null, 2), 'utf-8'); | ||
logger.log(`Detected using TypeScript but tsconfig.json is missing, created a ${pc.blue('tsconfig.json')} for you.`); | ||
} | ||
logger.log(`Detected using TypeScript but tsconfig.json is missing, created a ${pc.blue('tsconfig.json')} for you.`); | ||
} | ||
@@ -342,8 +345,4 @@ // Configure as ESM package by default if there's no package.json | ||
const mainCondition = isESM ? 'import' : 'require'; | ||
if (!pkgJson.main) { | ||
pkgJson.main = isUsingTs ? mainExport[mainCondition].default : mainExport[mainCondition]; | ||
} | ||
if (!pkgJson.module) { | ||
pkgJson.module = isUsingTs ? mainExport.import.default : mainExport.import; | ||
} | ||
pkgJson.main = isUsingTs ? mainExport[mainCondition].default : mainExport[mainCondition]; | ||
pkgJson.module = isUsingTs ? mainExport.import.default : mainExport.import; | ||
if (isUsingTs) { | ||
@@ -355,3 +354,10 @@ pkgJson.types = mainExport[mainCondition].types; | ||
if (Object.keys(pkgExports).length > 0) { | ||
pkgJson.exports = pkgExports; | ||
if (!pkgJson.exports) { | ||
pkgJson.exports = pkgExports; | ||
} else { | ||
// Update existing exports | ||
Object.keys(pkgExports).forEach((exportName)=>{ | ||
pkgJson.exports[exportName] = pkgExports[exportName]; | ||
}); | ||
} | ||
} | ||
@@ -358,0 +364,0 @@ } |
@@ -203,2 +203,3 @@ Object.defineProperty(exports, '__esModule', { value: true }); | ||
} | ||
// TODO: add unit test | ||
// Unlike path.basename, forcedly removing extension | ||
@@ -211,2 +212,4 @@ function filePathWithoutExtension(file) { | ||
const hasCjsExtension = (filename)=>path__default.default.extname(filename) === '.cjs'; | ||
// TODO: add unit test | ||
const baseNameWithoutExtension = (filename)=>path__default.default.basename(filename, path__default.default.extname(filename)); | ||
@@ -396,5 +399,2 @@ let hasLoggedTsWarning = false; | ||
} | ||
function getDistPath(distPath, cwd) { | ||
return path.resolve(cwd, distPath); | ||
} | ||
// Reached the end of the export path | ||
@@ -591,27 +591,2 @@ function isExportLike(field) { | ||
} | ||
const getExportTypeDist = (parsedExportCondition, cwd)=>{ | ||
const existed = new Set(); | ||
const exportTypes = Object.keys(parsedExportCondition.export); | ||
for (const key of exportTypes){ | ||
if (key === 'module') { | ||
continue; | ||
} | ||
const filePath = parsedExportCondition.export[key]; | ||
if (key === 'types') { | ||
const typeFile = getDistPath(filePath, cwd); | ||
if (existed.has(typeFile)) { | ||
continue; | ||
} | ||
existed.add(typeFile); | ||
continue; | ||
} | ||
const ext = path.extname(filePath).slice(1); | ||
const typeFile = getDistPath(`${filePathWithoutExtension(filePath) || ''}.${dtsExtensionsMap[ext]}`, cwd); | ||
if (existed.has(typeFile)) { | ||
continue; | ||
} | ||
existed.add(typeFile); | ||
} | ||
return Array.from(existed); | ||
}; | ||
function getPackageType(pkg) { | ||
@@ -645,32 +620,26 @@ return pkg.type || 'commonjs'; | ||
} | ||
function isCjsExportName(pkg, name, ext) { | ||
function isCjsExportName(pkg, exportCondition, ext) { | ||
const isESModule = isESModulePackage(pkg.type); | ||
return !isESModule && [ | ||
'require', | ||
'main', | ||
'node' | ||
].includes(name) && ext !== 'mjs' || ext === 'cjs'; | ||
'main' | ||
].includes(exportCondition) && ext !== 'mjs' || ext === 'cjs'; | ||
} | ||
function getExportConditionDist(pkg, parsedExportCondition, cwd) { | ||
function getExportsDistFilesOfCondition(pkg, parsedExportCondition, cwd) { | ||
const dist = []; | ||
const existed = new Set(); | ||
const exportTypes = Object.keys(parsedExportCondition.export); | ||
for (const exportType of exportTypes){ | ||
if (exportType === 'types') { | ||
const exportConditionNames = Object.keys(parsedExportCondition.export); | ||
const uniqueFiles = new Set(); | ||
for (const exportCondition of exportConditionNames){ | ||
if (exportCondition === 'types') { | ||
continue; | ||
} | ||
const filePath = parsedExportCondition.export[exportType]; | ||
const filePath = parsedExportCondition.export[exportCondition]; | ||
const ext = path.extname(filePath).slice(1); | ||
const relativePath = parsedExportCondition.export[exportType]; | ||
const distFile = getDistPath(relativePath, cwd); | ||
let format = 'esm'; | ||
if (isCjsExportName(pkg, exportType, ext)) { | ||
format = 'cjs'; | ||
} | ||
// Deduplicate the same path jobs | ||
// TODO: detect conflicts paths but with different format | ||
if (existed.has(distFile)) { | ||
const relativePath = parsedExportCondition.export[exportCondition]; | ||
const distFile = path.resolve(cwd, relativePath); | ||
const format = isCjsExportName(pkg, exportCondition, ext) ? 'cjs' : 'esm'; | ||
if (uniqueFiles.has(distFile)) { | ||
continue; | ||
} | ||
existed.add(distFile); | ||
uniqueFiles.add(distFile); | ||
dist.push({ | ||
@@ -681,16 +650,10 @@ format, | ||
} | ||
if (dist.length === 0 && !pkg.bin) { | ||
const defaultFormat = isESModulePackage(pkg.type) ? 'esm' : 'cjs'; | ||
dist.push({ | ||
format: defaultFormat, | ||
file: getDistPath('dist/index.js', cwd) | ||
}); | ||
} | ||
return dist; | ||
} | ||
function getTypeFilePath(entryFilePath, exportCondition, cwd) { | ||
const name = filePathWithoutExtension(entryFilePath); | ||
const firstDistPath = exportCondition ? Object.values(exportCondition.export)[0] : undefined; | ||
const exportName = (exportCondition == null ? void 0 : exportCondition.name) || 'index'; | ||
return entryFilePath ? name + '.d.ts' : path.resolve(firstDistPath ? path.dirname(firstDistPath) : path.join(cwd, 'dist'), (exportName === '.' ? 'index' : exportName) + '.d.ts'); | ||
function getExportFileTypePath(absoluteJsBundlePath) { | ||
const dirName = path.dirname(absoluteJsBundlePath); | ||
const baseName = baseNameWithoutExtension(absoluteJsBundlePath); | ||
const ext = path.extname(absoluteJsBundlePath).slice(1); | ||
const typeExtension = dtsExtensionsMap[ext]; | ||
return path.join(dirName, baseName + '.' + typeExtension); | ||
} | ||
@@ -728,3 +691,5 @@ function getExportTypeFromFile(filename, pkgType) { | ||
/** | ||
* return { '<absolute source path>': '<pkg>/<export>' } | ||
* return { | ||
* <absolute source path>: <pkg>/<export> | ||
* } | ||
*/ function getReversedAlias(entries) { | ||
@@ -741,3 +706,3 @@ const alias = {}; | ||
} | ||
async function buildInputConfig(entry, options, buildContext, dts) { | ||
async function buildInputConfig(entry, options, buildContext, exportCondition, dts) { | ||
const { entries, pkg, cwd, tsOptions: { tsConfigPath, tsCompilerOptions }, pluginContext } = buildContext; | ||
@@ -758,7 +723,8 @@ const hasNoExternal = options.external === null; | ||
} | ||
const { useTypescript, runtime, target: jscTarget, minify: shouldMinify } = options; | ||
const { useTypeScript } = buildContext; | ||
const { runtime, target: jscTarget, minify: shouldMinify } = options; | ||
const hasSpecifiedTsTarget = Boolean(tsCompilerOptions.target && tsConfigPath); | ||
const swcParserConfig = { | ||
syntax: useTypescript ? 'typescript' : 'ecmascript', | ||
[useTypescript ? 'tsx' : 'jsx']: true, | ||
syntax: useTypeScript ? 'typescript' : 'ecmascript', | ||
[useTypeScript ? 'tsx' : 'jsx']: true, | ||
exportDefaultFrom: true | ||
@@ -803,3 +769,3 @@ }; | ||
]; | ||
if (useTypescript) { | ||
if (useTypeScript) { | ||
const { options: overrideResolvedTsOptions } = await convertCompilerOptions(cwd, { | ||
@@ -814,6 +780,2 @@ declaration: true, | ||
target: 'ESNext', | ||
// Some react types required this to be false by default. | ||
// Some type package like express might need this as it has other dependencies. | ||
// Let users able to toggle this in tsconfig. | ||
preserveSymlinks: 'preserveSymlinks' in tsCompilerOptions ? tsCompilerOptions.preserveSymlinks : false, | ||
...!tsCompilerOptions.jsx ? { | ||
@@ -824,3 +786,5 @@ jsx: 'react-jsx' | ||
// file or when option '--tsBuildInfoFile' is specified. | ||
incremental: false | ||
...tsCompilerOptions.incremental && !tsCompilerOptions.tsBuildInfoFile ? { | ||
incremental: false | ||
} : undefined | ||
}); | ||
@@ -975,18 +939,13 @@ const dtsPlugin = require('rollup-plugin-dts').default({ | ||
const useEsModuleMark = hasEsmExport(exportPaths, tsCompilerOptions); | ||
const typings = getTypings(pkg); | ||
const file = options.file && path.resolve(cwd, options.file); | ||
const dtsDir = typings ? path.dirname(path.resolve(cwd, typings)) : path.resolve(cwd, 'dist'); | ||
const name = filePathWithoutExtension(file); | ||
// TODO: simplify dts file name detection | ||
const dtsFile = file ? file : exportCondition.export['types'] ? path.resolve(cwd, exportCondition.export['types']) : path.resolve(dtsDir, (exportCondition.name === '.' ? 'index' : exportCondition.name) + '.d.ts'); | ||
const dtsPathConfig = { | ||
dir: dtsFile ? path.dirname(dtsFile) : dtsDir | ||
}; | ||
const outputFile = dtsFile || file; | ||
const absoluteOutputFile = path.resolve(cwd, options.file); | ||
const name = filePathWithoutExtension(absoluteOutputFile); | ||
var _exportCondition_export_types; | ||
const dtsFile = path.resolve(cwd, dts ? options.file : (_exportCondition_export_types = exportCondition.export.types) != null ? _exportCondition_export_types : getExportFileTypePath(options.file)); | ||
const typesDir = path.dirname(dtsFile); | ||
const jsDir = path.dirname(absoluteOutputFile); | ||
const outputFile = dts ? dtsFile : absoluteOutputFile; | ||
const entryFiles = new Set(Object.values(entries).map((entry)=>entry.source)); | ||
return { | ||
name: pkg.name || name, | ||
...dts ? dtsPathConfig : { | ||
dir: path.dirname(outputFile) | ||
}, | ||
dir: dts ? typesDir : jsDir, | ||
format, | ||
@@ -1031,3 +990,3 @@ exports: 'named', | ||
exportCondForType = { | ||
[entryExport]: exportCondRef[exportType] | ||
[exportType]: exportCondRef[exportType] | ||
}; | ||
@@ -1115,38 +1074,57 @@ // Basic export type, pass down the exportPaths with erasing the special ones | ||
const entry = exportCondition.source; | ||
const inputOptions = await buildInputConfig(entry, options, pluginContext, dts); | ||
const outputExports = getExportConditionDist(pkg, exportCondition, cwd); | ||
let outputConfigs = []; | ||
// Generate dts job - single config | ||
if (dts) { | ||
const typeOutputExports = getExportTypeDist(exportCondition, cwd); | ||
outputConfigs = typeOutputExports.map((typeFile)=>buildOutputConfigs({ | ||
...bundleConfig, | ||
format: 'es', | ||
useTypescript, | ||
file: typeFile | ||
}, exportCondition, pluginContext, dts)); | ||
const inputOptions = await buildInputConfig(entry, options, pluginContext, exportCondition, dts); | ||
const outputExports = getExportsDistFilesOfCondition(pkg, exportCondition, cwd); | ||
// If there's nothing found, give a default output | ||
if (outputExports.length === 0 && !pkg.bin) { | ||
const defaultFormat = isESModulePackage(pkg.type) ? 'esm' : 'cjs'; | ||
outputExports.push({ | ||
format: defaultFormat, | ||
file: path.join(cwd, 'dist/index.js') | ||
}); | ||
} | ||
let bundleOptions = []; | ||
// multi outputs with specified format | ||
// CLI output option is always prioritized | ||
if (file) { | ||
var _outputExports_; | ||
const fallbackFormat = (_outputExports_ = outputExports[0]) == null ? void 0 : _outputExports_.format; | ||
bundleOptions = [ | ||
{ | ||
resolvedFile: path.resolve(cwd, file), | ||
format: bundleConfig.format || fallbackFormat | ||
} | ||
]; | ||
} else { | ||
// multi outputs with specified format | ||
outputConfigs = outputExports.map((exportDist)=>{ | ||
return buildOutputConfigs({ | ||
...bundleConfig, | ||
file: exportDist.file, | ||
format: exportDist.format, | ||
useTypescript | ||
}, exportCondition, pluginContext, dts); | ||
bundleOptions = outputExports.map((exportDist)=>{ | ||
return { | ||
resolvedFile: path.resolve(cwd, exportDist.file), | ||
format: exportDist.format | ||
}; | ||
}); | ||
// CLI output option is always prioritized | ||
if (file) { | ||
var _outputExports_; | ||
const fallbackFormat = (_outputExports_ = outputExports[0]) == null ? void 0 : _outputExports_.format; | ||
outputConfigs = [ | ||
buildOutputConfigs({ | ||
...bundleConfig, | ||
file, | ||
format: bundleConfig.format || fallbackFormat, | ||
useTypescript | ||
}, exportCondition, pluginContext, dts) | ||
]; | ||
} | ||
} | ||
if (dts) { | ||
// types could have duplicates, dedupe them | ||
// e.g. { types, import, .. } use the same `types` condition with all conditions | ||
const uniqTypes = new Set(); | ||
bundleOptions.forEach((bundleOption)=>{ | ||
if (exportCondition.export.types) { | ||
uniqTypes.add(path.resolve(cwd, exportCondition.export.types)); | ||
} | ||
const typeForExtension = getExportFileTypePath(bundleOption.resolvedFile); | ||
uniqTypes.add(typeForExtension); | ||
}); | ||
bundleOptions = Array.from(uniqTypes).map((typeFile)=>{ | ||
return { | ||
resolvedFile: typeFile, | ||
format: 'es' | ||
}; | ||
}); | ||
} | ||
const outputConfigs = bundleOptions.map((bundleOption)=>{ | ||
return buildOutputConfigs({ | ||
...bundleConfig, | ||
file: bundleOption.resolvedFile, | ||
format: bundleOption.format | ||
}, exportCondition, pluginContext, dts); | ||
}); | ||
return { | ||
@@ -1354,4 +1332,2 @@ input: inputOptions, | ||
const exportPaths = getExportPaths(pkg, packageType, resolvedWildcardExports); | ||
const exportKeys = Object.keys(exportPaths).filter((key)=>key !== './package.json'); | ||
// const exportPathsLength = Object.keys(exportPaths).length | ||
const isMultiEntries = hasMultiEntryExport(exportPaths) // exportPathsLength > 1 | ||
@@ -1378,8 +1354,6 @@ ; | ||
mainEntryPath = options.file; | ||
} else if (exportKeys.length === 0) { | ||
mainEntryPath = path.resolve(cwd, 'dist/index.js'); | ||
} | ||
if (mainEntryPath) { | ||
if (options.dts) { | ||
typesEntryPath = getTypeFilePath(mainEntryPath, undefined, cwd); | ||
typesEntryPath = getExportFileTypePath(mainEntryPath); | ||
} | ||
@@ -1429,2 +1403,3 @@ exportPaths['.'] = constructDefaultExportCondition({ | ||
tsOptions: defaultTsOptions, | ||
useTypeScript: hasTsConfig, | ||
pluginContext: { | ||
@@ -1443,3 +1418,5 @@ outputState: sizeCollector, | ||
} | ||
logOutputState(sizeCollector); | ||
if (!options.watch) { | ||
logOutputState(sizeCollector); | ||
} | ||
return result; | ||
@@ -1446,0 +1423,0 @@ } |
{ | ||
"name": "bunchee", | ||
"version": "4.3.3", | ||
"version": "4.3.4", | ||
"description": "zero config bundler for js/ts/jsx libraries", | ||
@@ -5,0 +5,0 @@ "bin": "./dist/bin/cli.js", |
@@ -37,2 +37,3 @@ # bunchee | ||
Create your library entry file and package.json. | ||
```sh | ||
@@ -61,2 +62,3 @@ cd ./my-lib | ||
Then use use the [exports field in package.json](https://nodejs.org/api/packages.html#exports-sugar) to configure different conditions and leverage the same functionality as other bundlers, such as webpack. The exports field allows you to define multiple conditions. | ||
```json | ||
@@ -74,2 +76,3 @@ { | ||
``` | ||
</details> | ||
@@ -100,5 +103,5 @@ | ||
``` | ||
</details> | ||
<details> | ||
@@ -129,2 +132,3 @@ <summary>Hybrid (CJS & ESM) Module Resolution with TypeScript</summary> | ||
``` | ||
</details> | ||
@@ -248,3 +252,2 @@ | ||
### Server Components | ||
@@ -289,3 +292,3 @@ | ||
By default, `bunchee` will mark all the `dependencies` and `peerDependencies` as externals so you don't need to pass them as CLI args. | ||
By default, `bunchee` will mark all the `dependencies` and `peerDependencies` as externals so you don't need to pass them as CLI args. | ||
But if there's any dependency that used but not in the dependency list and you want to mark as external, you can use the `--external` option to specify them. | ||
@@ -319,3 +322,2 @@ | ||
You can use `index.<export-type>.<ext>` to override the input source file for specific export name. Or using `<export-path>/index.<export-type>.<ext>` also works. Such as: | ||
@@ -332,3 +334,2 @@ | ||
### Wildcard Exports | ||
@@ -414,2 +415,3 @@ | ||
src/index.ts | ||
```js | ||
@@ -422,2 +424,3 @@ import data from './data.txt' | ||
src/data.txt | ||
```txt | ||
@@ -428,2 +431,3 @@ hello world | ||
output | ||
``` | ||
@@ -465,5 +469,4 @@ export default "hello world" | ||
### License | ||
MIT |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
460
92366
1972