client-bundle-purity.spec.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. /**
  2. * Pins the client-bundle purity gate (tsdown preset resolveId classifier):
  3. * a bare-name import of a module-table package must rewrite to its /client
  4. * external form (inlining it duplicates runtime identity — the P0
  5. /* leak that is not an
  6. * inline-safe wire layer must fail the build loudly.
  7. */
  8. import { describe, expect, it } from 'vitest'
  9. import { CLIENT_EXTERNALS, clientBundle } from '../packages/client/tsdown.client.ts'
  10. type ResolveId = (source: string) => null | { id: string; external: boolean }
  11. function purityResolveId(): ResolveId {
  12. // libEntry is spelled at every call site (no default) so the
  13. // package-invariants text check can see the invariant entry per package.
  14. const configs = clientBundle('@deepseek-ai/dsh-client-test', ['lib/types/index.js', 'lib/types/invariant.js'])
  15. const plugins = (configs[1] as { plugins: { name: string; resolveId?: unknown }[] }).plugins
  16. const gate = plugins.find(p => p.name === 'dsh-client-bundle-purity')
  17. if (gate?.resolveId === undefined) throw new Error('purity plugin missing from client config')
  18. return gate.resolveId as ResolveId
  19. }
  20. describe('client bundle purity gate', () => {
  21. const resolveId = purityResolveId()
  22. it('leaves table entries and non-scoped specifiers alone', () => {
  23. expect(resolveId('@deepseek-ai/dsh-client-ui-slots')).toBeNull()
  24. expect(resolveId('@deepseek-ai/dsh-client-runtime/client')).toBeNull()
  25. expect(resolveId('react')).toBeNull()
  26. expect(resolveId('zod')).toBeNull()
  27. })
  28. it('rewrites a bare table-package name to its external /client form (duplicate-instance prevention)', () => {
  29. expect(resolveId('@deepseek-ai/dsh-client-connection')).toEqual({
  30. id: '@deepseek-ai/dsh-client-connection/client',
  31. external: true,
  32. })
  33. expect(resolveId('@deepseek-ai/dsh-client-ui-layout')).toEqual({
  34. id: '@deepseek-ai/dsh-client-ui-layout/client',
  35. external: true,
  36. })
  37. })
  38. it('lets inline-safe wire layers inline', () => {
  39. expect(resolveId('@deepseek-ai/dsh-host-apiproxy/api')).toBeNull()
  40. expect(resolveId('@deepseek-ai/dsh-session/surface')).toBeNull()
  41. expect(resolveId('@deepseek-ai/dsh-brand')).toBeNull()
  42. })
  43. it('throws on any other @deepseek-ai leak', () => {
  44. expect(() => resolveId('@deepseek-ai/dsh-agent')).toThrow(/purity/)
  45. expect(() => resolveId('@deepseek-ai/dsh-client-web')).toThrow(/purity/)
  46. })
  47. it('every /client external has no bare-name twin in the table (the rewrite assumption)', () => {
  48. for (const entry of CLIENT_EXTERNALS) {
  49. if (entry.endsWith('/client')) expect(CLIENT_EXTERNALS).not.toContain(entry.slice(0, -'/client'.length))
  50. }
  51. })
  52. })