The packer images the web template bundles, every optional bundle, and an installation manifest instead of a dumped composition, and the Worker boots that profile through app-boot like dsh web. Package-local lazy client chunks move into content-addressed archives that the VFS fetches on first asynchronous read; client-modules reads chunks asynchronously. The Worker replaces node-addon-require-builtin with Node v24.18.0 internal-module interfaces and reports Node 24, so plugin metadata, the Cordis Loader, and HMR reach one cascaded loader backed by the Worker loader. Resolution failures carry Node error codes, the empty load cache lets HMR apply profile changes, and every optional bundle switches on and off live. Platform stubs throw ERR_FEATURE_UNAVAILABLE_ON_PLATFORM.
127 lines
7.5 KiB
TypeScript
127 lines
7.5 KiB
TypeScript
/** Installed packer/runtime interoperability without either package's source tree. */
|
|
import { existsSync } from 'node:fs'
|
|
import { mkdir, mkdtemp, readFile, readdir, realpath, rm, symlink, unlink, writeFile } from 'node:fs/promises'
|
|
import { tmpdir } from 'node:os'
|
|
import { dirname, join } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { execa } from 'execa'
|
|
import { expect, it } from 'vitest'
|
|
import { pnpmInvocation } from '../../../../scripts/pnpm-invocation.ts'
|
|
|
|
const experimentalDirectory = fileURLToPath(new URL('../..', import.meta.url))
|
|
const packages = ['webworker-runtime', 'webworker-packer']
|
|
const packageNames = new Set(packages.map(name => `@deepseek-ai/dsh-experimental-${name}`))
|
|
|
|
it('loads both tarballs through plain Node and mounts their base image and overlay', { retry: 0 }, async (test) => {
|
|
const root = await mkdtemp(join(tmpdir(), 'dsh-webworker-packed-'))
|
|
const links: string[] = []
|
|
let pending: Promise<string> = Promise.resolve('')
|
|
test.onTestFinished(async () => {
|
|
try {
|
|
await pending
|
|
} finally {
|
|
for (const path of links.reverse()) await unlink(path)
|
|
await rm(root, { recursive: true, force: true })
|
|
}
|
|
})
|
|
const run = (command: string, args: string[], cwd: string): Promise<string> => {
|
|
pending = execa(command, args, {
|
|
cwd,
|
|
env: { NODE_OPTIONS: undefined, NODE_PATH: undefined, TSX_TSCONFIG_PATH: undefined },
|
|
stdin: 'ignore',
|
|
timeout: test.task.timeout,
|
|
cancelSignal: test.signal,
|
|
killSignal: 'SIGKILL',
|
|
reject: false,
|
|
}).then((result) => {
|
|
expect(result.timedOut, `stderr:\n${result.stderr}`).toBe(false)
|
|
expect(result.isCanceled, `stderr:\n${result.stderr}`).toBe(false)
|
|
expect(result.signal, `stderr:\n${result.stderr}`).toBeUndefined()
|
|
expect(result.exitCode, `stderr:\n${result.stderr}`).toBe(0)
|
|
return result.stdout
|
|
})
|
|
return pending
|
|
}
|
|
await writeFile(join(root, 'package.json'), JSON.stringify({ private: true, type: 'module' }))
|
|
for (const name of packages) {
|
|
const source = join(experimentalDirectory, name)
|
|
const directory = join(root, 'node_modules/@deepseek-ai', `dsh-experimental-${name}`)
|
|
const packRoot = join(root, name)
|
|
await mkdir(packRoot, { recursive: true })
|
|
await mkdir(directory, { recursive: true })
|
|
const invocation = pnpmInvocation(['pack', '--pack-destination', packRoot])
|
|
await run(invocation.command, invocation.args, source)
|
|
const archives = (await readdir(packRoot)).filter(file => file.endsWith('.tgz'))
|
|
expect(archives).toHaveLength(1)
|
|
await run('tar', ['-xzf', join(packRoot, archives[0]!), '-C', directory, '--strip-components=1'], root)
|
|
expect(existsSync(join(directory, 'src'))).toBe(false)
|
|
const manifest = JSON.parse(await readFile(join(directory, 'package.json'), 'utf8')) as {
|
|
dependencies?: Record<string, string>
|
|
peerDependencies?: Record<string, string>
|
|
}
|
|
// Only the two subjects resolve from tarballs; their declared external dependencies use the built checkout.
|
|
for (const dependency of Object.keys({ ...manifest.dependencies, ...manifest.peerDependencies })) {
|
|
if (packageNames.has(dependency)) continue
|
|
const target = join(root, 'node_modules', dependency)
|
|
if (existsSync(target)) continue
|
|
await mkdir(dirname(target), { recursive: true })
|
|
await symlink(await realpath(join(source, 'node_modules', dependency)), target, process.platform === 'win32' ? 'junction' : 'dir')
|
|
links.push(target)
|
|
}
|
|
}
|
|
const script = `
|
|
import assert from 'node:assert/strict'
|
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
import { fileURLToPath } from 'node:url'
|
|
import * as packer from '@deepseek-ai/dsh-experimental-webworker-packer'
|
|
import * as runtime from '@deepseek-ai/dsh-experimental-webworker-runtime'
|
|
import * as client from '@deepseek-ai/dsh-experimental-webworker-runtime/client'
|
|
import { sessionFormatCatalog } from '@deepseek-ai/dsh-session-format-catalog'
|
|
for (const name of ['webworker-packer', 'webworker-runtime']) {
|
|
assert.equal(import.meta.resolve('@deepseek-ai/dsh-experimental-' + name),
|
|
new URL('./node_modules/@deepseek-ai/dsh-experimental-' + name + '/lib/index.js', import.meta.url).href)
|
|
}
|
|
assert.equal(typeof client.connectWorkerHost, 'function')
|
|
const worker = fileURLToPath(import.meta.resolve('@deepseek-ai/dsh-experimental-webworker-runtime/worker'))
|
|
assert.ok(existsSync(worker))
|
|
assert.equal(readFileSync(worker, 'utf8').match(/^import[ \\t]/m), null)
|
|
const base = packer.packVfsImage({ profile: 'packed-consumer', roster: [], workspaces: new Map(), resolveFrom: process.cwd(), entries: [] })
|
|
assert.deepEqual(base.missing, [])
|
|
mkdirSync('subject/lib', { recursive: true })
|
|
const subject = '@deepseek-ai/dsh-image-export-fixture'
|
|
writeFileSync('subject/package.json', JSON.stringify({ name: subject, files: ['lib'], exports: {
|
|
'.': { default: './lib/index.js' }, './types': { types: './lib/index.d.ts' },
|
|
} }))
|
|
writeFileSync('subject/lib/index.js', 'export const value = 1')
|
|
writeFileSync('subject/lib/index.d.ts', 'export declare const value: number')
|
|
const typedOptions = { profile: 'typed-consumer', roster: [subject],
|
|
workspaces: new Map([[subject, fileURLToPath(new URL('./subject', import.meta.url))]]),
|
|
resolveFrom: process.cwd(), entries: [] }
|
|
const typed = packer.packVfsImage(typedOptions)
|
|
assert.deepEqual(typed.missing, [])
|
|
assert.ok(Object.hasOwn(typed.files, 'node_modules/' + subject + '/lib/index.js'))
|
|
assert.equal(Object.hasOwn(typed.files, 'node_modules/' + subject + '/lib/index.d.ts'), false)
|
|
writeFileSync('subject/lib/index.js', 'export { value } from "' + subject + '/types"')
|
|
assert.throws(() => packer.packVfsImage(typedOptions),
|
|
error => error instanceof Error && error.message.includes('does not export "./types"'))
|
|
const vfs = runtime.loadVfsImage(await runtime.inflateImage(base.image, 'packed base'))
|
|
assert.ok(vfs.existsSync('/dsh/' + packer.MANIFEST_PATH))
|
|
mkdirSync('overlay')
|
|
writeFileSync('overlay/hello.txt', 'packed worker pair\\n')
|
|
const overlay = packer.packVfsOverlay([{ mount: 'workspace', directory: fileURLToPath(new URL('./overlay', import.meta.url)) }])
|
|
runtime.loadVfsOverlay(await runtime.inflateImage(overlay.image, 'packed overlay'), '/dsh', vfs)
|
|
assert.equal(vfs.readFileSync('/dsh/workspace/hello.txt', 'utf8'), 'packed worker pair\\n')
|
|
mkdirSync('home/sessions/project/preview', { recursive: true })
|
|
const historical = JSON.stringify({ type: 'session', version: 3, id: 'preview', createdAt: 1, isSeeded: false, delegationDepth: 0 }) + '\\n'
|
|
writeFileSync('home/sessions/project/preview/session.v3.jsonl', historical)
|
|
const prepared = packer.packPreviewFixture([{ mount: 'home', directory: fileURLToPath(new URL('./home', import.meta.url)) }])
|
|
runtime.loadVfsOverlay(await runtime.inflateImage(prepared.image, 'prepared preview'), '/dsh', vfs)
|
|
assert.equal(vfs.readFileSync('/dsh/home/sessions/project/preview/session.v3.jsonl', 'utf8'), historical)
|
|
const current = JSON.parse(vfs.readFileSync('/dsh/home/sessions/project/preview/session.v' + sessionFormatCatalog.currentVersion + '.jsonl', 'utf8'))
|
|
assert.equal(current.version, sessionFormatCatalog.currentVersion)
|
|
console.log('packed image and overlay mounted')
|
|
`
|
|
await writeFile(join(root, 'consumer.mjs'), script)
|
|
expect((await run(process.execPath, ['consumer.mjs'], root)).trim()).toBe('packed image and overlay mounted')
|
|
})
|