Files
core2026/tools/build-scripts/emit-declarations.test.mjs
T

74 lines
3.6 KiB
JavaScript

import assert from 'node:assert/strict';
import { mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
import path from 'node:path';
import test from 'node:test';
import { execFileSync } from 'node:child_process';
import { pathToFileURL } from 'node:url';
import { emitDeclarations } from './emit-declarations.mjs';
const workspaceRoot = path.resolve(import.meta.dirname, '../..');
test('native declarations preserve relative imports, subpaths and maps, and fail on type errors', async () => {
const temporaryRoot = path.join(workspaceRoot, '.turbo');
await mkdir(temporaryRoot, { recursive: true });
const fixture = await mkdtemp(path.join(temporaryRoot, 'declaration-test-'));
const outDir = path.join(fixture, 'dist');
try {
await mkdir(path.join(fixture, 'src'));
await writeFile(path.join(fixture, 'package.json'), JSON.stringify({ type: 'module' }));
await writeFile(
path.join(fixture, 'tsconfig.build.json'),
JSON.stringify({
extends: path.join(workspaceRoot, 'tsconfig.base.json'),
compilerOptions: { rootDir: 'src', outDir: 'dist' },
include: ['src'],
})
);
await writeFile(
path.join(fixture, 'src/model.ts'),
'export class Model { private readonly id = 1; getId(): number { return this.id; } }\n'
);
await writeFile(path.join(fixture, 'src/index.ts'), "export { Model } from './model.js';\n");
await emitDeclarations({ options: { cwd: fixture, outDir } });
assert.match(await readFile(path.join(outDir, 'index.d.ts'), 'utf8'), /from ['"]\.\/model\.js['"]/u);
assert.match(await readFile(path.join(outDir, 'model.d.ts'), 'utf8'), /getId\(\): number/u);
const map = JSON.parse(await readFile(path.join(outDir, 'model.d.ts.map'), 'utf8'));
assert.deepEqual(map.sources, ['../src/model.ts']);
await assert.rejects(readFile(path.join(outDir, 'index.js')), { code: 'ENOENT' });
await writeFile(
path.join(fixture, 'package.json'),
JSON.stringify({ type: 'module', exports: { './*': './dist/src/*' } })
);
await emitDeclarations({ options: { cwd: fixture, outDir } });
assert.equal(await readFile(path.join(outDir, 'index.d.ts'), 'utf8'), "export * from './src/index.js';\n");
const { Model } = await import(pathToFileURL(path.join(outDir, 'src/model.js')).href);
assert.equal(new Model().getId(), 1);
await readFile(path.join(outDir, 'src/model.d.ts.map'));
await readFile(path.join(outDir, 'src/model.js.map'));
await writeFile(
path.join(fixture, 'consumer.ts'),
"import { Model } from './dist/index.js';\n" +
"import { Model as SubpathModel } from './dist/src/model.js';\n" +
'export const same: Model = new SubpathModel();\n'
);
await writeFile(
path.join(fixture, 'tsconfig.consumer.json'),
JSON.stringify({ extends: path.join(workspaceRoot, 'tsconfig.base.json'), files: ['consumer.ts'] })
);
execFileSync(
'pnpm',
['-w', 'tsc7', '-p', path.join(fixture, 'tsconfig.consumer.json'), '--noEmit', '--types', 'node'],
{
cwd: fixture,
stdio: 'pipe',
}
);
await writeFile(path.join(fixture, 'src/model.ts'), 'export const id: number = "invalid";\n');
await assert.rejects(emitDeclarations({ options: { cwd: fixture, outDir } }), /Declaration emission failed/u);
} finally {
await rm(fixture, { recursive: true, force: true });
}
});