import { expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { currentCliVersion } from "../src/update-notifier.ts"; import { addWorkspaceApp, insertWorkspaceApp, resolveWorkspaceConfig, workspaceFiles, workspaceMigrationTargets, } from "../src/workspace.ts"; test("workspace environments preserve runtime and HMR policy", () => { const resolved = resolveWorkspaceConfig( { environments: { staging: { protocol: "https", rootDomain: "staging.example.com", port: 443, runtime: "development", hmr: false, build: false, migrate: false, profile: "uat", }, }, apps: [{ name: "web", dir: "apps/web", subdomain: "www" }], }, "staging", ); expect(resolved.config.runtime).toBe("development"); expect(resolved.config.hmr).toBe(false); expect(resolved.config.profile).toBe("uat"); expect(resolved.apps[0]?.publicOrigin).toBe("https://www.staging.example.com"); }); test("workspace templates pin the running framework release", () => { const files = workspaceFiles("acme"); const rootPackage = JSON.parse(files["package.json"]!); const sharedPackage = JSON.parse(files["packages/shared/package.json"]!); const version = currentCliVersion(); expect(rootPackage.devDependencies["@wrnexus/cli"]).toBe(version); expect(sharedPackage.dependencies["@wrnexus/pubsub"]).toBe(version); expect(files["README.md"]).toContain("http://127.0.0.1:3000"); expect(files["README.md"]).toContain("internal gateway targets"); expect(JSON.parse(files["package.json"]!).scripts.production).toBe("wrnexus production"); expect(JSON.parse(files["package.json"]!).scripts.check).toContain("typecheck"); expect(JSON.parse(files["package.json"]!).scripts.check).toContain("format:check"); expect(files["wrnexus.workspace.ts"]).toContain('runtime: "development"'); expect(files["wrnexus.workspace.ts"]).toContain("hmr: false"); expect(files[".env.example"]).toContain("REDIS_URL"); expect(files["eslint.config.js"]).toContain("typescript-eslint"); expect(files["tsconfig.json"]).toContain('"strict": true'); expect(files[".vscode/extensions.json"]).toContain("wrnexus.wrnexus"); }); test("production workspace detects default and named SQL migrations", () => { const root = mkdtempSync(join(tmpdir(), "wrnexus-production-migrations-")); try { mkdirSync(join(root, "app", "db", "migrations"), { recursive: true }); mkdirSync(join(root, "app", "db", "analytics", "migrations"), { recursive: true }); mkdirSync(join(root, "app", "db", "empty", "migrations"), { recursive: true }); writeFileSync(join(root, "app", "db", "migrations", "0001_init.sql"), "select 1;"); writeFileSync(join(root, "app", "db", "analytics", "migrations", "0001_init.sql"), "select 1;"); expect(workspaceMigrationTargets(root)).toEqual([null, "analytics"]); } finally { rmSync(root, { recursive: true, force: true }); } }); test("insertWorkspaceApp handles nested arrays and comments", () => { const source = `const config = { apps: [ { name: "web", dir: "apps/web", domains: ["localhost"] }, { name: "admin", dir: "apps/admin", domains: ["admin.localhost"], auth: { allowIps: ["::1"] } }, // ] ], }; export default config; `; const result = insertWorkspaceApp(source, { name: "reports", dir: "apps/reports", domains: ["reports.localhost"], }); expect(result).toContain( '{ name: "reports", dir: "apps/reports", domains: ["reports.localhost"] },', ); expect(result.indexOf('name: "reports"')).toBeLessThan(result.indexOf("\n ],")); }); test("workspace add scaffolds and registers an app", async () => { const root = mkdtempSync(join(tmpdir(), "wrnexus-workspace-add-")); writeFileSync( join(root, "wrnexus.workspace.ts"), 'export default { apps: [{ name: "web", dir: "apps/web", domains: ["localhost"] }] };\n', ); try { await addWorkspaceApp(root, "reports", ["--domain=reports.localhost"]); const manifest = JSON.parse( readFileSync(join(root, "apps", "reports", "package.json"), "utf8"), ); const config = readFileSync(join(root, "wrnexus.workspace.ts"), "utf8"); expect(manifest.name).toBe("reports"); expect(manifest.wrnexus.version).toBe(currentCliVersion()); expect(config).toContain('name: "reports"'); expect(config).toContain('domains: ["reports.localhost"]'); expect(existsSync(join(root, "apps", "reports", "public", "llms.txt"))).toBe(true); } finally { rmSync(root, { recursive: true, force: true }); } });