/** * Packager resolves `workspace:` build deps in an isolated staging dir by * rewriting them to `file:` paths pointing at the live monorepo member * (ISS-0147 / celilo#216). */ import { afterEach, beforeEach, describe, expect, it } from 'bun:test'; import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { rewriteWorkspaceDeps } from './workspace-deps'; describe('rewriteWorkspaceDeps', () => { let repo: string; // fake monorepo root let sourceDir: string; // module source under the monorepo let buildDir: string; // isolated staging copy function write(base: string, rel: string, obj: unknown): void { const full = join(base, rel); mkdirSync(join(full, '..'), { recursive: true }); writeFileSync(full, typeof obj === 'string' ? obj : JSON.stringify(obj, null, 2)); } beforeEach(() => { repo = mkdtempSync(join(tmpdir(), 'celilo-ws-repo-')); // Monorepo root with workspace globs mirroring the real repo. write(repo, 'package.json', { name: 'infra', private: true, workspaces: ['packages/*', 'modules/*/site'], }); // A sibling workspace package. write(repo, 'packages/visualizer/package.json', { name: '@celilo/visualizer', version: '0.1.0', }); sourceDir = join(repo, 'modules/website'); mkdirSync(sourceDir, { recursive: true }); // Isolated staging copy of the module (what the packager builds in). buildDir = mkdtempSync(join(tmpdir(), 'celilo-ws-stage-')); write(buildDir, 'site/package.json', { name: 'website', dependencies: { '@celilo/visualizer': 'workspace:^', astro: '^5.7.0' }, }); }); afterEach(() => { for (const d of [repo, buildDir]) { try { rmSync(d, { recursive: true, force: true }); } catch { /* ignore */ } } }); it('rewrites a workspace: spec to a file: path at the live member', () => { const rewrites = rewriteWorkspaceDeps(buildDir, sourceDir); const pkg = JSON.parse(readFileSync(join(buildDir, 'site/package.json'), 'utf-8')); expect(pkg.dependencies['@celilo/visualizer']).toBe( `file:${join(repo, 'packages/visualizer')}`, ); // Non-workspace deps untouched. expect(pkg.dependencies.astro).toBe('^5.7.0'); expect(rewrites).toHaveLength(1); }); it('is a no-op when there are no workspace deps', () => { write(buildDir, 'site/package.json', { name: 'website', dependencies: { astro: '^5.7.0' }, }); expect(rewriteWorkspaceDeps(buildDir, sourceDir)).toEqual([]); }); it('fails loudly naming an unresolvable workspace dep', () => { write(buildDir, 'site/package.json', { name: 'website', dependencies: { '@celilo/ghost': 'workspace:*' }, }); expect(() => rewriteWorkspaceDeps(buildDir, sourceDir)).toThrow(/@celilo\/ghost/); }); it('handles the workspaces:{packages:[]} object form', () => { write(repo, 'package.json', { name: 'infra', workspaces: { packages: ['packages/*', 'modules/*/site'] }, }); const rewrites = rewriteWorkspaceDeps(buildDir, sourceDir); expect(rewrites).toHaveLength(1); }); });