Skip to content

Commit f889af8

Browse files
committed
feat!: support exports, publint, attw for multi-configs
1 parent 85c0e55 commit f889af8

File tree

12 files changed

+241
-106
lines changed

12 files changed

+241
-106
lines changed

src/config/chunks.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/config/options.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import isInCi from 'is-in-ci'
55
import { createDebug } from 'obug'
66
import { resolveClean } from '../features/clean.ts'
77
import { resolveEntry } from '../features/entry.ts'
8-
import { hasExportsTypes } from '../features/exports.ts'
8+
import { hasExportsTypes } from '../features/pkg/exports.ts'
99
import { resolveTarget } from '../features/target.ts'
1010
import { resolveTsconfig } from '../features/tsconfig.ts'
1111
import {
@@ -14,7 +14,7 @@ import {
1414
resolveRegex,
1515
toArray,
1616
} from '../utils/general.ts'
17-
import { createLogger } from '../utils/logger.ts'
17+
import { createLogger, prettyName } from '../utils/logger.ts'
1818
import { normalizeFormat, readPackageJson } from '../utils/package.ts'
1919
import type { Awaitable } from '../utils/types.ts'
2020
import { loadViteConfig } from './file.ts'
@@ -135,6 +135,25 @@ export async function resolveUserConfig(
135135
report = resolveFeatureOption(report, {})
136136
dts = resolveFeatureOption(dts, {})
137137

138+
if (!pkg) {
139+
if (exports) {
140+
throw new Error('`package.json` not found, cannot write exports')
141+
}
142+
if (publint) {
143+
logger.warn(
144+
prettyName(name),
145+
'publint is enabled but package.json is not found',
146+
)
147+
}
148+
if (attw) {
149+
logger.warn(
150+
prettyName(name),
151+
'attw is enabled but package.json is not found',
152+
)
153+
return
154+
}
155+
}
156+
138157
if (publicDir) {
139158
if (copy) {
140159
throw new TypeError(

src/config/types.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import type { AttwOptions } from '../features/attw.ts'
21
import type { CopyEntry, CopyOptions, CopyOptionsFn } from '../features/copy.ts'
32
import type { DebugOptions } from '../features/debug.ts'
4-
import type { ExportsOptions } from '../features/exports.ts'
53
import type {
64
BuildContext,
75
RolldownContext,
@@ -15,7 +13,14 @@ import type {
1513
OutExtensionFactory,
1614
OutExtensionObject,
1715
} from '../features/output.ts'
16+
import type { AttwOptions } from '../features/pkg/attw.ts'
17+
import type { ExportsOptions } from '../features/pkg/exports.ts'
1818
import type { ReportOptions } from '../features/report.ts'
19+
import type {
20+
RolldownChunk,
21+
TsdownBundle,
22+
TsdownChunks,
23+
} from '../utils/chunks.ts'
1924
import type { Logger, LogLevel } from '../utils/logger.ts'
2025
import type { PackageJsonWithPath, PackageType } from '../utils/package.ts'
2126
import type {
@@ -40,7 +45,6 @@ import type {
4045
import type { Options as DtsOptions } from 'rolldown-plugin-dts'
4146
import type { Options as UnusedOptions } from 'unplugin-unused'
4247

43-
export * from './chunks.ts'
4448
export type Sourcemap = boolean | 'inline' | 'hidden'
4549
export type Format = ModuleFormat
4650
export type NormalizedFormat = InternalModuleFormat
@@ -63,8 +67,11 @@ export type {
6367
PackageType,
6468
PublintOptions,
6569
ReportOptions,
70+
RolldownChunk,
6671
RolldownContext,
6772
TreeshakingOptions,
73+
TsdownBundle,
74+
TsdownChunks,
6875
TsdownHooks,
6976
UnusedOptions,
7077
}

src/features/attw.ts renamed to src/features/pkg/attw.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import process from 'node:process'
55
import { dim } from 'ansis'
66
import { createDebug } from 'obug'
77
import { exec } from 'tinyexec'
8-
import { fsRemove } from '../utils/fs.ts'
9-
import { importWithError } from '../utils/general.ts'
10-
import { prettyName } from '../utils/logger.ts'
11-
import type { ResolvedConfig } from '../config/index.ts'
8+
import { fsRemove } from '../../utils/fs.ts'
9+
import { importWithError } from '../../utils/general.ts'
10+
import { prettyName } from '../../utils/logger.ts'
11+
import type { ResolvedConfig } from '../../config/index.ts'
1212
import type {
1313
CheckPackageOptions,
1414
CheckResult,

src/features/exports.test.ts renamed to src/features/pkg/exports.test.ts

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import path from 'node:path'
22
import process from 'node:process'
33
import { describe, test } from 'vitest'
4+
import type { RolldownChunk } from '../../utils/chunks.ts'
45
import { generateExports } from './exports.ts'
5-
import type { OutputChunk } from 'rolldown'
66

77
const cwd = process.cwd()
88
const FAKE_PACKAGE_JSON = {
@@ -11,7 +11,7 @@ const FAKE_PACKAGE_JSON = {
1111

1212
describe.concurrent('generateExports', () => {
1313
test('no entries', async ({ expect }) => {
14-
const results = generateExports(FAKE_PACKAGE_JSON, cwd, {}, {})
14+
const results = generateExports(FAKE_PACKAGE_JSON, {}, {})
1515
await expect(results).resolves.toMatchInlineSnapshot(`
1616
{
1717
"exports": {
@@ -28,10 +28,7 @@ describe.concurrent('generateExports', () => {
2828
test('only one entry', async ({ expect }) => {
2929
const results = generateExports(
3030
FAKE_PACKAGE_JSON,
31-
cwd,
32-
{
33-
es: [genChunk('main.js')],
34-
},
31+
{ es: [genChunk('main.js')] },
3532
{},
3633
)
3734
await expect(results).resolves.toMatchInlineSnapshot(`
@@ -51,10 +48,7 @@ describe.concurrent('generateExports', () => {
5148
test('index entry', async ({ expect }) => {
5249
const results = generateExports(
5350
FAKE_PACKAGE_JSON,
54-
cwd,
55-
{
56-
es: [genChunk('index.js'), genChunk('foo.js')],
57-
},
51+
{ es: [genChunk('index.js'), genChunk('foo.js')] },
5852
{},
5953
)
6054
await expect(results).resolves.toMatchInlineSnapshot(`
@@ -75,10 +69,7 @@ describe.concurrent('generateExports', () => {
7569
test('index entry in dir', async ({ expect }) => {
7670
const results = generateExports(
7771
FAKE_PACKAGE_JSON,
78-
cwd,
79-
{
80-
es: [genChunk('index.js'), genChunk('foo/index.js')],
81-
},
72+
{ es: [genChunk('index.js'), genChunk('foo/index.js')] },
8273
{},
8374
)
8475
await expect(results).resolves.toMatchInlineSnapshot(`
@@ -99,10 +90,7 @@ describe.concurrent('generateExports', () => {
9990
test('multiple entries', async ({ expect }) => {
10091
const results = generateExports(
10192
FAKE_PACKAGE_JSON,
102-
cwd,
103-
{
104-
es: [genChunk('foo.js'), genChunk('bar.js')],
105-
},
93+
{ es: [genChunk('foo.js'), genChunk('bar.js')] },
10694
{},
10795
)
10896
await expect(results).resolves.toMatchInlineSnapshot(`
@@ -123,7 +111,6 @@ describe.concurrent('generateExports', () => {
123111
test('dual formats', async ({ expect }) => {
124112
const results = generateExports(
125113
FAKE_PACKAGE_JSON,
126-
cwd,
127114
{
128115
es: [genChunk('foo.js')],
129116
cjs: [genChunk('foo.cjs')],
@@ -150,7 +137,6 @@ describe.concurrent('generateExports', () => {
150137
test('dts', async ({ expect }) => {
151138
const results = generateExports(
152139
FAKE_PACKAGE_JSON,
153-
cwd,
154140
{
155141
es: [genChunk('foo.js'), genChunk('foo.d.ts')],
156142
cjs: [genChunk('foo.cjs'), genChunk('foo.d.cts')],
@@ -177,7 +163,6 @@ describe.concurrent('generateExports', () => {
177163
test('fixed extension', async ({ expect }) => {
178164
const results = generateExports(
179165
FAKE_PACKAGE_JSON,
180-
cwd,
181166
{
182167
es: [genChunk('index.mjs'), genChunk('index.d.mts')],
183168
cjs: [genChunk('index.cjs'), genChunk('index.d.cts')],
@@ -204,7 +189,6 @@ describe.concurrent('generateExports', () => {
204189
test('dev exports: dev condition', async ({ expect }) => {
205190
const results = await generateExports(
206191
FAKE_PACKAGE_JSON,
207-
cwd,
208192
{ es: [genChunk('index.js')], cjs: [genChunk('index.cjs')] },
209193
{ devExports: 'dev' },
210194
)
@@ -235,7 +219,6 @@ describe.concurrent('generateExports', () => {
235219
test('dev exports: all conditions', async ({ expect }) => {
236220
const results = generateExports(
237221
FAKE_PACKAGE_JSON,
238-
cwd,
239222
{ es: [genChunk('index.js')], cjs: [genChunk('index.cjs')] },
240223
{ devExports: true },
241224
)
@@ -262,7 +245,6 @@ describe.concurrent('generateExports', () => {
262245
test('customExports', async ({ expect }) => {
263246
const results = await generateExports(
264247
FAKE_PACKAGE_JSON,
265-
cwd,
266248
{ es: [genChunk('index.js')] },
267249
{
268250
devExports: 'dev',
@@ -297,7 +279,6 @@ describe.concurrent('generateExports', () => {
297279
test('export all', async ({ expect }) => {
298280
const results = generateExports(
299281
FAKE_PACKAGE_JSON,
300-
cwd,
301282
{ es: [genChunk('index.js')], cjs: [genChunk('index.cjs')] },
302283
{ all: true },
303284
)
@@ -321,7 +302,6 @@ describe.concurrent('generateExports', () => {
321302
test('windows-like paths for subpackages', async ({ expect }) => {
322303
const results = generateExports(
323304
FAKE_PACKAGE_JSON,
324-
cwd,
325305
{
326306
es: [
327307
genChunk('index.js'),
@@ -355,7 +335,6 @@ describe.concurrent('generateExports', () => {
355335
}) => {
356336
const results = generateExports(
357337
FAKE_PACKAGE_JSON,
358-
cwd,
359338
{
360339
es: [
361340
genChunk('index.js'),
@@ -409,5 +388,6 @@ function genChunk(fileName: string) {
409388
fileName,
410389
isEntry: true,
411390
facadeModuleId: `./SRC/${fileName}`,
412-
} as OutputChunk
391+
outDir: cwd,
392+
} as RolldownChunk
413393
}

src/features/exports.ts renamed to src/features/pkg/exports.ts

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { readFile, writeFile } from 'node:fs/promises'
22
import path from 'node:path'
33
import { RE_DTS } from 'rolldown-plugin-dts/filename'
4-
import { detectIndentation } from '../utils/format.ts'
5-
import { slash } from '../utils/general.ts'
6-
import type { TsdownChunks } from '../config/chunks.ts'
7-
import type { NormalizedFormat, ResolvedConfig } from '../config/index.ts'
8-
import type { Awaitable } from '../utils/types.ts'
4+
import { detectIndentation } from '../../utils/format.ts'
5+
import { slash } from '../../utils/general.ts'
6+
import type { NormalizedFormat, ResolvedConfig } from '../../config/types.ts'
7+
import type { RolldownChunk, TsdownChunks } from '../../utils/chunks.ts'
8+
import type { Awaitable } from '../../utils/types.ts'
99
import type { PackageJson } from 'pkg-types'
10-
import type { OutputAsset, OutputChunk } from 'rolldown'
1110

1211
export interface ExportsOptions {
1312
/**
@@ -27,42 +26,22 @@ export interface ExportsOptions {
2726
context: {
2827
pkg: PackageJson
2928
chunks: TsdownChunks
30-
outDir: string
3129
isPublish: boolean
3230
},
3331
) => Awaitable<Record<string, any>>
3432
}
3533

36-
export const exportsState: Map<
37-
string /* packagePath::outDir */,
38-
Set<TsdownChunks>
39-
> = new Map()
40-
4134
export async function writeExports(
4235
options: ResolvedConfig,
4336
chunks: TsdownChunks,
4437
): Promise<void> {
45-
if (!options.exports) return
46-
47-
const { outDir, pkg } = options
48-
if (!pkg) {
49-
throw new Error('`package.json` not found, cannot write exports')
50-
}
51-
52-
const stateKey = `${pkg.packageJsonPath}::${outDir}`
53-
let chunkSets = exportsState.get(stateKey)
54-
if (!chunkSets) {
55-
chunkSets = new Set()
56-
exportsState.set(stateKey, chunkSets)
57-
}
58-
chunkSets.add(chunks)
59-
const mergedChunks = mergeChunks(chunkSets)
38+
const pkg = options.pkg!
39+
const exports = options.exports as ExportsOptions
6040

6141
const { publishExports, ...generated } = await generateExports(
6242
pkg,
63-
outDir,
64-
mergedChunks,
65-
options.exports,
43+
chunks,
44+
exports,
6645
)
6746

6847
const updatedPkg = {
@@ -88,7 +67,6 @@ type SubExport = Partial<Record<'cjs' | 'es' | 'src', string>>
8867

8968
export async function generateExports(
9069
pkg: PackageJson,
91-
outDir: string,
9270
chunks: TsdownChunks,
9371
{ devExports, all, customExports }: ExportsOptions,
9472
): Promise<{
@@ -99,7 +77,6 @@ export async function generateExports(
9977
publishExports?: Record<string, any>
10078
}> {
10179
const pkgRoot = path.dirname(pkg.packageJsonPath)
102-
const outDirRelative = slash(path.relative(pkgRoot, outDir))
10380

10481
let main: string | undefined,
10582
module: string | undefined,
@@ -109,7 +86,7 @@ export async function generateExports(
10986

11087
for (const [format, chunksByFormat] of Object.entries(chunks) as [
11188
NormalizedFormat,
112-
(OutputChunk | OutputAsset)[],
89+
RolldownChunk[],
11390
][]) {
11491
if (format !== 'es' && format !== 'cjs') continue
11592

@@ -132,6 +109,7 @@ export async function generateExports(
132109
name = name.slice(0, -2)
133110
}
134111
const isIndex = onlyOneEntry || name === 'index'
112+
const outDirRelative = slash(path.relative(pkgRoot, chunk.outDir))
135113
const distFile = `${outDirRelative ? `./${outDirRelative}` : '.'}/${normalizedName}`
136114

137115
if (isIndex) {
@@ -187,7 +165,6 @@ export async function generateExports(
187165
if (customExports) {
188166
exports = await customExports(exports, {
189167
pkg,
190-
outDir,
191168
chunks,
192169
isPublish: false,
193170
})
@@ -205,7 +182,6 @@ export async function generateExports(
205182
if (customExports) {
206183
publishExports = await customExports(publishExports, {
207184
pkg,
208-
outDir,
209185
chunks,
210186
isPublish: true,
211187
})
@@ -283,12 +259,12 @@ export function hasExportsTypes(pkg?: PackageJson): boolean {
283259
return false
284260
}
285261

286-
function mergeChunks(chunkSets: Set<TsdownChunks>): TsdownChunks {
262+
export function mergeChunks(chunkSets: TsdownChunks[]): TsdownChunks {
287263
const merged: TsdownChunks = {}
288264
for (const chunkSet of chunkSets) {
289265
for (const [format, chunks] of Object.entries(chunkSet) as [
290266
NormalizedFormat,
291-
(OutputChunk | OutputAsset)[],
267+
RolldownChunk[],
292268
][]) {
293269
if (!chunks.length) continue
294270
const target = (merged[format] ||= [])

0 commit comments

Comments
 (0)