f04db9751f
## Problem A front component that imports `MetadataApiClient` from `twenty-client-sdk/metadata` crashes at render time: ``` FrontComponent error: Failed to resolve module specifier "./chunk-Dqa2HsxW.mjs". Invalid relative url or base scheme isn't hierarchical. ``` (hash differs per build). The equivalent component using `CoreApiClient` from `twenty-client-sdk/core` works fine. ## Root cause The front-component renderer loads each SDK client as a **single in-memory blob-URL module** and only rewrites the two bare specifiers it knows (`twenty-client-sdk/core`, `twenty-client-sdk/metadata`). A blob-URL module cannot resolve a **relative** `import … from "./chunk-*.mjs"` (blob URLs aren't hierarchical), and that chunk isn't served anyway. Only two entrypoints are externalized by the front-component build (`FRONT_COMPONENT_EXTERNAL_MODULES`) and thus served as blob modules: `core` and `metadata`. Everything else (`rest`, `generate`) is bundled into the component and is unaffected. Of those two: | client | how `dist/*.mjs` is produced | self-contained? | |---|---|---| | **core** | esbuild single-file bundle (`compileGeneratedClient`), re-run per workspace at server runtime by `replaceCoreClient` | ✅ | | **metadata** | the shared multi-entry Vite build, which hoists shared code into a relative `chunk-*.mjs` | ❌ | The metadata client is built once at package-build time (it is not workspace-specific) and was shipped straight from the multi-entry Vite output, keeping the unresolvable relative chunk import. ## Regression trace This was **not** broken on arrival — it regressed via a transitive bundler swap: | Date | Commit | Event | |---|---|---| | 2026-05-20 | `a26fe3bb65` | Metadata-client-in-front-components shipped; `twenty-client-sdk` on **Vite 7 (Rollup)** | | 2026-06-08 | `d2e7dc0e74` (#21309, *"security: bump vulnerable direct dependencies"*) | Bumped **Vite 7 → 8**, introducing **Rolldown 1.0.3** (no rolldown entries in the lockfile before this commit) | Vite 7 is Rollup-based; Vite 8 uses Rolldown. The breaking artifact is literally a `\0rolldown/runtime.js` shared chunk — a Rolldown construct that could not have existed before the bump. So the metadata front-component path worked from 2026-05-20 until the 2026-06-08 security dependency bump silently changed the bundler and split out the shared runtime chunk. ## Fix Build the metadata client as its **own single-entry Vite library** (`vite.metadata.config.ts`) so its output is a single self-contained file with no shared chunk. `core` / `rest` / `generate` stay in the main multi-entry build (`vite.config.ts`); shared config (`isExternal`, `entryFileNames`) is factored into `vite.shared.ts`. The build pipeline runs `vite build && vite build -c vite.metadata.config.ts`. The server picks this up automatically: `SdkClientGenerationService` ships the pre-built package `dist/` and only regenerates the **core** client; it never regenerates metadata. No server-side change required. ## Regression guard (e2e) The postcard example's `card.front-component.tsx` previously used `CoreApiClient` only, so this metadata-only regression had no e2e coverage. It now loads and round-trips all three SDK clients (`Core`, `Metadata`, `Rest`) via an SDK health panel, and the e2e asserts the blob-served `core` + `metadata` probes reach `ok` — which only happens if those bundles resolve and function. A future chunk-import regression in either blob module would crash the component on load and fail the test. ## Verification - `npx nx build twenty-client-sdk` succeeds. - `dist/metadata.mjs` / `dist/metadata.cjs`: **0** `chunk-*` imports, **0** relative imports; both load and export `MetadataApiClient` + `MetadataSchema`. - `dist/metadata/index.d.ts` types still emitted. - `npx nx typecheck` + `npx nx lint twenty-client-sdk` pass; postcard app typecheck + lint pass. ## Notes - `dist/` is not committed (CI builds it); a running server must rebuild `twenty-client-sdk` for the fix to take effect. - The e2e was validated statically (typecheck + lint); running it end-to-end requires a live stack with a seeded postcard record.
72 lines
1.8 KiB
JSON
72 lines
1.8 KiB
JSON
{
|
|
"name": "twenty-client-sdk",
|
|
"version": "2.17.0",
|
|
"sideEffects": false,
|
|
"license": "AGPL-3.0",
|
|
"scripts": {
|
|
"build": "npx rimraf dist && npx vite build && npx vite build -c vite.metadata.config.ts && tsgo -p tsconfig.lib.json --declaration --emitDeclarationOnly --noEmit false --outDir dist --rootDir src && npx tsc-alias -p tsconfig.lib.json --outDir dist"
|
|
},
|
|
"exports": {
|
|
"./core": {
|
|
"types": "./dist/core/index.d.ts",
|
|
"import": "./dist/core.mjs",
|
|
"require": "./dist/core.cjs"
|
|
},
|
|
"./metadata": {
|
|
"types": "./dist/metadata/index.d.ts",
|
|
"import": "./dist/metadata.mjs",
|
|
"require": "./dist/metadata.cjs"
|
|
},
|
|
"./rest": {
|
|
"types": "./dist/rest/index.d.ts",
|
|
"import": "./dist/rest.mjs",
|
|
"require": "./dist/rest.cjs"
|
|
},
|
|
"./generate": {
|
|
"types": "./dist/generate/index.d.ts",
|
|
"import": "./dist/generate.mjs",
|
|
"require": "./dist/generate.cjs"
|
|
}
|
|
},
|
|
"typesVersions": {
|
|
"*": {
|
|
"core": [
|
|
"dist/core/index.d.ts"
|
|
],
|
|
"metadata": [
|
|
"dist/metadata/index.d.ts"
|
|
],
|
|
"rest": [
|
|
"dist/rest/index.d.ts"
|
|
],
|
|
"generate": [
|
|
"dist/generate/index.d.ts"
|
|
]
|
|
}
|
|
},
|
|
"files": [
|
|
"dist"
|
|
],
|
|
"dependencies": {
|
|
"@genql/runtime": "^2.10.0",
|
|
"esbuild": "^0.28.1",
|
|
"graphql": "^16.8.1",
|
|
"lodash": "^4.17.21",
|
|
"prettier": "^3.8.3"
|
|
},
|
|
"devDependencies": {
|
|
"@types/lodash": "^4.17.24",
|
|
"@typescript/native-preview": "^7.0.0-dev.20260116.1",
|
|
"tsc-alias": "^1.8.16",
|
|
"twenty-shared": "workspace:*",
|
|
"typescript": "^5.9.3",
|
|
"vite": "^8.0.0",
|
|
"vite-plugin-dts": "^4.5.4",
|
|
"vitest": "^4.1.0"
|
|
},
|
|
"engines": {
|
|
"node": "^24.5.0",
|
|
"yarn": "^4.0.2"
|
|
}
|
|
}
|