From 4dbb1e8b71ff99c6d4385953377c06256136a87c Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Thu, 11 Jun 2026 13:14:25 +0000 Subject: [PATCH] fix(frontend): make packaged runes-module imports resolvable by consumers --- frontend/package.json | 2 +- frontend/scripts/fix-svelte-module-imports.js | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 frontend/scripts/fix-svelte-module-imports.js diff --git a/frontend/package.json b/frontend/package.json index 65111d6101..952a94aa10 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,7 +13,7 @@ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .", "format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. .", - "package": "svelte-package -o package && node scripts/package-system-prompts.js", + "package": "svelte-package -o package && node scripts/package-system-prompts.js && node scripts/fix-svelte-module-imports.js", "generate-backend-client": "openapi-ts --input ../backend/windmill-api/openapi.yaml --output ./src/lib/gen --useOptions --enums javascript --format false", "generate-backend-client-mac": "openapi-ts --input ../backend/windmill-api/openapi.yaml --output ./src/lib/gen --useOptions --enums javascript", "pretest": "tsc --incremental -p tests/tsconfig.json", diff --git a/frontend/scripts/fix-svelte-module-imports.js b/frontend/scripts/fix-svelte-module-imports.js new file mode 100644 index 0000000000..2bb7af6b84 --- /dev/null +++ b/frontend/scripts/fix-svelte-module-imports.js @@ -0,0 +1,60 @@ +// Rewrite extension-less runes-module imports in the svelte-package output. +// +// Source files import runes modules (`foo.svelte.ts`) as `$lib/foo.svelte`, +// which Vite resolves inside this repo by appending `.ts`. svelte-package +// emits those modules as `foo.svelte.js` but keeps the import specifier as +// `../foo.svelte`, which consumers of @windmill-labs/components cannot +// resolve (their bundler looks for a `.svelte` component file that does not +// exist). Append `.js` to any relative `.svelte` specifier whose target only +// exists as `.js` in the package output. +import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'fs' +import { fileURLToPath } from 'url' +import { dirname, join, resolve } from 'path' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) + +const packageDir = resolve(__dirname, '..', 'package') + +const IMPORT_SPECIFIER_RE = /(\bfrom\s*|\bimport\s*\(?\s*)(['"])(\.\.?\/[^'"]*\.svelte)\2/g + +function* walk(dir) { + for (const entry of readdirSync(dir)) { + const full = join(dir, entry) + if (statSync(full).isDirectory()) { + yield* walk(full) + } else if (/\.(js|svelte|ts)$/.test(entry)) { + yield full + } + } +} + +let rewrittenFiles = 0 +let rewrittenImports = 0 + +for (const file of walk(packageDir)) { + const content = readFileSync(file, 'utf-8') + let changed = false + const updated = content.replace(IMPORT_SPECIFIER_RE, (match, prefix, quote, specifier) => { + const target = resolve(dirname(file), specifier) + // A real `.svelte` component file: leave the import alone. + if (existsSync(target)) { + return match + } + // A runes module emitted as `.svelte.js`: make the extension explicit. + if (existsSync(target + '.js')) { + changed = true + rewrittenImports++ + return `${prefix}${quote}${specifier}.js${quote}` + } + return match + }) + if (changed) { + writeFileSync(file, updated) + rewrittenFiles++ + } +} + +console.log( + `fix-svelte-module-imports: rewrote ${rewrittenImports} import(s) in ${rewrittenFiles} file(s)` +)