fix: replace Vite ?raw imports with readFileSync for Node.js compatibility#250
fix: replace Vite ?raw imports with readFileSync for Node.js compatibility#250Dubworx wants to merge 2 commits intoOpenCoworkAI:mainfrom
Conversation
Signed-off-by: hqhq1025 <97931168+hqhq1025@users.noreply.github.com> (cherry picked from commit 0cbb792)
…ility The `?raw` import suffix is a Vite-specific feature that fails when importing @open-codesign/core from Node.js/tsx contexts (e.g. headless CLI scripts). This replaces all ?raw imports in frames/index.ts and design-skills/index.ts with fs.readFileSync, which works in both Vite (via plugin) and plain Node.js. Also adds "type": "module" to root package.json to enable ESM top-level await in scripts that import from the core package. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Findings
-
[Major] Runtime
readFileSync()here breaks packaged desktop builds.FRAME_TEMPLATESandDESIGN_SKILLSare imported by the Electron main process (apps/desktop/src/main/index.ts:9,apps/desktop/src/main/index.ts:296), but packaging only shipsout/**pluspackage.json(apps/desktop/electron-builder.yml:15). Replacing?rawwithreadFileSync(resolve(__dirname, name))(packages/core/src/frames/index.ts:19,packages/core/src/design-skills/index.ts:17) means the packaged app now expects the.jsxsource files to exist next to the bundled JS, and the current electron-vite build does not emit or copy them (apps/desktop/electron.vite.config.ts:12). That turns a packaged app import into anENOENTon the first frame/skill load.
Suggested fix:// Keep these starter assets bundled into JS until there is a dual-path // solution that also emits/copies the companion .jsx files for packaged builds. import iphoneJsx from './iphone.jsx?raw'; import ipadJsx from './ipad.jsx?raw'; // ...apply the same revert for the rest of the frame and skill starters
-
[Minor]
website/public/llms.txtnow points to a plan file that is not in the public checkout.website/public/llms.txt:79referencesdocs/v0.2-plan.md, but that file is not present, andAGENTS.md:16explicitly saysdocs/**is mostly maintainer-local. That leaves public readers and LLM consumers with a dead source reference.
Suggested fix:See the [roadmap](/roadmap) for the milestone plan.
Summary
- Review mode: initial
- 2 findings. The main risk is a packaged-desktop regression from swapping bundled starter assets for runtime filesystem reads.
- Existing tests cover starter contents, but I did not find a regression test for the plain-Node import path claimed in this PR or a packaged Electron smoke path.
Testing
- Not run (automation).
pnpmis not installed in this runner, so I could not execute the repo test suite.
open-codesign Bot
| const __dirname = dirname(fileURLToPath(import.meta.url)); | ||
|
|
||
| function loadFrame(name: string): string { | ||
| return readFileSync(resolve(__dirname, name), 'utf-8'); |
There was a problem hiding this comment.
[Major] This replaces build-time inlining with a runtime readFileSync, but the packaged desktop app only ships out/** and package.json (apps/desktop/electron-builder.yml:15-17). Because the main process imports FRAME_TEMPLATES / DESIGN_SKILLS (apps/desktop/src/main/index.ts:9-10, apps/desktop/src/main/index.ts:296-300), packaged builds will now look for iphone.jsx-style source files next to the bundled JS and hit ENOENT.
Suggested fix:
import iphoneJsx from './iphone.jsx?raw';
import ipadJsx from './ipad.jsx?raw';
// ...keep the starter bodies bundled until there is a dual-path
// solution that also emits/copies the .jsx assets for packaged builds| - v0.1 migration path — existing SQLite designs migrate into workspaces and session history | ||
|
|
||
| Design doc: `docs/plans/2026-04-23-v0.2-agentic-design-loop-design.md` in the repo. | ||
| Plan source: `docs/v0.2-plan.md` in the repo. |
There was a problem hiding this comment.
[Minor] docs/v0.2-plan.md is not in the public checkout, and AGENTS.md says docs/** is mostly maintainer-local. This leaves a dead public reference.
Suggested fix:
See the [roadmap](/roadmap) for the milestone plan.There was a problem hiding this comment.
Review mode: initial
Findings
-
[Major]
readFileSyncapproach likely breaks production Electron build
packages/core/src/frames/index.ts:12-14andpackages/core/src/design-skills/index.ts:12-14replace Vite's?rawimports withreadFileSync. In Vite,?rawimports are bundled as inlined strings. The new code relies onnode:fsandimport.meta.urlat runtime.- In the development server (
pnpm dev), Vite's Node.js compatibility layer may handlereadFileSyncand resolve paths correctly. - In the production Electron build (where the renderer is bundled by Vite), the JSX files will not be bundled alongside the output, and
node:fsmay not be available in the renderer context unlessnodeIntegrationis enabled andfsis externalised. This can cause runtime failures when loading frame templates or design skills. - No Vite configuration changes are included to externalise
node:fsor copy the.jsxfiles to the output directory. - The PR’s test plan checks
pnpm devandpnpm build, but does not verify that the production Electron app can load frames and skills.
Suggested fix:
- Before merging, verify the production build with
pnpm buildand run the Electron app to confirm that frames and design skills render correctly. - If the renderer does not have direct filesystem access, an alternative is to keep
?rawimports for the Vite context and provide a Node.js-only entry point (e.g.,index.node.ts) that usesreadFileSync. The existing@open-codesign/corecould then expose both versions via package.jsonexportsormainfields. - At minimum, add a Vite plugin to copy the
.jsxfiles into the final build and ensurenode:fsis externalised if applicable.
- In the development server (
-
[Minor] Unrelated documentation and website changes increase review scope
The diff touches 13 files, but only 3 (package.json and the two core index.ts files) are related to the described fix. The remaining changes (READMEs, website markdown, FAQ, roadmap, llms.txt, QR code image) appear to be separate v0.2 promotion or maintenance work.
Suggested fix:
Split the core compatibility fix into its own PR and handle the documentation updates in a separate PR to keep reviews focused and avoid accidental reverts or conflicts. -
[Minor] Missing tests for the new file-loading logic
No unit tests have been added topackages/coreto verify thatloadFrameandloadSkillwork correctly, or that the replaced modules still export the expected arrays. This regression risk is especially relevant when the loading fails (missing file, wrong path) – the current code throws synchronously, which is acceptable, but uncovered paths can hide edge-case bugs.
Suggested fix:
Add a Vitest unit test that mocksreadFileSyncto control file contents and path resolution, and asserts the shape ofFRAME_TEMPLATESandDESIGN_SKILLS.// packages/core/src/frames/__tests__/index.test.ts import { vi, describe, it, expect } from 'vitest'; vi.mock('node:fs', () => ({ readFileSync: vi.fn((path: string) => `content-of-${path}`) })); import { FRAME_TEMPLATES } from '../index'; describe('FRAME_TEMPLATES', () => { it('returns the expected frame names', () => { expect(FRAME_TEMPLATES.map(([n]) => n)).toEqual([ 'iphone.jsx', 'ipad.jsx', 'watch.jsx', 'android.jsx', 'macos-safari.jsx', ]); }); });
-
[Nit] Adding
"type": "module"to rootpackage.jsonmay affect non‑TypeScript scripts
package.json:2adds"type": "module". The project already usestsxfor Node.js scripts, so ESM behaviour is likely already the default. However, any plain.jsfile (e.g., inscripts/,huskyhooks, or other tooling) that previously relied on CJS will now be treated as ESM.
Suggested fix:
Verify that husky, Biome, and other tools run without errors after this change. If any script requires CJS, rename it to.cjsor adjust the"type"field accordingly.
Questions
- Has the production Electron build (
pnpm buildfollowed by launching the packaged app) been tested with this change? The core frames and design skills are critical; a runtime error here would silently break all designs that use device frames or skill starters. - Are there any Electron renderer restrictions (contextIsolation, nodeIntegration settings) that could block
fsaccess? IfnodeIntegrationis off orcontextIsolationis true,readFileSyncwill not work from the renderer side.
Summary
The conversion from Vite‑specific ?raw imports to readFileSync is a valid intent for Node.js/tsx compatibility, but the implementation may break the production Electron build because the new code relies on runtime filesystem access that Vite does not bundle. The missing test coverage and the unrelated documentation changes further reduce confidence. I recommend blocking the merge until the Electron production path is verified and tests are added.
Testing
- Existing CI should pass
pnpm typecheckandpnpm lint, but no new tests were added for the core loading logic. - Manually validate the production build by running
pnpm buildand launching the packaged application, then creating a design that uses a device frame and a design skill.
Open-CoDesign Bot
Summary
?rawimports inpackages/core/src/frames/index.tsandpackages/core/src/design-skills/index.tswithfs.readFileSync, enabling@open-codesign/coreto be imported from Node.js/tsx contexts (e.g. headless CLI scripts) without Vite running"type": "module"to rootpackage.jsonto support ESM top-levelawaitin scripts that import from the core packageProblem
The
?rawimport suffix is a Vite-only feature. When importing@open-codesign/corefrom a plain Node.js/tsx script (such as the headlessscripts/clone-from-dna.tsorscripts/extract-dna.ts), the import chain fails with:This blocks any headless/CLI usage of the core
generate()function outside of the Vite dev server or Electron app context.Approach
Replaced all
?rawimports with areadFileSynchelper that resolves paths relative toimport.meta.url. This works in both:readFileSyncfinefsmodule, no bundler neededFiles Changed
package.json"type": "module"packages/core/src/frames/index.ts?raw→readFileSyncfor 5 frame JSX filespackages/core/src/design-skills/index.ts?raw→readFileSyncfor 12 skill JSX filesTest plan
pnpm dev— Electron app starts and renders designs normallypnpm build— Production build succeedsnpx tsx scripts/clone-from-dna.ts --help— CLI script imports core without errorsnpx tsx scripts/extract-dna.ts --help— CLI script imports core without errors🤖 Generated with Claude Code