From a77826eab9354717c9bc39377adba47c8a8ff2e4 Mon Sep 17 00:00:00 2001 From: vince Date: Sat, 20 Jun 2026 07:20:18 +0200 Subject: [PATCH 1/2] refactor(turbo): consume workspace package exports --- apps/web/src/lib/workspace-boundary.test.ts | 27 +++++++++++++++++++++ apps/web/tsconfig.json | 6 ----- apps/web/vite.config.ts | 12 --------- turbo.json | 1 + 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/apps/web/src/lib/workspace-boundary.test.ts b/apps/web/src/lib/workspace-boundary.test.ts index 9cde8e8..3bb7f85 100644 --- a/apps/web/src/lib/workspace-boundary.test.ts +++ b/apps/web/src/lib/workspace-boundary.test.ts @@ -114,6 +114,33 @@ describe("workspace boundaries", () => { ); }); + test("consumes workspace packages through package exports instead of source aliases", () => { + const webTsconfig = JSON.parse( + readFileSync(join(root, "apps/web/tsconfig.json"), "utf8"), + ) as { compilerOptions?: { paths?: Record } }; + const viteConfig = readFileSync(join(root, "apps/web/vite.config.ts"), "utf8"); + const turboConfig = JSON.parse( + readFileSync(join(root, "turbo.json"), "utf8"), + ) as { tasks?: Record }; + + expect(webTsconfig.compilerOptions?.paths).not.toHaveProperty( + "@dimensionlab/dashboard-model", + ); + expect(webTsconfig.compilerOptions?.paths).not.toHaveProperty( + "@dimensionlab/dashboard-model/fixtures", + ); + expect(webTsconfig.compilerOptions?.paths).not.toHaveProperty("@dimensionlab/ui"); + expect(webTsconfig.compilerOptions?.paths).not.toHaveProperty( + "@dimensionlab/ui/styles.css", + ); + expect(webTsconfig.compilerOptions?.paths).toEqual({ + "$lib/*": ["src/lib/*"], + }); + expect(viteConfig).not.toContain("../../packages/dashboard-model/src"); + expect(viteConfig).not.toContain("../../packages/ui/src"); + expect(turboConfig.tasks?.dev?.dependsOn).toEqual(["^build"]); + }); + test("builds the internal container from a turbo-pruned web workspace", () => { const containerfile = readFileSync( join(root, "apps/web/Containerfile"), diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index f9f784d..120931b 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -3,12 +3,6 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "@dimensionlab/dashboard-model": ["../../packages/dashboard-model/src/index.ts"], - "@dimensionlab/dashboard-model/fixtures": [ - "../../packages/dashboard-model/src/fixtures/index.ts" - ], - "@dimensionlab/ui": ["../../packages/ui/src/index.ts"], - "@dimensionlab/ui/styles.css": ["../../packages/ui/src/styles.css"], "$lib/*": ["src/lib/*"] }, "types": ["node", "bun-types", "react", "react-dom", "vite/client"] diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index 687c180..ceff746 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -24,18 +24,6 @@ export default defineConfig({ plugins: [react(), tailwindcss()], resolve: { alias: { - "@dimensionlab/ui/styles.css": fileURLToPath( - new URL("../../packages/ui/src/styles.css", import.meta.url), - ), - "@dimensionlab/ui": fileURLToPath( - new URL("../../packages/ui/src/index.ts", import.meta.url), - ), - "@dimensionlab/dashboard-model/fixtures": fileURLToPath( - new URL("../../packages/dashboard-model/src/fixtures/index.ts", import.meta.url), - ), - "@dimensionlab/dashboard-model": fileURLToPath( - new URL("../../packages/dashboard-model/src/index.ts", import.meta.url), - ), $lib: fileURLToPath(new URL("./src/lib", import.meta.url)), }, }, diff --git a/turbo.json b/turbo.json index 446d6fe..f2d3137 100644 --- a/turbo.json +++ b/turbo.json @@ -60,6 +60,7 @@ "env": ["DATABASE_URL"] }, "dev": { + "dependsOn": ["^build"], "cache": false, "persistent": true, "env": [ -- 2.49.1 From 2d779165cdbd4bf999e053ef1e60a37dc9b78706 Mon Sep 17 00:00:00 2001 From: vince Date: Sat, 20 Jun 2026 07:26:29 +0200 Subject: [PATCH 2/2] fix(turbo): keep package exports fresh in dev --- apps/web/src/lib/workspace-boundary.test.ts | 44 +++++++++++++++++++++ apps/web/src/server/dev.test.ts | 8 ++++ apps/web/src/server/dev.ts | 6 ++- packages/dashboard-model/package.json | 2 + packages/ui/package.json | 11 +++++- 5 files changed, 68 insertions(+), 3 deletions(-) diff --git a/apps/web/src/lib/workspace-boundary.test.ts b/apps/web/src/lib/workspace-boundary.test.ts index 3bb7f85..2f1bfb1 100644 --- a/apps/web/src/lib/workspace-boundary.test.ts +++ b/apps/web/src/lib/workspace-boundary.test.ts @@ -118,6 +118,12 @@ describe("workspace boundaries", () => { const webTsconfig = JSON.parse( readFileSync(join(root, "apps/web/tsconfig.json"), "utf8"), ) as { compilerOptions?: { paths?: Record } }; + const modelPackage = JSON.parse( + readFileSync(join(root, "packages/dashboard-model/package.json"), "utf8"), + ) as { exports?: Record }; + const uiPackage = JSON.parse( + readFileSync(join(root, "packages/ui/package.json"), "utf8"), + ) as { exports?: Record }; const viteConfig = readFileSync(join(root, "apps/web/vite.config.ts"), "utf8"); const turboConfig = JSON.parse( readFileSync(join(root, "turbo.json"), "utf8"), @@ -139,6 +145,29 @@ describe("workspace boundaries", () => { expect(viteConfig).not.toContain("../../packages/dashboard-model/src"); expect(viteConfig).not.toContain("../../packages/ui/src"); expect(turboConfig.tasks?.dev?.dependsOn).toEqual(["^build"]); + expectPackageExport(modelPackage.exports?.["."], { + types: "./dist/index.d.ts", + development: "./src/index.ts", + default: "./dist/index.js", + }); + expectPackageExport(modelPackage.exports?.["./fixtures"], { + types: "./dist/fixtures/index.d.ts", + development: "./src/fixtures/index.ts", + default: "./dist/fixtures/index.js", + }); + expectPackageExport(uiPackage.exports?.["."], { + types: "./dist/index.d.ts", + development: "./src/index.ts", + default: "./dist/index.js", + }); + expectPackageExport(uiPackage.exports?.["./styles.css"], { + development: "./src/styles.css", + default: "./dist/styles.css", + }); + expectPackageExport(uiPackage.exports?.["./tokens.css"], { + development: "./src/tokens.css", + default: "./dist/tokens.css", + }); }); test("builds the internal container from a turbo-pruned web workspace", () => { @@ -210,3 +239,18 @@ describe("workspace boundaries", () => { ); }); }); + +type WorkspacePackageExport = + | string + | { + types?: string; + development?: string; + default?: string; + }; + +function expectPackageExport( + actual: WorkspacePackageExport | undefined, + expected: Exclude, +): void { + expect(actual).toMatchObject(expected); +} diff --git a/apps/web/src/server/dev.test.ts b/apps/web/src/server/dev.test.ts index f43f953..60031db 100644 --- a/apps/web/src/server/dev.test.ts +++ b/apps/web/src/server/dev.test.ts @@ -2,6 +2,7 @@ import { readFileSync } from "node:fs"; import { join } from "node:path"; import { describe, expect, test } from "vitest"; import { createDevServerConfig } from "../../vite.config"; +import { apiServerArgs } from "./dev"; describe("local development runtime", () => { test("starts the Bun API server together with the Vite dev server", () => { @@ -22,4 +23,11 @@ describe("local development runtime", () => { changeOrigin: true, }); }); + + test("uses development package export conditions for the Bun API server", () => { + expect(apiServerArgs).toEqual([ + "--conditions=development", + "src/server/index.ts", + ]); + }); }); diff --git a/apps/web/src/server/dev.ts b/apps/web/src/server/dev.ts index c515240..fa4dc2f 100644 --- a/apps/web/src/server/dev.ts +++ b/apps/web/src/server/dev.ts @@ -3,6 +3,10 @@ const webPort = process.env.PORT || "5173"; const apiHost = process.env.DASHBOARD_DEV_API_HOST || "127.0.0.1"; const apiPort = process.env.DASHBOARD_DEV_API_PORT || "5174"; const apiTarget = `http://${apiHost}:${apiPort}`; +export const apiServerArgs = [ + "--conditions=development", + "src/server/index.ts", +] as const; if (import.meta.main) { runDevServers(); @@ -51,7 +55,7 @@ export function runDevServers(): void { process.on("SIGINT", () => shutdown(0)); process.on("SIGTERM", () => shutdown(0)); - spawn("api server", [process.execPath, "src/server/index.ts"], { + spawn("api server", [process.execPath, ...apiServerArgs], { HOST: apiHost, PORT: apiPort, }); diff --git a/packages/dashboard-model/package.json b/packages/dashboard-model/package.json index 978522e..ae9a49b 100644 --- a/packages/dashboard-model/package.json +++ b/packages/dashboard-model/package.json @@ -6,10 +6,12 @@ "exports": { ".": { "types": "./dist/index.d.ts", + "development": "./src/index.ts", "default": "./dist/index.js" }, "./fixtures": { "types": "./dist/fixtures/index.d.ts", + "development": "./src/fixtures/index.ts", "default": "./dist/fixtures/index.js" } }, diff --git a/packages/ui/package.json b/packages/ui/package.json index cb7febf..897043c 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -7,10 +7,17 @@ "exports": { ".": { "types": "./dist/index.d.ts", + "development": "./src/index.ts", "default": "./dist/index.js" }, - "./styles.css": "./dist/styles.css", - "./tokens.css": "./dist/tokens.css" + "./styles.css": { + "development": "./src/styles.css", + "default": "./dist/styles.css" + }, + "./tokens.css": { + "development": "./src/tokens.css", + "default": "./dist/tokens.css" + } }, "scripts": { "build": "rm -rf dist && tsc -p tsconfig.build.json && mkdir -p dist/components && cp src/styles.css dist/styles.css && cp src/tokens.css dist/tokens.css && cp src/components/styles.css dist/components/styles.css", -- 2.49.1