@mui/internal-code-infra 0.0.4-canary.13 → 0.0.4-canary.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  import * as fs from 'node:fs/promises';
2
- import * as os from 'node:os';
3
2
  import * as path from 'node:path';
4
3
  import { describe, expect, it } from 'vitest';
5
4
 
5
+ import { makeTempDir } from './testUtils.mjs';
6
6
  import { createPackageBin, createPackageExports } from './build.mjs';
7
7
 
8
8
  /**
@@ -14,21 +14,110 @@ async function createFile(filePath, contents = '') {
14
14
  await fs.writeFile(filePath, contents, 'utf8');
15
15
  }
16
16
 
17
- /**
18
- * @param {(cwd: string) => Promise<void>} fn
19
- */
20
- async function withTempDir(fn) {
21
- const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'code-infra-build-test-'));
22
- try {
23
- return await fn(tmpDir);
24
- } finally {
25
- await fs.rm(tmpDir, { recursive: true, force: true });
26
- }
27
- }
28
-
29
17
  describe('createPackageExports', () => {
30
18
  it('creates exports for a dual bundle module package', async () => {
31
- await withTempDir(async (cwd) => {
19
+ const cwd = await makeTempDir();
20
+ const outputDir = path.join(cwd, 'build');
21
+ /**
22
+ * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
23
+ */
24
+ const bundles = [
25
+ { type: 'esm', dir: '.' },
26
+ { type: 'cjs', dir: '.' },
27
+ ];
28
+
29
+ await Promise.all([
30
+ createFile(path.join(cwd, 'src/index.ts')),
31
+ createFile(path.join(cwd, 'src/feature.ts')),
32
+
33
+ // Create output files for index
34
+ createFile(path.join(outputDir, `index.js`)),
35
+ createFile(path.join(outputDir, `index.cjs`)),
36
+ createFile(path.join(outputDir, `index.d.ts`)),
37
+ createFile(path.join(outputDir, `index.d.cts`)),
38
+
39
+ // Create output files for feature
40
+ createFile(path.join(outputDir, `feature.js`)),
41
+ createFile(path.join(outputDir, `feature.cjs`)),
42
+ createFile(path.join(outputDir, `feature.d.ts`)),
43
+ createFile(path.join(outputDir, `feature.d.cts`)),
44
+ ]);
45
+
46
+ const {
47
+ exports: packageExports,
48
+ main,
49
+ types,
50
+ } = await createPackageExports({
51
+ exports: {
52
+ '.': './src/index.ts',
53
+ './feature': './src/feature.ts',
54
+ },
55
+ bundles,
56
+ outputDir,
57
+ cwd,
58
+ addTypes: true,
59
+ isFlat: true,
60
+ packageType: 'module',
61
+ });
62
+
63
+ expect(main).toBe('./index.cjs');
64
+ expect(types).toBe('./index.d.cts');
65
+
66
+ expect(packageExports['.']).toEqual({
67
+ import: { types: './index.d.ts', default: './index.js' },
68
+ require: { types: './index.d.cts', default: './index.cjs' },
69
+ default: {
70
+ types: './index.d.ts',
71
+ default: './index.js',
72
+ },
73
+ });
74
+ expect(packageExports['./feature']).toEqual({
75
+ import: { types: './feature.d.ts', default: './feature.js' },
76
+ require: { types: './feature.d.cts', default: './feature.cjs' },
77
+ default: {
78
+ types: './feature.d.ts',
79
+ default: './feature.js',
80
+ },
81
+ });
82
+
83
+ const {
84
+ exports: packageExports2,
85
+ main: main2,
86
+ types: types2,
87
+ } = await createPackageExports({
88
+ exports: {
89
+ '.': './src/index.ts',
90
+ './feature': './src/feature.ts',
91
+ },
92
+ bundles: [bundles[1]], // only CJS bundle
93
+ outputDir,
94
+ cwd,
95
+ addTypes: true,
96
+ isFlat: true,
97
+ });
98
+
99
+ expect(main2).toBe('./index.js');
100
+ expect(types2).toBe('./index.d.ts');
101
+
102
+ expect(packageExports2['.']).toEqual({
103
+ require: { types: './index.d.ts', default: './index.js' },
104
+ default: {
105
+ types: './index.d.ts',
106
+ default: './index.js',
107
+ },
108
+ });
109
+ expect(packageExports2['./feature']).toEqual({
110
+ require: { types: './feature.d.ts', default: './feature.js' },
111
+ default: {
112
+ types: './feature.d.ts',
113
+ default: './feature.js',
114
+ },
115
+ });
116
+ });
117
+
118
+ describe('glob expansion', () => {
119
+ it('expands glob patterns in export keys and values', async () => {
120
+ const cwd = await makeTempDir();
32
121
  const outputDir = path.join(cwd, 'build');
33
122
  /**
34
123
  * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
@@ -39,30 +128,23 @@ describe('createPackageExports', () => {
39
128
  ];
40
129
 
41
130
  await Promise.all([
42
- createFile(path.join(cwd, 'src/index.ts')),
43
- createFile(path.join(cwd, 'src/feature.ts')),
44
-
45
- // Create output files for index
46
- createFile(path.join(outputDir, `index.js`)),
47
- createFile(path.join(outputDir, `index.cjs`)),
48
- createFile(path.join(outputDir, `index.d.ts`)),
49
- createFile(path.join(outputDir, `index.d.cts`)),
50
-
51
- // Create output files for feature
52
- createFile(path.join(outputDir, `feature.js`)),
53
- createFile(path.join(outputDir, `feature.cjs`)),
54
- createFile(path.join(outputDir, `feature.d.ts`)),
55
- createFile(path.join(outputDir, `feature.d.cts`)),
131
+ createFile(path.join(cwd, 'src/Button.ts')),
132
+ createFile(path.join(cwd, 'src/TextField.ts')),
133
+
134
+ // Output files
135
+ createFile(path.join(outputDir, 'Button.js')),
136
+ createFile(path.join(outputDir, 'Button.cjs')),
137
+ createFile(path.join(outputDir, 'Button.d.ts')),
138
+ createFile(path.join(outputDir, 'Button.d.cts')),
139
+ createFile(path.join(outputDir, 'TextField.js')),
140
+ createFile(path.join(outputDir, 'TextField.cjs')),
141
+ createFile(path.join(outputDir, 'TextField.d.ts')),
142
+ createFile(path.join(outputDir, 'TextField.d.cts')),
56
143
  ]);
57
144
 
58
- const {
59
- exports: packageExports,
60
- main,
61
- types,
62
- } = await createPackageExports({
145
+ const { exports: packageExports } = await createPackageExports({
63
146
  exports: {
64
- '.': './src/index.ts',
65
- './feature': './src/feature.ts',
147
+ './*': './src/*.ts',
66
148
  },
67
149
  bundles,
68
150
  outputDir,
@@ -72,634 +154,523 @@ describe('createPackageExports', () => {
72
154
  packageType: 'module',
73
155
  });
74
156
 
75
- expect(main).toBe('./index.cjs');
76
- expect(types).toBe('./index.d.cts');
77
-
78
- expect(packageExports['.']).toEqual({
79
- import: { types: './index.d.ts', default: './index.js' },
80
- require: { types: './index.d.cts', default: './index.cjs' },
81
- default: {
82
- types: './index.d.ts',
83
- default: './index.js',
84
- },
157
+ expect(packageExports['./Button']).toEqual({
158
+ import: { types: './Button.d.ts', default: './Button.js' },
159
+ require: { types: './Button.d.cts', default: './Button.cjs' },
160
+ default: { types: './Button.d.ts', default: './Button.js' },
85
161
  });
86
- expect(packageExports['./feature']).toEqual({
87
- import: { types: './feature.d.ts', default: './feature.js' },
88
- require: { types: './feature.d.cts', default: './feature.cjs' },
89
- default: {
90
- types: './feature.d.ts',
91
- default: './feature.js',
92
- },
162
+ expect(packageExports['./TextField']).toEqual({
163
+ import: { types: './TextField.d.ts', default: './TextField.js' },
164
+ require: { types: './TextField.d.cts', default: './TextField.cjs' },
165
+ default: { types: './TextField.d.ts', default: './TextField.js' },
93
166
  });
167
+ // glob key should not appear in the output
168
+ expect(packageExports['./*']).toBeUndefined();
169
+ });
170
+
171
+ it('expands glob with commonjs package type', async () => {
172
+ const cwd = await makeTempDir();
173
+ const outputDir = path.join(cwd, 'build');
174
+ /**
175
+ * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
176
+ */
177
+ const bundles = [
178
+ { type: 'esm', dir: '.' },
179
+ { type: 'cjs', dir: '.' },
180
+ ];
181
+
182
+ await Promise.all([
183
+ createFile(path.join(cwd, 'src/Button.ts')),
184
+
185
+ createFile(path.join(outputDir, 'Button.js')),
186
+ createFile(path.join(outputDir, 'Button.mjs')),
187
+ createFile(path.join(outputDir, 'Button.d.ts')),
188
+ createFile(path.join(outputDir, 'Button.d.mts')),
189
+ ]);
94
190
 
95
- const {
96
- exports: packageExports2,
97
- main: main2,
98
- types: types2,
99
- } = await createPackageExports({
191
+ const { exports: packageExports } = await createPackageExports({
100
192
  exports: {
101
- '.': './src/index.ts',
102
- './feature': './src/feature.ts',
193
+ './*': './src/*.ts',
103
194
  },
104
- bundles: [bundles[1]], // only CJS bundle
195
+ bundles,
105
196
  outputDir,
106
197
  cwd,
107
198
  addTypes: true,
108
199
  isFlat: true,
200
+ packageType: 'commonjs',
109
201
  });
110
202
 
111
- expect(main2).toBe('./index.js');
112
- expect(types2).toBe('./index.d.ts');
113
-
114
- expect(packageExports2['.']).toEqual({
115
- require: { types: './index.d.ts', default: './index.js' },
116
- default: {
117
- types: './index.d.ts',
118
- default: './index.js',
119
- },
120
- });
121
- expect(packageExports2['./feature']).toEqual({
122
- require: { types: './feature.d.ts', default: './feature.js' },
123
- default: {
124
- types: './feature.d.ts',
125
- default: './feature.js',
126
- },
203
+ expect(packageExports['./Button']).toEqual({
204
+ import: { types: './Button.d.mts', default: './Button.mjs' },
205
+ require: { types: './Button.d.ts', default: './Button.js' },
206
+ default: { types: './Button.d.mts', default: './Button.mjs' },
127
207
  });
128
208
  });
129
- });
130
209
 
131
- describe('glob expansion', () => {
132
- it('expands glob patterns in export keys and values', async () => {
133
- await withTempDir(async (cwd) => {
134
- const outputDir = path.join(cwd, 'build');
135
- /**
136
- * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
137
- */
138
- const bundles = [
139
- { type: 'esm', dir: '.' },
140
- { type: 'cjs', dir: '.' },
141
- ];
142
-
143
- await Promise.all([
144
- createFile(path.join(cwd, 'src/Button.ts')),
145
- createFile(path.join(cwd, 'src/TextField.ts')),
146
-
147
- // Output files
148
- createFile(path.join(outputDir, 'Button.js')),
149
- createFile(path.join(outputDir, 'Button.cjs')),
150
- createFile(path.join(outputDir, 'Button.d.ts')),
151
- createFile(path.join(outputDir, 'Button.d.cts')),
152
- createFile(path.join(outputDir, 'TextField.js')),
153
- createFile(path.join(outputDir, 'TextField.cjs')),
154
- createFile(path.join(outputDir, 'TextField.d.ts')),
155
- createFile(path.join(outputDir, 'TextField.d.cts')),
156
- ]);
157
-
158
- const { exports: packageExports } = await createPackageExports({
159
- exports: {
160
- './*': './src/*.ts',
161
- },
162
- bundles,
163
- outputDir,
164
- cwd,
165
- addTypes: true,
166
- isFlat: true,
167
- packageType: 'module',
168
- });
169
-
170
- expect(packageExports['./Button']).toEqual({
171
- import: { types: './Button.d.ts', default: './Button.js' },
172
- require: { types: './Button.d.cts', default: './Button.cjs' },
173
- default: { types: './Button.d.ts', default: './Button.js' },
174
- });
175
- expect(packageExports['./TextField']).toEqual({
176
- import: { types: './TextField.d.ts', default: './TextField.js' },
177
- require: { types: './TextField.d.cts', default: './TextField.cjs' },
178
- default: { types: './TextField.d.ts', default: './TextField.js' },
179
- });
180
- // glob key should not appear in the output
181
- expect(packageExports['./*']).toBeUndefined();
182
- });
183
- });
210
+ it('expands glob with single CJS bundle', async () => {
211
+ const cwd = await makeTempDir();
212
+ const outputDir = path.join(cwd, 'build');
184
213
 
185
- it('expands glob with commonjs package type', async () => {
186
- await withTempDir(async (cwd) => {
187
- const outputDir = path.join(cwd, 'build');
188
- /**
189
- * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
190
- */
191
- const bundles = [
192
- { type: 'esm', dir: '.' },
193
- { type: 'cjs', dir: '.' },
194
- ];
195
-
196
- await Promise.all([
197
- createFile(path.join(cwd, 'src/Button.ts')),
198
-
199
- createFile(path.join(outputDir, 'Button.js')),
200
- createFile(path.join(outputDir, 'Button.mjs')),
201
- createFile(path.join(outputDir, 'Button.d.ts')),
202
- createFile(path.join(outputDir, 'Button.d.mts')),
203
- ]);
204
-
205
- const { exports: packageExports } = await createPackageExports({
206
- exports: {
207
- './*': './src/*.ts',
208
- },
209
- bundles,
210
- outputDir,
211
- cwd,
212
- addTypes: true,
213
- isFlat: true,
214
- packageType: 'commonjs',
215
- });
216
-
217
- expect(packageExports['./Button']).toEqual({
218
- import: { types: './Button.d.mts', default: './Button.mjs' },
219
- require: { types: './Button.d.ts', default: './Button.js' },
220
- default: { types: './Button.d.mts', default: './Button.mjs' },
221
- });
214
+ await Promise.all([
215
+ createFile(path.join(cwd, 'src/Button.ts')),
216
+
217
+ createFile(path.join(outputDir, 'Button.js')),
218
+ createFile(path.join(outputDir, 'Button.d.ts')),
219
+ ]);
220
+
221
+ const { exports: packageExports } = await createPackageExports({
222
+ exports: {
223
+ './*': './src/*.ts',
224
+ },
225
+ bundles: [{ type: 'cjs', dir: '.' }],
226
+ outputDir,
227
+ cwd,
228
+ addTypes: true,
229
+ isFlat: true,
230
+ packageType: 'commonjs',
222
231
  });
223
- });
224
232
 
225
- it('expands glob with single CJS bundle', async () => {
226
- await withTempDir(async (cwd) => {
227
- const outputDir = path.join(cwd, 'build');
228
-
229
- await Promise.all([
230
- createFile(path.join(cwd, 'src/Button.ts')),
231
-
232
- createFile(path.join(outputDir, 'Button.js')),
233
- createFile(path.join(outputDir, 'Button.d.ts')),
234
- ]);
235
-
236
- const { exports: packageExports } = await createPackageExports({
237
- exports: {
238
- './*': './src/*.ts',
239
- },
240
- bundles: [{ type: 'cjs', dir: '.' }],
241
- outputDir,
242
- cwd,
243
- addTypes: true,
244
- isFlat: true,
245
- packageType: 'commonjs',
246
- });
247
-
248
- expect(packageExports['./Button']).toEqual({
249
- require: { types: './Button.d.ts', default: './Button.js' },
250
- default: { types: './Button.d.ts', default: './Button.js' },
251
- });
233
+ expect(packageExports['./Button']).toEqual({
234
+ require: { types: './Button.d.ts', default: './Button.js' },
235
+ default: { types: './Button.d.ts', default: './Button.js' },
252
236
  });
253
237
  });
254
238
 
255
239
  it('expands glob patterns with mui-src object values', async () => {
256
- await withTempDir(async (cwd) => {
257
- const outputDir = path.join(cwd, 'build');
258
- /**
259
- * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
260
- */
261
- const bundles = [
262
- { type: 'esm', dir: '.' },
263
- { type: 'cjs', dir: '.' },
264
- ];
265
-
266
- await Promise.all([
267
- createFile(path.join(cwd, 'src/Alert.ts')),
268
-
269
- createFile(path.join(outputDir, 'Alert.js')),
270
- createFile(path.join(outputDir, 'Alert.cjs')),
271
- ]);
272
-
273
- const { exports: packageExports } = await createPackageExports({
274
- exports: {
275
- './*': { 'mui-src': './src/*.ts' },
276
- },
277
- bundles,
278
- outputDir,
279
- cwd,
280
- isFlat: true,
281
- packageType: 'module',
282
- });
283
-
284
- expect(packageExports['./Alert']).toEqual({
285
- import: './Alert.js',
286
- require: './Alert.cjs',
287
- default: './Alert.js',
288
- });
240
+ const cwd = await makeTempDir();
241
+ const outputDir = path.join(cwd, 'build');
242
+ /**
243
+ * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
244
+ */
245
+ const bundles = [
246
+ { type: 'esm', dir: '.' },
247
+ { type: 'cjs', dir: '.' },
248
+ ];
249
+
250
+ await Promise.all([
251
+ createFile(path.join(cwd, 'src/Alert.ts')),
252
+
253
+ createFile(path.join(outputDir, 'Alert.js')),
254
+ createFile(path.join(outputDir, 'Alert.cjs')),
255
+ ]);
256
+
257
+ const { exports: packageExports } = await createPackageExports({
258
+ exports: {
259
+ './*': { 'mui-src': './src/*.ts' },
260
+ },
261
+ bundles,
262
+ outputDir,
263
+ cwd,
264
+ isFlat: true,
265
+ packageType: 'module',
266
+ });
267
+
268
+ expect(packageExports['./Alert']).toEqual({
269
+ import: './Alert.js',
270
+ require: './Alert.cjs',
271
+ default: './Alert.js',
289
272
  });
290
273
  });
291
274
 
292
275
  it('preserves extra conditions from mui-src object values', async () => {
293
- await withTempDir(async (cwd) => {
294
- const outputDir = path.join(cwd, 'build');
295
- /**
296
- * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
297
- */
298
- const bundles = [
299
- { type: 'esm', dir: '.' },
300
- { type: 'cjs', dir: '.' },
301
- ];
302
-
303
- await Promise.all([
304
- createFile(path.join(cwd, 'src/Alert.ts')),
305
-
306
- createFile(path.join(outputDir, 'Alert.js')),
307
- createFile(path.join(outputDir, 'Alert.cjs')),
308
- ]);
309
-
310
- const { exports: packageExports } = await createPackageExports({
311
- exports: {
312
- './*': { 'mui-src': './src/*.ts', node: './src/node/*.ts' },
313
- },
314
- bundles,
315
- outputDir,
316
- cwd,
317
- isFlat: true,
318
- packageType: 'module',
319
- });
320
-
321
- expect(packageExports['./Alert']).toEqual({
322
- import: { node: './src/node/*.ts', default: './Alert.js' },
323
- require: { node: './src/node/*.ts', default: './Alert.cjs' },
324
- default: './Alert.js',
325
- });
276
+ const cwd = await makeTempDir();
277
+ const outputDir = path.join(cwd, 'build');
278
+ /**
279
+ * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
280
+ */
281
+ const bundles = [
282
+ { type: 'esm', dir: '.' },
283
+ { type: 'cjs', dir: '.' },
284
+ ];
285
+
286
+ await Promise.all([
287
+ createFile(path.join(cwd, 'src/Alert.ts')),
288
+
289
+ createFile(path.join(outputDir, 'Alert.js')),
290
+ createFile(path.join(outputDir, 'Alert.cjs')),
291
+ ]);
292
+
293
+ const { exports: packageExports } = await createPackageExports({
294
+ exports: {
295
+ './*': { 'mui-src': './src/*.ts', node: './src/node/*.ts' },
296
+ },
297
+ bundles,
298
+ outputDir,
299
+ cwd,
300
+ isFlat: true,
301
+ packageType: 'module',
302
+ });
303
+
304
+ expect(packageExports['./Alert']).toEqual({
305
+ import: { node: './src/node/*.ts', default: './Alert.js' },
306
+ require: { node: './src/node/*.ts', default: './Alert.cjs' },
307
+ default: './Alert.js',
326
308
  });
327
309
  });
328
310
 
329
311
  it('mixes glob and non-glob exports', async () => {
330
- await withTempDir(async (cwd) => {
331
- const outputDir = path.join(cwd, 'build');
332
- /**
333
- * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
334
- */
335
- const bundles = [
336
- { type: 'esm', dir: '.' },
337
- { type: 'cjs', dir: '.' },
338
- ];
339
-
340
- await Promise.all([
341
- createFile(path.join(cwd, 'src/index.ts')),
342
- createFile(path.join(cwd, 'src/Chip.ts')),
343
-
344
- createFile(path.join(outputDir, 'index.js')),
345
- createFile(path.join(outputDir, 'index.cjs')),
346
- createFile(path.join(outputDir, 'Chip.js')),
347
- createFile(path.join(outputDir, 'Chip.cjs')),
348
- ]);
349
-
350
- const { exports: packageExports } = await createPackageExports({
351
- exports: {
352
- '.': './src/index.ts',
353
- './*': './src/*.ts',
354
- },
355
- bundles,
356
- outputDir,
357
- cwd,
358
- isFlat: true,
359
- packageType: 'module',
360
- });
361
-
362
- // Explicit export still works
363
- expect(packageExports['.']).toBeDefined();
364
- // Glob-expanded export
365
- expect(packageExports['./Chip']).toEqual({
366
- import: './Chip.js',
367
- require: './Chip.cjs',
368
- default: './Chip.js',
369
- });
312
+ const cwd = await makeTempDir();
313
+ const outputDir = path.join(cwd, 'build');
314
+ /**
315
+ * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
316
+ */
317
+ const bundles = [
318
+ { type: 'esm', dir: '.' },
319
+ { type: 'cjs', dir: '.' },
320
+ ];
321
+
322
+ await Promise.all([
323
+ createFile(path.join(cwd, 'src/index.ts')),
324
+ createFile(path.join(cwd, 'src/Chip.ts')),
325
+
326
+ createFile(path.join(outputDir, 'index.js')),
327
+ createFile(path.join(outputDir, 'index.cjs')),
328
+ createFile(path.join(outputDir, 'Chip.js')),
329
+ createFile(path.join(outputDir, 'Chip.cjs')),
330
+ ]);
331
+
332
+ const { exports: packageExports } = await createPackageExports({
333
+ exports: {
334
+ '.': './src/index.ts',
335
+ './*': './src/*.ts',
336
+ },
337
+ bundles,
338
+ outputDir,
339
+ cwd,
340
+ isFlat: true,
341
+ packageType: 'module',
342
+ });
343
+
344
+ // Explicit export still works
345
+ expect(packageExports['.']).toBeDefined();
346
+ // Glob-expanded export
347
+ expect(packageExports['./Chip']).toEqual({
348
+ import: './Chip.js',
349
+ require: './Chip.cjs',
350
+ default: './Chip.js',
370
351
  });
371
352
  });
372
353
 
373
354
  it('expands glob with subdirectory pattern', async () => {
374
- await withTempDir(async (cwd) => {
375
- const outputDir = path.join(cwd, 'build');
376
- /**
377
- * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
378
- */
379
- const bundles = [
380
- { type: 'esm', dir: '.' },
381
- { type: 'cjs', dir: '.' },
382
- ];
383
-
384
- await Promise.all([
385
- createFile(path.join(cwd, 'src/utils/color.ts')),
386
- createFile(path.join(cwd, 'src/utils/size.ts')),
387
-
388
- createFile(path.join(outputDir, 'utils/color.js')),
389
- createFile(path.join(outputDir, 'utils/color.cjs')),
390
- createFile(path.join(outputDir, 'utils/size.js')),
391
- createFile(path.join(outputDir, 'utils/size.cjs')),
392
- ]);
393
-
394
- const { exports: packageExports } = await createPackageExports({
395
- exports: {
396
- './utils/*': './src/utils/*.ts',
397
- },
398
- bundles,
399
- outputDir,
400
- cwd,
401
- isFlat: true,
402
- packageType: 'module',
403
- });
404
-
405
- expect(packageExports['./utils/color']).toEqual({
406
- import: './utils/color.js',
407
- require: './utils/color.cjs',
408
- default: './utils/color.js',
409
- });
410
- expect(packageExports['./utils/size']).toEqual({
411
- import: './utils/size.js',
412
- require: './utils/size.cjs',
413
- default: './utils/size.js',
414
- });
355
+ const cwd = await makeTempDir();
356
+ const outputDir = path.join(cwd, 'build');
357
+ /**
358
+ * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
359
+ */
360
+ const bundles = [
361
+ { type: 'esm', dir: '.' },
362
+ { type: 'cjs', dir: '.' },
363
+ ];
364
+
365
+ await Promise.all([
366
+ createFile(path.join(cwd, 'src/utils/color.ts')),
367
+ createFile(path.join(cwd, 'src/utils/size.ts')),
368
+
369
+ createFile(path.join(outputDir, 'utils/color.js')),
370
+ createFile(path.join(outputDir, 'utils/color.cjs')),
371
+ createFile(path.join(outputDir, 'utils/size.js')),
372
+ createFile(path.join(outputDir, 'utils/size.cjs')),
373
+ ]);
374
+
375
+ const { exports: packageExports } = await createPackageExports({
376
+ exports: {
377
+ './utils/*': './src/utils/*.ts',
378
+ },
379
+ bundles,
380
+ outputDir,
381
+ cwd,
382
+ isFlat: true,
383
+ packageType: 'module',
384
+ });
385
+
386
+ expect(packageExports['./utils/color']).toEqual({
387
+ import: './utils/color.js',
388
+ require: './utils/color.cjs',
389
+ default: './utils/color.js',
390
+ });
391
+ expect(packageExports['./utils/size']).toEqual({
392
+ import: './utils/size.js',
393
+ require: './utils/size.cjs',
394
+ default: './utils/size.js',
415
395
  });
416
396
  });
417
397
 
418
398
  it('produces no entries when glob matches nothing', async () => {
419
- await withTempDir(async (cwd) => {
420
- const outputDir = path.join(cwd, 'build');
421
-
422
- // Create the src directory but no .ts files in it
423
- createFile(path.join(cwd, 'src/.gitkeep'));
424
-
425
- const { exports: packageExports } = await createPackageExports({
426
- exports: {
427
- './*': './src/*.ts',
428
- },
429
- bundles: [{ type: 'cjs', dir: '.' }],
430
- outputDir,
431
- cwd,
432
- isFlat: true,
433
- });
434
-
435
- // Only the default ./package.json entry should be present
436
- expect(Object.keys(packageExports)).toEqual(['./package.json']);
399
+ const cwd = await makeTempDir();
400
+ const outputDir = path.join(cwd, 'build');
401
+
402
+ // Create the src directory but no .ts files in it
403
+ createFile(path.join(cwd, 'src/.gitkeep'));
404
+
405
+ const { exports: packageExports } = await createPackageExports({
406
+ exports: {
407
+ './*': './src/*.ts',
408
+ },
409
+ bundles: [{ type: 'cjs', dir: '.' }],
410
+ outputDir,
411
+ cwd,
412
+ isFlat: true,
437
413
  });
414
+
415
+ // Only the default ./package.json entry should be present
416
+ expect(Object.keys(packageExports)).toEqual(['./package.json']);
438
417
  });
439
418
 
440
419
  it('expands globs in sorted order', async () => {
441
- await withTempDir(async (cwd) => {
442
- const outputDir = path.join(cwd, 'build');
443
-
444
- await Promise.all([
445
- createFile(path.join(cwd, 'src/Zebra.ts')),
446
- createFile(path.join(cwd, 'src/Apple.ts')),
447
- createFile(path.join(cwd, 'src/Mango.ts')),
448
-
449
- createFile(path.join(outputDir, 'Zebra.js')),
450
- createFile(path.join(outputDir, 'Apple.js')),
451
- createFile(path.join(outputDir, 'Mango.js')),
452
- ]);
453
-
454
- const { exports: packageExports } = await createPackageExports({
455
- exports: {
456
- './*': './src/*.ts',
457
- },
458
- bundles: [{ type: 'cjs', dir: '.' }],
459
- outputDir,
460
- cwd,
461
- isFlat: true,
462
- });
463
-
464
- const exportKeys = Object.keys(packageExports).filter((k) => k !== './package.json');
465
- expect(exportKeys).toEqual(['./Apple', './Mango', './Zebra']);
420
+ const cwd = await makeTempDir();
421
+ const outputDir = path.join(cwd, 'build');
422
+
423
+ await Promise.all([
424
+ createFile(path.join(cwd, 'src/Zebra.ts')),
425
+ createFile(path.join(cwd, 'src/Apple.ts')),
426
+ createFile(path.join(cwd, 'src/Mango.ts')),
427
+
428
+ createFile(path.join(outputDir, 'Zebra.js')),
429
+ createFile(path.join(outputDir, 'Apple.js')),
430
+ createFile(path.join(outputDir, 'Mango.js')),
431
+ ]);
432
+
433
+ const { exports: packageExports } = await createPackageExports({
434
+ exports: {
435
+ './*': './src/*.ts',
436
+ },
437
+ bundles: [{ type: 'cjs', dir: '.' }],
438
+ outputDir,
439
+ cwd,
440
+ isFlat: true,
466
441
  });
442
+
443
+ const exportKeys = Object.keys(packageExports).filter((k) => k !== './package.json');
444
+ expect(exportKeys).toEqual(['./Apple', './Mango', './Zebra']);
467
445
  });
468
446
 
469
447
  it('removes expanded entries matching a null-valued glob (negation)', async () => {
470
- await withTempDir(async (cwd) => {
471
- const outputDir = path.join(cwd, 'build');
472
- /**
473
- * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
474
- */
475
- const bundles = [
476
- { type: 'esm', dir: '.' },
477
- { type: 'cjs', dir: '.' },
478
- ];
479
-
480
- await Promise.all([
481
- createFile(path.join(cwd, 'src/Accordion.ts')),
482
- createFile(path.join(cwd, 'src/Button.ts')),
483
- createFile(path.join(cwd, 'src/ButtonBase.ts')),
484
-
485
- createFile(path.join(outputDir, 'Accordion.js')),
486
- createFile(path.join(outputDir, 'Accordion.cjs')),
487
- createFile(path.join(outputDir, 'Button.js')),
488
- createFile(path.join(outputDir, 'Button.cjs')),
489
- createFile(path.join(outputDir, 'ButtonBase.js')),
490
- createFile(path.join(outputDir, 'ButtonBase.cjs')),
491
- ]);
492
-
493
- const { exports: packageExports } = await createPackageExports({
494
- exports: {
495
- './*': './src/*.ts',
496
- './Button*': null,
497
- },
498
- bundles,
499
- outputDir,
500
- cwd,
501
- isFlat: true,
502
- packageType: 'module',
503
- });
504
-
505
- expect(packageExports['./Accordion']).toBeDefined();
506
- expect(packageExports['./Button']).toBeUndefined();
507
- expect(packageExports['./ButtonBase']).toBeUndefined();
508
- // The negation glob key itself should not appear
509
- expect(packageExports['./Button*']).toBeUndefined();
448
+ const cwd = await makeTempDir();
449
+ const outputDir = path.join(cwd, 'build');
450
+ /**
451
+ * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
452
+ */
453
+ const bundles = [
454
+ { type: 'esm', dir: '.' },
455
+ { type: 'cjs', dir: '.' },
456
+ ];
457
+
458
+ await Promise.all([
459
+ createFile(path.join(cwd, 'src/Accordion.ts')),
460
+ createFile(path.join(cwd, 'src/Button.ts')),
461
+ createFile(path.join(cwd, 'src/ButtonBase.ts')),
462
+
463
+ createFile(path.join(outputDir, 'Accordion.js')),
464
+ createFile(path.join(outputDir, 'Accordion.cjs')),
465
+ createFile(path.join(outputDir, 'Button.js')),
466
+ createFile(path.join(outputDir, 'Button.cjs')),
467
+ createFile(path.join(outputDir, 'ButtonBase.js')),
468
+ createFile(path.join(outputDir, 'ButtonBase.cjs')),
469
+ ]);
470
+
471
+ const { exports: packageExports } = await createPackageExports({
472
+ exports: {
473
+ './*': './src/*.ts',
474
+ './Button*': null,
475
+ },
476
+ bundles,
477
+ outputDir,
478
+ cwd,
479
+ isFlat: true,
480
+ packageType: 'module',
510
481
  });
482
+
483
+ expect(packageExports['./Accordion']).toBeDefined();
484
+ expect(packageExports['./Button']).toBeUndefined();
485
+ expect(packageExports['./ButtonBase']).toBeUndefined();
486
+ // The negation glob key itself should not appear
487
+ expect(packageExports['./Button*']).toBeUndefined();
511
488
  });
512
489
 
513
490
  it('negation with null removes only matching keys', async () => {
514
- await withTempDir(async (cwd) => {
515
- const outputDir = path.join(cwd, 'build');
516
-
517
- await Promise.all([
518
- createFile(path.join(cwd, 'src/Alert.ts')),
519
- createFile(path.join(cwd, 'src/AlertTitle.ts')),
520
- createFile(path.join(cwd, 'src/Button.ts')),
521
-
522
- createFile(path.join(outputDir, 'Alert.js')),
523
- createFile(path.join(outputDir, 'AlertTitle.js')),
524
- createFile(path.join(outputDir, 'Button.js')),
525
- ]);
526
-
527
- const { exports: packageExports } = await createPackageExports({
528
- exports: {
529
- './*': './src/*.ts',
530
- './Alert*': null,
531
- },
532
- bundles: [{ type: 'cjs', dir: '.' }],
533
- outputDir,
534
- cwd,
535
- isFlat: true,
536
- });
537
-
538
- const exportKeys = Object.keys(packageExports).filter((k) => k !== './package.json');
539
- expect(exportKeys).toEqual(['./Button']);
491
+ const cwd = await makeTempDir();
492
+ const outputDir = path.join(cwd, 'build');
493
+
494
+ await Promise.all([
495
+ createFile(path.join(cwd, 'src/Alert.ts')),
496
+ createFile(path.join(cwd, 'src/AlertTitle.ts')),
497
+ createFile(path.join(cwd, 'src/Button.ts')),
498
+
499
+ createFile(path.join(outputDir, 'Alert.js')),
500
+ createFile(path.join(outputDir, 'AlertTitle.js')),
501
+ createFile(path.join(outputDir, 'Button.js')),
502
+ ]);
503
+
504
+ const { exports: packageExports } = await createPackageExports({
505
+ exports: {
506
+ './*': './src/*.ts',
507
+ './Alert*': null,
508
+ },
509
+ bundles: [{ type: 'cjs', dir: '.' }],
510
+ outputDir,
511
+ cwd,
512
+ isFlat: true,
540
513
  });
514
+
515
+ const exportKeys = Object.keys(packageExports).filter((k) => k !== './package.json');
516
+ expect(exportKeys).toEqual(['./Button']);
541
517
  });
542
518
 
543
519
  it('preserves null glob pattern when no keys match', async () => {
544
- await withTempDir(async (cwd) => {
545
- const outputDir = path.join(cwd, 'build');
546
-
547
- await Promise.all([
548
- createFile(path.join(cwd, 'src/Button.ts')),
549
- createFile(path.join(outputDir, 'Button.js')),
550
- ]);
551
-
552
- const { exports: packageExports } = await createPackageExports({
553
- exports: {
554
- './*': './src/*.ts',
555
- './internal/*': null,
556
- },
557
- bundles: [{ type: 'cjs', dir: '.' }],
558
- outputDir,
559
- cwd,
560
- isFlat: true,
561
- });
562
-
563
- // Button is kept since it doesn't match the negation
564
- expect(packageExports['./Button']).toBeDefined();
565
- // The negation pattern is preserved as null since nothing matched it
566
- expect(packageExports['./internal/*']).toBeNull();
520
+ const cwd = await makeTempDir();
521
+ const outputDir = path.join(cwd, 'build');
522
+
523
+ await Promise.all([
524
+ createFile(path.join(cwd, 'src/Button.ts')),
525
+ createFile(path.join(outputDir, 'Button.js')),
526
+ ]);
527
+
528
+ const { exports: packageExports } = await createPackageExports({
529
+ exports: {
530
+ './*': './src/*.ts',
531
+ './internal/*': null,
532
+ },
533
+ bundles: [{ type: 'cjs', dir: '.' }],
534
+ outputDir,
535
+ cwd,
536
+ isFlat: true,
567
537
  });
538
+
539
+ // Button is kept since it doesn't match the negation
540
+ expect(packageExports['./Button']).toBeDefined();
541
+ // The negation pattern is preserved as null since nothing matched it
542
+ expect(packageExports['./internal/*']).toBeNull();
568
543
  });
569
544
 
570
545
  it('does not expand glob patterns when isFlat is false', async () => {
571
- await withTempDir(async (cwd) => {
572
- const outputDir = path.join(cwd, 'build');
573
-
574
- await Promise.all([
575
- createFile(path.join(cwd, 'src/Button.ts')),
576
- createFile(path.join(cwd, 'src/TextField.ts')),
577
- ]);
578
-
579
- const { exports: packageExports } = await createPackageExports({
580
- exports: {
581
- './*': './src/*.ts',
582
- },
583
- bundles: [{ type: 'cjs', dir: '.' }],
584
- outputDir,
585
- cwd,
586
- isFlat: false,
587
- });
588
-
589
- // Glob should NOT be expanded to individual files
590
- expect(packageExports['./Button']).toBeUndefined();
591
- expect(packageExports['./TextField']).toBeUndefined();
592
- // The raw glob pattern is passed through as-is
593
- expect(packageExports['./*']).toEqual({
594
- require: './*.js',
595
- default: './*.js',
596
- });
546
+ const cwd = await makeTempDir();
547
+ const outputDir = path.join(cwd, 'build');
548
+
549
+ await Promise.all([
550
+ createFile(path.join(cwd, 'src/Button.ts')),
551
+ createFile(path.join(cwd, 'src/TextField.ts')),
552
+ ]);
553
+
554
+ const { exports: packageExports } = await createPackageExports({
555
+ exports: {
556
+ './*': './src/*.ts',
557
+ },
558
+ bundles: [{ type: 'cjs', dir: '.' }],
559
+ outputDir,
560
+ cwd,
561
+ isFlat: false,
597
562
  });
598
- });
599
563
 
600
- it('passes through glob key when value has no wildcard', async () => {
601
- await withTempDir(async (cwd) => {
602
- const outputDir = path.join(cwd, 'build');
603
-
604
- await Promise.all([
605
- createFile(path.join(cwd, 'src/index.ts')),
606
- createFile(path.join(outputDir, 'index.js')),
607
- ]);
608
-
609
- const { exports: packageExports } = await createPackageExports({
610
- exports: {
611
- './*': './src/index.ts',
612
- },
613
- bundles: [{ type: 'cjs', dir: '.' }],
614
- outputDir,
615
- cwd,
616
- isFlat: true,
617
- });
618
-
619
- // When the value has no *, the glob key is passed through as-is
620
- expect(packageExports['./*']).toBeDefined();
564
+ // Glob should NOT be expanded to individual files
565
+ expect(packageExports['./Button']).toBeUndefined();
566
+ expect(packageExports['./TextField']).toBeUndefined();
567
+ // The raw glob pattern is passed through as-is
568
+ expect(packageExports['./*']).toEqual({
569
+ require: './*.js',
570
+ default: './*.js',
621
571
  });
622
572
  });
623
- });
624
573
 
625
- it('uses require/import and default for single bundle package', async () => {
626
- await withTempDir(async (cwd) => {
574
+ it('passes through glob key when value has no wildcard', async () => {
575
+ const cwd = await makeTempDir();
627
576
  const outputDir = path.join(cwd, 'build');
628
577
 
629
578
  await Promise.all([
630
579
  createFile(path.join(cwd, 'src/index.ts')),
631
580
  createFile(path.join(outputDir, 'index.js')),
632
- createFile(path.join(outputDir, 'index.d.ts')),
633
581
  ]);
634
582
 
635
583
  const { exports: packageExports } = await createPackageExports({
636
584
  exports: {
637
- '.': './src/index.ts',
585
+ './*': './src/index.ts',
638
586
  },
639
587
  bundles: [{ type: 'cjs', dir: '.' }],
640
588
  outputDir,
641
589
  cwd,
642
- addTypes: true,
643
590
  isFlat: true,
644
- packageType: 'commonjs',
645
591
  });
646
592
 
647
- // Single CJS bundle should have both require and default pointing to the same files
648
- expect(packageExports['.']).toEqual({
649
- require: {
650
- types: './index.d.ts',
651
- default: './index.js',
652
- },
653
- default: {
654
- types: './index.d.ts',
655
- default: './index.js',
656
- },
657
- });
593
+ // When the value has no *, the glob key is passed through as-is
594
+ expect(packageExports['./*']).toBeDefined();
595
+ });
596
+ });
597
+
598
+ it('uses require/import and default for single bundle package', async () => {
599
+ const cwd = await makeTempDir();
600
+ const outputDir = path.join(cwd, 'build');
601
+
602
+ await Promise.all([
603
+ createFile(path.join(cwd, 'src/index.ts')),
604
+ createFile(path.join(outputDir, 'index.js')),
605
+ createFile(path.join(outputDir, 'index.d.ts')),
606
+ ]);
607
+
608
+ const { exports: packageExports } = await createPackageExports({
609
+ exports: {
610
+ '.': './src/index.ts',
611
+ },
612
+ bundles: [{ type: 'cjs', dir: '.' }],
613
+ outputDir,
614
+ cwd,
615
+ addTypes: true,
616
+ isFlat: true,
617
+ packageType: 'commonjs',
618
+ });
619
+
620
+ // Single CJS bundle should have both require and default pointing to the same files
621
+ expect(packageExports['.']).toEqual({
622
+ require: {
623
+ types: './index.d.ts',
624
+ default: './index.js',
625
+ },
626
+ default: {
627
+ types: './index.d.ts',
628
+ default: './index.js',
629
+ },
658
630
  });
659
631
  });
660
632
  });
661
633
 
662
634
  describe('createPackageBin', () => {
663
635
  it('prefers the ESM bundle when available', async () => {
664
- await withTempDir(async (cwd) => {
665
- /**
666
- * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
667
- */
668
- const bundles = [
669
- { type: 'esm', dir: '.' },
670
- { type: 'cjs', dir: '.' },
671
- ];
672
-
673
- await Promise.all([createFile(path.join(cwd, 'src/cli.ts'))]);
674
-
675
- let bin = await createPackageBin({
676
- bin: './src/cli.ts',
677
- bundles,
678
- cwd,
679
- isFlat: true,
680
- packageType: 'module',
681
- });
682
-
683
- expect(bin).toBe('./cli.js');
636
+ const cwd = await makeTempDir();
637
+ /**
638
+ * @type {{ type: import('./build.mjs').BundleType; dir: string }[]}
639
+ */
640
+ const bundles = [
641
+ { type: 'esm', dir: '.' },
642
+ { type: 'cjs', dir: '.' },
643
+ ];
644
+
645
+ await Promise.all([createFile(path.join(cwd, 'src/cli.ts'))]);
646
+
647
+ let bin = await createPackageBin({
648
+ bin: './src/cli.ts',
649
+ bundles,
650
+ cwd,
651
+ isFlat: true,
652
+ packageType: 'module',
653
+ });
684
654
 
685
- bin = await createPackageBin({
686
- bin: './src/cli.ts',
687
- bundles: [bundles[1]], // only CJS bundle
688
- cwd,
689
- isFlat: true,
690
- });
655
+ expect(bin).toBe('./cli.js');
691
656
 
692
- expect(bin).toBe('./cli.js');
657
+ bin = await createPackageBin({
658
+ bin: './src/cli.ts',
659
+ bundles: [bundles[1]], // only CJS bundle
660
+ cwd,
661
+ isFlat: true,
662
+ });
693
663
 
694
- bin = await createPackageBin({
695
- bin: './src/cli.ts',
696
- bundles, // only CJS bundle
697
- cwd,
698
- isFlat: true,
699
- packageType: 'commonjs',
700
- });
664
+ expect(bin).toBe('./cli.js');
701
665
 
702
- expect(bin).toBe('./cli.mjs');
666
+ bin = await createPackageBin({
667
+ bin: './src/cli.ts',
668
+ bundles, // only CJS bundle
669
+ cwd,
670
+ isFlat: true,
671
+ packageType: 'commonjs',
703
672
  });
673
+
674
+ expect(bin).toBe('./cli.mjs');
704
675
  });
705
676
  });