also looking at this
fix(bundle): leave template literal text alone when renaming identifiers
#3131
3 files
+108
-3
| @@ -461,6 +461,58 @@ describe('generate with bundle: true', () => { | ||
| 461 | 461 | await rm(dir, { recursive: true, force: true }) |
| 462 | 462 | }) |
| 463 | 463 | |
| 464 | // Renaming a linked name (`enabled` to the default export's helper, a | |
| 465 | // colliding `Options` to `Options_1`) also rewrote the same word inside | |
| 466 | // template literal types, changing what they accept. | |
| 467 | it('keeps template literal text when renaming', async () => { | |
| 468 | const dir = await mkdtemp(join(tmpdir(), 'dtsx-bundle-template-')) | |
| 469 | await writeFiles(dir, { | |
| 470 | 'src/index.ts': [ | |
| 471 | `import enabled from './flag'`, | |
| 472 | `export * from './labels'`, | |
| 473 | `export type Options = 'x' | 'y'`, | |
| 474 | 'export type Status = `enabled` | `Options`', | |
| 475 | `export function isEnabled(): number { return Number(enabled) }`, | |
| 476 | ].join('\n'), | |
| 477 | 'src/flag.ts': `export default 1`, | |
| 478 | 'src/labels.ts': [ | |
| 479 | `type Options = 'a' | 'b'`, | |
| 480 | 'export type Label = `Options-${Options}`', | |
| 481 | ].join('\n'), | |
| 482 | 'consumer.ts': [ | |
| 483 | `import { isEnabled, type Label, type Options, type Status } from './dist/index'`, | |
| 484 | `const status: Status = 'enabled'`, | |
| 485 | `const other: Status = 'Options'`, | |
| 486 | `const label: Label = 'Options-a'`, | |
| 487 | `const option: Options = 'x'`, | |
| 488 | `export { status, other, label, option, isEnabled }`, | |
| 489 | ].join('\n'), | |
| 490 | }) | |
| 491 | ||
| 492 | await generate({ | |
| 493 | cwd: dir, | |
| 494 | root: 'src', | |
| 495 | entrypoints: ['index.ts'], | |
| 496 | outdir: join(dir, 'dist'), | |
| 497 | clean: false, | |
| 498 | keepComments: false, | |
| 499 | tsconfigPath: '', | |
| 500 | verbose: false, | |
| 501 | bundle: true, | |
| 502 | }) | |
| 503 | const bundled = await Bun.file(join(dir, 'dist', 'index.d.ts')).text() | |
| 504 | ||
| 505 | expect(bundled).toContain('type Status = `enabled` | `Options`;') | |
| 506 | expect(bundled).toContain('type Label = `Options-${Options_1}`;') | |
| 507 | ||
| 508 | if (tscAvailable) { | |
| 509 | const result = runTsc(dir, ['consumer.ts']) | |
| 510 | expect(result.output).toBe('') | |
| 511 | expect(result.ok).toBe(true) | |
| 512 | } | |
| 513 | await rm(dir, { recursive: true, force: true }) | |
| 514 | }) | |
| 515 | ||
| 464 | 516 | it('writes one bundled file per entrypoint', async () => { |
| 465 | 517 | await writeFiles(TMP, { |
| 466 | 518 | 'src/index.ts': `export * from './router';`, |