mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
Review found the CLI entry guard compared import.meta.url against a concatenated file:// URL. That fails whenever import.meta.url encodes something process.argv[1] does not — a repository path containing a space, or any Windows drive path — and it fails silently: the script exits 0 having done nothing, so verify-tsconfig-paths would pass without checking exactly where it is needed. Running a copy from a directory whose name contains a space reproduces it. The guard now uses the comparison the repository's seven other generators already use. Deleting the group wildcards also removed the fallback that resolved a package nobody had aliased, so the generator now asserts coverage: every workspace package with a src directory must be mapped, and --check names any that is not. That assertion immediately found four packages named dsh-<group>-<directory> whose siblings carry hand-written aliases while they did not, so they reached built lib/ output through the workspace symlink. They now carry aliases too, which takes the resolution differences in this branch from seven to eleven. Two comments in tsconfig.base.json still pointed at the deleted wildcards; they now state why those aliases stay hand-written. The package-inventory proposal recorded the wildcard collapse as current, so both notes are cross-linked as partial supersession.
99 lines
4.1 KiB
TypeScript
99 lines
4.1 KiB
TypeScript
import { readFileSync } from 'node:fs'
|
|
import { resolve } from 'node:path'
|
|
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
collectPackageAliases,
|
|
collectPackageNames,
|
|
mappedSpecifiers,
|
|
renderAliases,
|
|
uncoveredPackages,
|
|
writeRegion,
|
|
} from './gen-tsconfig-paths.ts'
|
|
|
|
const root = resolve(import.meta.dirname, '..')
|
|
|
|
describe('generated tsconfig package aliases', () => {
|
|
it('maps each package to its own source directory', () => {
|
|
const aliases = collectPackageAliases()
|
|
expect(aliases.length).toBeGreaterThan(100)
|
|
const session = aliases.find(alias => alias.specifier === '@deepseek-ai/dsh-session')
|
|
expect(session).toEqual({
|
|
specifier: '@deepseek-ai/dsh-session',
|
|
source: './packages/core/session/src',
|
|
hasInvariant: true,
|
|
})
|
|
// Sorted, so a package added anywhere lands in a stable spot in the diff.
|
|
expect([...aliases].sort((a, b) => a.specifier.localeCompare(b.specifier))).toEqual(aliases)
|
|
// Only packages named after their directory: the rest carry hand-written
|
|
// aliases, because the removed wildcards could never have resolved them.
|
|
expect(aliases.some(alias => alias.specifier === '@deepseek-ai/dsh-typert-protocol')).toBe(false)
|
|
})
|
|
|
|
it('yields to a hand-written alias and closes without a trailing comma', () => {
|
|
const aliases = [
|
|
{ specifier: '@deepseek-ai/dsh-a', source: './packages/g/a/src', hasInvariant: true },
|
|
{ specifier: '@deepseek-ai/dsh-b', source: './packages/g/b/src', hasInvariant: false },
|
|
]
|
|
const body = renderAliases(aliases, new Set(['@deepseek-ai/dsh-a']))
|
|
|
|
// The hand-written bare alias is skipped; its /invariant sibling is not.
|
|
expect(body).toBe([
|
|
' "@deepseek-ai/dsh-a/invariant": ["./packages/g/a/src/invariant.ts"]',
|
|
' "@deepseek-ai/dsh-b": ["./packages/g/b/src"]',
|
|
].join(',\n'))
|
|
expect(body.endsWith(',')).toBe(false)
|
|
})
|
|
|
|
it('replaces only the marked region', () => {
|
|
const text = [
|
|
'{ "before": 1,',
|
|
' // BEGIN generated package aliases — pnpm run gen-tsconfig-paths',
|
|
' "stale": ["gone"]',
|
|
' // END generated package aliases',
|
|
' "after": 2 }',
|
|
].join('\n')
|
|
|
|
const next = writeRegion(text, ' "fresh": ["kept"]')
|
|
|
|
expect(next).toContain('{ "before": 1,')
|
|
expect(next).toContain(' "after": 2 }')
|
|
expect(next).toContain('"fresh": ["kept"]')
|
|
expect(next).not.toContain('stale')
|
|
})
|
|
|
|
it('refuses a config without the region markers', () => {
|
|
expect(() => writeRegion('{}', '')).toThrow('missing the generated-region markers')
|
|
})
|
|
|
|
it('names a package that no alias covers', () => {
|
|
// Deleting the group wildcards removed the fallback that used to resolve a
|
|
// package nobody had aliased. A package whose name does not match its
|
|
// directory is skipped by the generator, so without this check it would
|
|
// resolve through the workspace symlink to built lib/types instead.
|
|
expect(uncoveredPackages(
|
|
['@deepseek-ai/dsh-a', '@deepseek-ai/dsh-b'],
|
|
new Set(['@deepseek-ai/dsh-a', '@deepseek-ai/dsh-a/invariant']),
|
|
)).toEqual(['@deepseek-ai/dsh-b'])
|
|
|
|
expect(uncoveredPackages(['@deepseek-ai/dsh-a'], new Set(['@deepseek-ai/dsh-a']))).toEqual([])
|
|
})
|
|
|
|
it('covers every workspace package in the committed config', () => {
|
|
const config = readFileSync(resolve(root, 'tsconfig.base.json'), 'utf8')
|
|
// Includes the packages the generator skips because their name does not
|
|
// match their directory: those carry hand-written aliases.
|
|
const names = collectPackageNames()
|
|
expect(names).toContain('@deepseek-ai/dsh-typert-protocol')
|
|
expect(uncoveredPackages(names, mappedSpecifiers(config))).toEqual([])
|
|
})
|
|
|
|
it('leaves no wildcard that probes every package group', () => {
|
|
const config = readFileSync(resolve(root, 'tsconfig.base.json'), 'utf8')
|
|
// These two listed one candidate per group, so resolving a package late in
|
|
// the list cost a filesystem probe — and under tsx a decorated module
|
|
// error — for every group before it.
|
|
expect(config).not.toContain('"@deepseek-ai/dsh-*":')
|
|
expect(config).not.toContain('"@deepseek-ai/dsh-*/invariant":')
|
|
})
|
|
})
|