Skip to content

Commit 22b444d

Browse files
committed
refactor: replace tsconfk
1 parent bc2b8d7 commit 22b444d

15 files changed

+563
-23
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@pandacss/node': patch
3+
---
4+
5+
Replace discontinued `tsconfck` with [`get-tsconfig`](https://github.com/privatenumber/get-tsconfig) for resolving and
6+
parsing `tsconfig.json` (including `extends`).
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
2+
import path from 'node:path'
3+
import { tmpdir } from 'node:os'
4+
import { describe, expect, test } from 'vitest'
5+
import { findClosestTsconfig, resolveDirectTsconfigJson } from '../src/tsconfig-utils'
6+
7+
describe('findClosestTsconfig', () => {
8+
test('finds tsconfig in the same directory as the config file', async () => {
9+
const dir = mkdtempSync(path.join(tmpdir(), 'panda-tsconfig-'))
10+
try {
11+
const tsconfigPath = path.join(dir, 'tsconfig.json')
12+
writeFileSync(tsconfigPath, JSON.stringify({ compilerOptions: { paths: { '@/*': ['./src/*'] } } }))
13+
const pandaConfig = path.join(dir, 'panda.config.ts')
14+
writeFileSync(pandaConfig, 'export default {}')
15+
16+
await expect(findClosestTsconfig(pandaConfig, dir)).resolves.toBe(tsconfigPath)
17+
} finally {
18+
rmSync(dir, { recursive: true, force: true })
19+
}
20+
})
21+
22+
test('walks up to a parent directory', async () => {
23+
const root = mkdtempSync(path.join(tmpdir(), 'panda-tsconfig-'))
24+
try {
25+
const tsconfigPath = path.join(root, 'tsconfig.json')
26+
writeFileSync(tsconfigPath, '{}')
27+
const sub = path.join(root, 'packages', 'app')
28+
mkdirSync(sub, { recursive: true })
29+
const pandaConfig = path.join(sub, 'panda.config.ts')
30+
writeFileSync(pandaConfig, 'export default {}')
31+
32+
await expect(findClosestTsconfig(pandaConfig, root)).resolves.toBe(tsconfigPath)
33+
} finally {
34+
rmSync(root, { recursive: true, force: true })
35+
}
36+
})
37+
38+
test('does not search above root (matches tsconfck root option)', async () => {
39+
const outer = mkdtempSync(path.join(tmpdir(), 'panda-tsconfig-'))
40+
try {
41+
writeFileSync(path.join(outer, 'tsconfig.json'), '{}')
42+
const inner = path.join(outer, 'nested', 'pkg')
43+
mkdirSync(inner, { recursive: true })
44+
const pandaConfig = path.join(inner, 'panda.config.ts')
45+
writeFileSync(pandaConfig, 'export default {}')
46+
47+
await expect(findClosestTsconfig(pandaConfig, inner)).resolves.toBeNull()
48+
} finally {
49+
rmSync(outer, { recursive: true, force: true })
50+
}
51+
})
52+
})
53+
54+
describe('resolveDirectTsconfigJson', () => {
55+
test('resolves when conf.path is a tsconfig.json file', async () => {
56+
const dir = mkdtempSync(path.join(tmpdir(), 'panda-tsconfig-'))
57+
try {
58+
const tsconfigPath = path.join(dir, 'tsconfig.json')
59+
writeFileSync(tsconfigPath, '{}')
60+
await expect(resolveDirectTsconfigJson(tsconfigPath)).resolves.toBe(path.resolve(tsconfigPath))
61+
} finally {
62+
rmSync(dir, { recursive: true, force: true })
63+
}
64+
})
65+
66+
test('returns null for non-json paths', async () => {
67+
await expect(resolveDirectTsconfigJson('/tmp/foo.ts')).resolves.toBeNull()
68+
})
69+
70+
test('throws when path exists but is not a file (tsconfck resolveTSConfigJson parity)', async () => {
71+
const dir = mkdtempSync(path.join(tmpdir(), 'panda-tsconfig-'))
72+
try {
73+
const tsconfigDir = path.join(dir, 'tsconfig.json')
74+
mkdirSync(tsconfigDir)
75+
await expect(resolveDirectTsconfigJson(tsconfigDir)).rejects.toThrow(/exists but is not a regular file/)
76+
} finally {
77+
rmSync(dir, { recursive: true, force: true })
78+
}
79+
})
80+
})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const foo = 1
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"compilerOptions": {
3+
"composite": true,
4+
"strictNullChecks": true
5+
}
6+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"files": [],
3+
"include": [],
4+
"references": [{ "path": "./tsconfig.src.json" }, { "path": "./tsconfig.test.json" }]
5+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": "./tsconfig.base",
3+
"include": ["src/**/*"],
4+
"exclude": ["src/**/*.spec.ts"],
5+
"compilerOptions": {
6+
"strict": true,
7+
"baseUrl": ".",
8+
"paths": {
9+
"@pkg/*": ["./src/*"]
10+
}
11+
}
12+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"extends": "./tsconfig.base",
3+
"include": ["src/**/*.spec.ts"],
4+
"compilerOptions": {
5+
"strict": false
6+
}
7+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import path from 'node:path'
2+
import { fileURLToPath } from 'node:url'
3+
import { describe, expect, test } from 'vitest'
4+
import type { LoadConfigResult } from '@pandacss/types'
5+
import { loadTsConfig } from '../src/load-tsconfig'
6+
7+
const fixtureDir = path.join(path.dirname(fileURLToPath(import.meta.url)), 'fixtures', 'solution-mixed')
8+
9+
function mockConf(configPath: string): LoadConfigResult {
10+
return {
11+
path: configPath,
12+
config: {} as LoadConfigResult['config'],
13+
serialized: '',
14+
deserialize: () => ({}) as LoadConfigResult['config'],
15+
dependencies: [],
16+
hooks: {},
17+
}
18+
}
19+
20+
describe('loadTsConfig + TypeScript project references', () => {
21+
test('resolves to referenced tsconfig.src.json for sources under src/', async () => {
22+
const pandaPath = path.join(fixtureDir, 'src', 'panda.config.ts')
23+
const cwd = fixtureDir
24+
const result = await loadTsConfig(mockConf(pandaPath), cwd)
25+
26+
expect(result?.tsconfigFile).toBe(path.join(fixtureDir, 'tsconfig.src.json'))
27+
expect(result?.tsconfig?.compilerOptions).toBeDefined()
28+
})
29+
30+
test('falls back to root tsconfig when file is not in any referenced project', async () => {
31+
const pandaPath = path.join(fixtureDir, 'panda.config.ts')
32+
const cwd = fixtureDir
33+
const result = await loadTsConfig(mockConf(pandaPath), cwd)
34+
35+
expect(result?.tsconfigFile).toBe(path.join(fixtureDir, 'tsconfig.json'))
36+
})
37+
})
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import path from 'node:path'
2+
import { describe, expect, test } from 'vitest'
3+
import { resolveBaseUrlForCompilerOptions } from '../src/tsconfig-utils'
4+
5+
describe('resolveBaseUrlForCompilerOptions', () => {
6+
const cwd = '/project'
7+
const tsconfig = '/project/packages/app/tsconfig.json'
8+
9+
test('uses cwd when baseUrl is omitted', () => {
10+
expect(resolveBaseUrlForCompilerOptions(undefined, tsconfig, cwd)).toBe(cwd)
11+
})
12+
13+
test('resolves relative baseUrl against the tsconfig directory', () => {
14+
expect(resolveBaseUrlForCompilerOptions('.', tsconfig, cwd)).toBe(path.resolve('/project/packages/app'))
15+
expect(resolveBaseUrlForCompilerOptions('./src', tsconfig, cwd)).toBe(path.resolve('/project/packages/app/src'))
16+
})
17+
18+
test('leaves absolute baseUrl unchanged', () => {
19+
expect(resolveBaseUrlForCompilerOptions('/abs/base', tsconfig, cwd)).toBe('/abs/base')
20+
})
21+
})

0 commit comments

Comments
 (0)