also looking at this
fix(generator): skip glob and relative entrypoints outside the root
#3126
3 files
+74
-2
| @@ -0,0 +1,64 @@ | ||
| 1 | /** | |
| 2 | * An entrypoint pattern reaching above the root wrote its declarations outside | |
| 3 | * outdir: | |
| 4 | * | |
| 5 | * generate({ root: 'src', outdir: 'dist', entrypoints: ['../*.ts'] }) | |
| 6 | * | |
| 7 | * wrote `outside.d.ts` next to `outside.ts`, and `../outside.ts` did the same. | |
| 8 | * An absolute path outside the root was already skipped with a warning; a | |
| 9 | * glob or relative pattern now is too. | |
| 10 | */ | |
| 11 | import { afterEach, describe, expect, it } from 'bun:test' | |
| 12 | import { existsSync } from 'node:fs' | |
| 13 | import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' | |
| 14 | import { tmpdir } from 'node:os' | |
| 15 | import { join } from 'node:path' | |
| 16 | import { generate } from '../src/generator' | |
| 17 | ||
| 18 | const tempDirectories: string[] = [] | |
| 19 | ||
| 20 | afterEach(async () => { | |
| 21 | await Promise.all(tempDirectories.splice(0).map(dir => rm(dir, { recursive: true, force: true }))) | |
| 22 | }) | |
| 23 | ||
| 24 | /** A project with `src/inside.ts` and `outside.ts` next to `src`. */ | |
| 25 | async function project(): Promise<string> { | |
| 26 | const cwd = await mkdtemp(join(tmpdir(), 'dtsx-outside-root-')) | |
| 27 | tempDirectories.push(cwd) | |
| 28 | await mkdir(join(cwd, 'src')) | |
| 29 | await writeFile(join(cwd, 'src', 'inside.ts'), 'export const inside = 1\n') | |
| 30 | await writeFile(join(cwd, 'outside.ts'), 'export const outside = 2\n') | |
| 31 | return cwd | |
| 32 | } | |
| 33 | ||
| 34 | describe('entrypoints outside the root', () => { | |
| 35 | it.each([ | |
| 36 | ['glob', ['../*.ts']], | |
| 37 | ['relative path', ['../outside.ts']], | |
| 38 | ])('are not written outside outdir: %s', async (_label, entrypoints) => { | |
| 39 | const cwd = await project() | |
| 40 | await expect(generate({ cwd, root: 'src', outdir: 'dist', entrypoints, clean: false })).rejects.toThrow('No source files matched') | |
| 41 | expect(existsSync(join(cwd, 'outside.d.ts'))).toBe(false) | |
| 42 | expect(existsSync(join(cwd, 'dist', 'outside.d.ts'))).toBe(false) | |
| 43 | }) | |
| 44 | ||
| 45 | it('are skipped beside an entrypoint inside the root', async () => { | |
| 46 | const cwd = await project() | |
| 47 | await generate({ cwd, root: 'src', outdir: 'dist', entrypoints: ['*.ts', '../*.ts'], clean: false }) | |
| 48 | expect(existsSync(join(cwd, 'outside.d.ts'))).toBe(false) | |
| 49 | expect(existsSync(join(cwd, 'dist', 'outside.d.ts'))).toBe(false) | |
| 50 | expect(existsSync(join(cwd, 'dist', 'inside.d.ts'))).toBe(true) | |
| 51 | }) | |
| 52 | ||
| 53 | it('are written into outdir with a flat output structure', async () => { | |
| 54 | const cwd = await project() | |
| 55 | await generate({ cwd, root: 'src', outdir: 'dist', entrypoints: ['../*.ts'], outputStructure: 'flat', clean: false }) | |
| 56 | expect(existsSync(join(cwd, 'outside.d.ts'))).toBe(false) | |
| 57 | expect(existsSync(join(cwd, 'dist', 'outside.d.ts'))).toBe(true) | |
| 58 | }) | |
| 59 | ||
| 60 | it('still fail when an exclude leaves nothing', async () => { | |
| 61 | const cwd = await project() | |
| 62 | await expect(generate({ cwd, root: 'src', outdir: 'dist', entrypoints: ['../*.ts'], exclude: ['../*.ts'], outputStructure: 'flat', clean: false })).rejects.toThrow('No source files matched') | |
| 63 | }) | |
| 64 | }) | |