diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0aadf9..5ffee54 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,9 @@ jobs: matrix: node-version: [18.x, 20.x, 21.x] os: [ubuntu-latest, windows-latest] + exclude: + - os: windows-latest + node-version: 21.x steps: - uses: actions/checkout@v4 diff --git a/fixtures/monorepo/package-lock.json b/fixtures/monorepo/package-lock.json new file mode 100644 index 0000000..244287a --- /dev/null +++ b/fixtures/monorepo/package-lock.json @@ -0,0 +1,35 @@ +{ + "name": "project-build", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "project-build", + "version": "1.0.0", + "license": "ISC", + "workspaces": [ + "package*" + ] + }, + "node_modules/package1": { + "resolved": "package1", + "link": true + }, + "node_modules/package2": { + "resolved": "package2", + "link": true + }, + "package1": { + "version": "1.0.0", + "license": "ISC" + }, + "package2": { + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "package1": "file:../package1" + } + } + } +} diff --git a/fixtures/monorepo/package.json b/fixtures/monorepo/package.json new file mode 100644 index 0000000..3f2d277 --- /dev/null +++ b/fixtures/monorepo/package.json @@ -0,0 +1,15 @@ +{ + "name": "project-build", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "workspaces": [ + "package*" + ], + "license": "ISC" +} diff --git a/fixtures/monorepo/package1/package.json b/fixtures/monorepo/package1/package.json new file mode 100644 index 0000000..13423f6 --- /dev/null +++ b/fixtures/monorepo/package1/package.json @@ -0,0 +1,13 @@ +{ + "name": "package1", + "version": "1.0.0", + "description": "", + "main": "dist/src/lib/add.js", + "types": "dist/src/lib/add.d.ts", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/fixtures/monorepo/package1/src/lib/add.ts b/fixtures/monorepo/package1/src/lib/add.ts new file mode 100644 index 0000000..95c44a7 --- /dev/null +++ b/fixtures/monorepo/package1/src/lib/add.ts @@ -0,0 +1,4 @@ + +export function add (x: number, y: number): number { + return x + y +} diff --git a/fixtures/monorepo/package1/src/test/add.test.ts b/fixtures/monorepo/package1/src/test/add.test.ts new file mode 100644 index 0000000..efd7568 --- /dev/null +++ b/fixtures/monorepo/package1/src/test/add.test.ts @@ -0,0 +1,7 @@ +import { test } from 'node:test' +import { add } from '../lib/add.js' +import { strictEqual } from 'node:assert' + +test('add', () => { + strictEqual(add(1, 2), 3) +}) diff --git a/fixtures/monorepo/package1/src/test/add2.test.ts b/fixtures/monorepo/package1/src/test/add2.test.ts new file mode 100644 index 0000000..d938558 --- /dev/null +++ b/fixtures/monorepo/package1/src/test/add2.test.ts @@ -0,0 +1,7 @@ +import { test } from 'node:test' +import { add } from '../lib/add.js' +import { strictEqual } from 'node:assert' + +test('add2', () => { + strictEqual(add(3, 2), 5) +}) diff --git a/fixtures/monorepo/package1/tsconfig.json b/fixtures/monorepo/package1/tsconfig.json new file mode 100644 index 0000000..305bde5 --- /dev/null +++ b/fixtures/monorepo/package1/tsconfig.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist" + }, + "references": [ + ] + } + \ No newline at end of file diff --git a/fixtures/monorepo/package2/package.json b/fixtures/monorepo/package2/package.json new file mode 100644 index 0000000..5965e85 --- /dev/null +++ b/fixtures/monorepo/package2/package.json @@ -0,0 +1,15 @@ +{ + "name": "package2", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "dependencies": { + "package1": "file:../package1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/fixtures/monorepo/package2/src/lib/add.ts b/fixtures/monorepo/package2/src/lib/add.ts new file mode 100644 index 0000000..9987d46 --- /dev/null +++ b/fixtures/monorepo/package2/src/lib/add.ts @@ -0,0 +1,4 @@ +import { add as add2 } from 'package1' +export function add (x: number, y: number): number { + return add2(x, y) +} diff --git a/fixtures/monorepo/package2/src/test/add.test.ts b/fixtures/monorepo/package2/src/test/add.test.ts new file mode 100644 index 0000000..2fd45fc --- /dev/null +++ b/fixtures/monorepo/package2/src/test/add.test.ts @@ -0,0 +1,7 @@ +import { test } from 'node:test' +import { add } from '../lib/add.js' +import { strictEqual } from 'node:assert' + +test('package2-add', () => { + strictEqual(add(1, 2), 3) +}) diff --git a/fixtures/monorepo/package2/src/test/add2.test.ts b/fixtures/monorepo/package2/src/test/add2.test.ts new file mode 100644 index 0000000..89e190c --- /dev/null +++ b/fixtures/monorepo/package2/src/test/add2.test.ts @@ -0,0 +1,7 @@ +import { test } from 'node:test' +import { add } from '../lib/add.js' +import { strictEqual } from 'node:assert' + +test('package2-add2', () => { + strictEqual(add(3, 2), 5) +}) diff --git a/fixtures/monorepo/package2/tsconfig.json b/fixtures/monorepo/package2/tsconfig.json new file mode 100644 index 0000000..df3ecf5 --- /dev/null +++ b/fixtures/monorepo/package2/tsconfig.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist" + }, + "references": [ + { "path": "../package1" } + ] + } + \ No newline at end of file diff --git a/fixtures/monorepo/tsconfig.base.json b/fixtures/monorepo/tsconfig.base.json new file mode 100644 index 0000000..9e6283c --- /dev/null +++ b/fixtures/monorepo/tsconfig.base.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "sourceMap": true, + "target": "ES2022", + "composite": true, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "esModuleInterop": true, + "strict": true, + "resolveJsonModule": true, + "removeComments": true, + "newLine": "lf", + "noUnusedLocals": true, + "noFallthroughCasesInSwitch": true, + "isolatedModules": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "lib": [ + "ESNext" + ], + "incremental": true + } +} diff --git a/fixtures/monorepo/tsconfig.json b/fixtures/monorepo/tsconfig.json new file mode 100644 index 0000000..22054e7 --- /dev/null +++ b/fixtures/monorepo/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "package1" }, + { "path": "package2" } + ] +} diff --git a/lib/run.js b/lib/run.js index e7a9841..90cd231 100644 --- a/lib/run.js +++ b/lib/run.js @@ -27,8 +27,10 @@ export default async function runWithTypeScript (config) { let prefix = '' let tscPath + const typescriptCliArgs = [] if (tsconfigPath && config.typescript !== false) { + const tsconfig = JSON.parse(await readFile(tsconfigPath)) const _require = createRequire(tsconfigPath) const typescriptPathCWD = _require.resolve('typescript') tscPath = join(typescriptPathCWD, '..', '..', 'bin', 'tsc') @@ -38,19 +40,22 @@ export default async function runWithTypeScript (config) { // Watch is handled aftterwards if (!config.watch) { + if (Array.isArray(tsconfig.references) && tsconfig.references.length > 0) { + typescriptCliArgs.push('--build') + } const start = Date.now() - await execa('node', [tscPath], { cwd: dirname(tsconfigPath) }) + await execa('node', [tscPath, ...typescriptCliArgs], { cwd: dirname(tsconfigPath) }) process.stdout.write(`TypeScript compilation complete (${Date.now() - start}ms)\n`) pushable.push({ type: 'test:diagnostic', data: { nesting: 0, - message: `TypeScript compilation complete (${Date.now() - start}ms)` + message: `TypeScript compilation complete (${Date.now() - start}ms)`, + typescriptCliArgs } }) } } - const tsconfig = JSON.parse(await readFile(tsconfigPath)) const outDir = tsconfig.compilerOptions.outDir if (outDir) { prefix = join(dirname(tsconfigPath), outDir) @@ -83,17 +88,21 @@ export default async function runWithTypeScript (config) { let p if (config.watch) { + typescriptCliArgs.push('--watch') p = deferred() - const start = Date.now() - tscChild = execa('node', [tscPath, '--watch'], { cwd }) + let start = Date.now() + tscChild = execa('node', [tscPath, ...typescriptCliArgs], { cwd }) tscChild.stdout.setEncoding('utf8') tscChild.stdout.on('data', (data) => { - if (data.includes('Watching for file changes')) { + if (data.includes('File change detected')) { + start = Date.now() + } else if (data.includes('Watching for file changes')) { pushable.push({ type: 'test:diagnostic', data: { nesting: 0, - message: `TypeScript compilation complete (${Date.now() - start}ms)` + message: `TypeScript compilation complete (${Date.now() - start}ms)`, + typescriptCliArgs } }) diff --git a/test/basic.test.js b/test/basic.test.js index 3972300..6885c62 100644 --- a/test/basic.test.js +++ b/test/basic.test.js @@ -2,6 +2,7 @@ import { test } from 'node:test' import { tspl } from '@matteo.collina/tspl' import runWithTypeScript from '../lib/run.js' import { join } from 'desm' +import { execa } from 'execa' test('ts-esm', async (t) => { const { strictEqual, completed, match } = tspl(t, { plan: 4 }) @@ -141,7 +142,31 @@ test('src-to-dist', async (t) => { await completed }) +test('monorepo', async (t) => { + const { strictEqual, completed, match, deepEqual } = tspl(t, { plan: 5 }) + const config = { + files: [], + cwd: join(import.meta.url, '..', 'fixtures', 'monorepo/package2') + } + + await execa('npm', ['install'], { cwd: join(import.meta.url, '..', 'fixtures', 'monorepo') }) + const stream = await runWithTypeScript(config) + + const names = new Set(['package2-add', 'package2-add2']) + + stream.once('data', (test) => { + strictEqual(test.type, 'test:diagnostic') + match(test.data.message, /TypeScript compilation complete \(\d+ms\)/) + deepEqual(test.data.typescriptCliArgs, ['--build']) + }) + stream.on('test:pass', (test) => { + strictEqual(names.has(test.name), true) + names.delete(test.name) + }) + + await completed +}) test('only-src', async (t) => { const { strictEqual, completed, match } = tspl(t, { plan: 4 }) const config = {