import { atomicReplaceDirSync, bundleWorkspacePackage } from './index';
import { existsSync, mkdtempSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
import { afterEach, describe, expect, it } from 'vitest';
describe('bundleWorkspacePackage', () => {
    let rootDir;
    afterEach(() => {
        if (rootDir) {
            rmSync(rootDir, { recursive: true, force: true });
            rootDir = undefined;
        }
    });
    it('removes legacy dist staging dirs when rebundling into an existing destination', () => {
        rootDir = mkdtempSync(join(tmpdir(), 'happier-cli-common-bundle-workspace-'));
        const srcPackageDir = resolve(rootDir, 'packages/protocol');
        const srcDistDir = resolve(srcPackageDir, 'dist');
        mkdirSync(srcDistDir, { recursive: true });
        writeFileSync(resolve(srcPackageDir, 'package.json'), JSON.stringify({
            name: '@happier-dev/protocol',
            version: '0.0.0',
            type: 'module',
            exports: { '.': { default: './dist/index.js' } },
        }, null, 2));
        writeFileSync(resolve(srcDistDir, 'index.js'), 'export {};');
        const destPackageDir = resolve(rootDir, 'apps/stack/node_modules/@happier-dev/protocol');
        mkdirSync(resolve(destPackageDir, 'dist'), { recursive: true });
        const legacyTmpDir = resolve(destPackageDir, 'dist.__sync_tmp__.old-staging');
        const legacyBackupDir = resolve(destPackageDir, 'dist.__sync_backup__.old-staging');
        mkdirSync(legacyTmpDir, { recursive: true });
        mkdirSync(legacyBackupDir, { recursive: true });
        bundleWorkspacePackage({
            packageName: '@happier-dev/protocol',
            srcDir: srcPackageDir,
            destDir: destPackageDir,
        });
        expect(() => readdirSync(legacyTmpDir)).toThrow();
        expect(() => readdirSync(legacyBackupDir)).toThrow();
        const destPackageJsonPath = resolve(destPackageDir, 'package.json');
        const destPackageJson = JSON.parse(readFileSync(destPackageJsonPath, 'utf8'));
        expect(destPackageJson).toEqual(expect.objectContaining({
            name: '@happier-dev/protocol',
            private: true,
            exports: { '.': { default: './dist/index.js' } },
        }));
        expect(readFileSync(resolve(destPackageDir, 'dist/index.js'), 'utf8')).toBe('export {};');
        const destParent = resolve(destPackageDir, '..');
        const siblingNames = readdirSync(destParent);
        expect(siblingNames.some((name) => name.startsWith('.protocol.__sync_tmp__.'))).toBe(false);
        expect(siblingNames.some((name) => name.startsWith('.protocol.__sync_backup__.'))).toBe(false);
    });
});
describe('atomicReplaceDirSync', () => {
    let rootDir;
    afterEach(() => {
        if (rootDir) {
            rmSync(rootDir, { recursive: true, force: true });
            rootDir = undefined;
        }
    });
    it('retries a staged swap when the destination briefly reappears during the rename', () => {
        rootDir = mkdtempSync(join(tmpdir(), 'happier-cli-common-atomic-replace-'));
        const destDir = resolve(rootDir, 'apps/cli/node_modules/@happier-dev/protocol');
        const tempFileName = 'next.txt';
        const previousFileName = 'previous.txt';
        mkdirSync(destDir, { recursive: true });
        writeFileSync(resolve(destDir, previousFileName), 'old');
        let stagedDir = '';
        let renameFailures = 0;
        atomicReplaceDirSync({
            destDir,
            buildInto(tempDir) {
                stagedDir = tempDir;
                mkdirSync(tempDir, { recursive: true });
                writeFileSync(resolve(tempDir, tempFileName), 'new');
            },
            fsOps: {
                renameSync(source, target) {
                    if (source === stagedDir && target === destDir && renameFailures === 0) {
                        renameFailures += 1;
                        const error = new Error('ENOTEMPTY');
                        Reflect.set(error, 'code', 'ENOTEMPTY');
                        throw error;
                    }
                    return renameSync(source, target);
                },
            },
        });
        expect(renameFailures).toBe(1);
        expect(readFileSync(resolve(destDir, tempFileName), 'utf8')).toBe('new');
        expect(existsSync(resolve(destDir, previousFileName))).toBe(false);
    });
});
//# sourceMappingURL=index.test.js.map