mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
97 lines
4.4 KiB
TypeScript
97 lines
4.4 KiB
TypeScript
/**
|
|
* Pins shared client-bundle preset contracts: the module-edge purity gate and
|
|
* the physical watch dependencies hidden behind virtual CSS Modules.
|
|
*/
|
|
import { fileURLToPath } from 'node:url'
|
|
import { describe, expect, it, vi } from 'vitest'
|
|
import { CLIENT_EXTERNALS, clientBundle } from '../packages/client/tsdown.client.ts'
|
|
|
|
type ResolveId = (source: string) => null | { id: string; external: boolean }
|
|
|
|
interface CssModulePlugin {
|
|
name: string
|
|
resolveId?: (source: string, importer: string | undefined) => null | string
|
|
load?: (this: { addWatchFile: (id: string) => void }, id: string) => Promise<unknown>
|
|
}
|
|
|
|
function purityResolveId(): ResolveId {
|
|
// libEntry is spelled at every call site (no default) so the
|
|
// package-invariants text check can see the invariant entry per package.
|
|
const configs = clientBundle('@deepseek-ai/dsh-client-test', ['lib/types/index.js', 'lib/types/invariant.js'])
|
|
const plugins = (configs[1] as { plugins: { name: string; resolveId?: unknown }[] }).plugins
|
|
const gate = plugins.find(p => p.name === 'dsh-client-bundle-purity')
|
|
if (gate?.resolveId === undefined) throw new Error('purity plugin missing from client config')
|
|
return gate.resolveId as ResolveId
|
|
}
|
|
|
|
function cssModulePlugin(): CssModulePlugin {
|
|
const configs = clientBundle('@deepseek-ai/dsh-client-test', ['lib/types/index.js', 'lib/types/invariant.js'])
|
|
const plugins = (configs[1] as { plugins: CssModulePlugin[] }).plugins
|
|
const plugin = plugins.find(candidate => candidate.name === 'dsh-css-modules-inline')
|
|
if (plugin?.resolveId === undefined || plugin.load === undefined) {
|
|
throw new Error('CSS Modules plugin missing from client config')
|
|
}
|
|
return plugin
|
|
}
|
|
|
|
describe('client bundle purity gate', () => {
|
|
const resolveId = purityResolveId()
|
|
|
|
it('leaves platform table entries and non-scoped specifiers alone', () => {
|
|
expect(resolveId('@deepseek-ai/dsh-client-ui-slots')).toBeNull()
|
|
expect(resolveId('@deepseek-ai/dsh-client-web-react')).toBeNull()
|
|
expect(resolveId('@deepseek-ai/dsh-client-ui-primitives')).toBeNull()
|
|
expect(resolveId('react')).toBeNull()
|
|
expect(resolveId('zod')).toBeNull()
|
|
})
|
|
|
|
it('rejects retired table entries (web-react/store left the 8-entry seed)', () => {
|
|
expect(() => resolveId('@deepseek-ai/dsh-client-web-react/store')).toThrow(/purity/)
|
|
})
|
|
|
|
it('lets inline-safe wire layers inline', () => {
|
|
expect(resolveId('@deepseek-ai/dsh-host-apiproxy/api')).toBeNull()
|
|
expect(resolveId('@deepseek-ai/dsh-session/surface')).toBeNull()
|
|
expect(resolveId('@deepseek-ai/dsh-brand')).toBeNull()
|
|
})
|
|
|
|
it('throws on any other @deepseek-ai leak', () => {
|
|
expect(() => resolveId('@deepseek-ai/dsh-agent')).toThrow(/purity/)
|
|
expect(() => resolveId('@deepseek-ai/dsh-client-web')).toThrow(/purity/)
|
|
})
|
|
|
|
it('throws on cross-plugin value imports — bare plugin names and /client subpaths alike (the rewrite arm is gone)', () => {
|
|
expect(() => resolveId('@deepseek-ai/dsh-client-connection')).toThrow(/purity/)
|
|
expect(() => resolveId('@deepseek-ai/dsh-client-runtime')).toThrow(/purity/)
|
|
expect(() => resolveId('@deepseek-ai/dsh-client-ui-layout/client')).toThrow(/purity/)
|
|
})
|
|
|
|
it('carries exactly one documented temporary exemption: runtime/client (store engine pending rehoming)', () => {
|
|
expect(resolveId('@deepseek-ai/dsh-client-runtime/client')).toBeNull()
|
|
const dshClientChannels = CLIENT_EXTERNALS.filter(
|
|
entry => entry.startsWith('@deepseek-ai/') && entry.endsWith('/client'))
|
|
expect(dshClientChannels).toEqual(['@deepseek-ai/dsh-client-runtime/client'])
|
|
})
|
|
})
|
|
|
|
describe('client bundle CSS Modules watch graph', () => {
|
|
it('registers the physical stylesheet read behind a virtual module', async () => {
|
|
const plugin = cssModulePlugin()
|
|
const importer = fileURLToPath(new URL(
|
|
'../packages/client/ui-conversation/src/client/queue/QueueDock.tsx',
|
|
import.meta.url,
|
|
))
|
|
const stylesheet = fileURLToPath(new URL(
|
|
'../packages/client/ui-conversation/src/client/queue/QueueDock.module.css',
|
|
import.meta.url,
|
|
))
|
|
const virtualId = plugin.resolveId?.('./QueueDock.module.css', importer)
|
|
if (virtualId === null || virtualId === undefined) throw new Error('CSS Modules import was not resolved')
|
|
const addWatchFile = vi.fn()
|
|
|
|
await plugin.load?.call({ addWatchFile }, virtualId)
|
|
|
|
expect(addWatchFile).toHaveBeenCalledExactlyOnceWith(stylesheet)
|
|
})
|
|
})
|