Skip to content

Commit 5a17e5d

Browse files
authored
fix(backend+ci): try to bundle for windows 🙈 (#46)
1 parent 6a38a47 commit 5a17e5d

6 files changed

Lines changed: 186 additions & 104 deletions

File tree

backend/bun/package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,11 @@
88
"format": "prettier --write .",
99
"prepublishOnly": "npm run build && npm run lint"
1010
},
11-
"private": true
11+
"private": true,
12+
"devDependencies": {
13+
"chromium-bidi": "12.0.1",
14+
"electron": "39.2.7",
15+
"handlebars": "4.7.8",
16+
"playwright-core": "1.57.0"
17+
}
1218
}

backend/bun/src/utils/htmlToImage.ts

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { chromium } from "playwright-core";
1+
// Use dynamic import for playwright-core to avoid bundling issues
2+
// This allows playwright-core to be loaded at runtime from node_modules
23
import type { Page } from "playwright-core";
34

45
export interface HtmlToImageOptions {
@@ -11,12 +12,53 @@ export interface HtmlToImageOptions {
1112
executablePath?: string | null;
1213
}
1314

15+
/**
16+
* Dynamically loads playwright-core at runtime
17+
* due to dynamic imports and native dependencies
18+
*/
19+
async function loadPlaywright() {
20+
const path = await import("node:path");
21+
const fs = await import("node:fs");
22+
23+
// For compiled binaries, playwright-core should be in node_modules relative to the executable
24+
// Try bundled location first (for production builds)
25+
if (process.execPath) {
26+
const execDir = path.dirname(process.execPath);
27+
const bundledPath = path.join(execDir, "node_modules", "playwright-core");
28+
29+
if (fs.existsSync(bundledPath)) {
30+
try {
31+
// Use file:// URL for absolute path import
32+
const playwright = await import(path.resolve(bundledPath));
33+
return playwright.chromium;
34+
} catch (error) {
35+
// Fall through to standard import
36+
}
37+
}
38+
}
39+
40+
// Try standard import (works for development and if node_modules is in module resolution path)
41+
try {
42+
const playwright = await import("playwright-core");
43+
return playwright.chromium;
44+
} catch (error) {
45+
throw new Error(
46+
`Failed to load playwright-core: ${
47+
error instanceof Error ? error.message : String(error)
48+
}. ` +
49+
"Make sure playwright-core is installed or bundled with the application in node_modules/playwright-core.",
50+
);
51+
}
52+
}
53+
1454
/**
1555
* Converts HTML to an image using Playwright.
1656
* @param options - Configuration options for the image generation
1757
* @returns Buffer containing the image data
1858
*/
19-
export async function htmlToImage(options: HtmlToImageOptions): Promise<Buffer> {
59+
export async function htmlToImage(
60+
options: HtmlToImageOptions,
61+
): Promise<Buffer> {
2062
const {
2163
html,
2264
output,
@@ -27,10 +69,18 @@ export async function htmlToImage(options: HtmlToImageOptions): Promise<Buffer>
2769
executablePath,
2870
} = options;
2971

72+
// Dynamically load playwright-core
73+
const chromium = await loadPlaywright();
74+
3075
// Launch browser with appropriate settings
3176
const launchOptions: Parameters<typeof chromium.launch>[0] = {
3277
headless: true,
33-
args: ["--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage", "--disable-gpu"],
78+
args: [
79+
"--no-sandbox",
80+
"--disable-setuid-sandbox",
81+
"--disable-dev-shm-usage",
82+
"--disable-gpu",
83+
],
3484
};
3585

3686
// If executable path is provided, use it explicitly
@@ -45,7 +95,11 @@ export async function htmlToImage(options: HtmlToImageOptions): Promise<Buffer>
4595

4696
// Set content with HTML
4797
await page.setContent(html, {
48-
waitUntil: waitUntil as "load" | "domcontentloaded" | "networkidle" | "commit",
98+
waitUntil: waitUntil as
99+
| "load"
100+
| "domcontentloaded"
101+
| "networkidle"
102+
| "commit",
49103
});
50104

51105
// Measure the actual rendered content width to respect max-width constraints
@@ -60,7 +114,11 @@ export async function htmlToImage(options: HtmlToImageOptions): Promise<Buffer>
60114

61115
// Use body dimensions which respect max-width constraints
62116
const width = bodyRect.width;
63-
const height = Math.max(body.scrollHeight, document.documentElement.scrollHeight, bodyRect.height);
117+
const height = Math.max(
118+
body.scrollHeight,
119+
document.documentElement.scrollHeight,
120+
bodyRect.height,
121+
);
64122

65123
return {
66124
width: Math.ceil(width),
@@ -98,7 +156,9 @@ export async function htmlToImage(options: HtmlToImageOptions): Promise<Buffer>
98156
});
99157

100158
// Convert to Buffer if needed
101-
const buffer = screenshotBuffer instanceof Buffer ? screenshotBuffer : Buffer.from(screenshotBuffer);
159+
const buffer = screenshotBuffer instanceof Buffer
160+
? screenshotBuffer
161+
: Buffer.from(screenshotBuffer);
102162

103163
return buffer;
104164
} finally {

bun.lock

Lines changed: 24 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
],
1010
"scripts": {
1111
"prepare": "bun run --cwd web svelte-kit sync || echo ''",
12-
"postinstall": "bunx simple-git-hooks && bunx playwright install chromium --only-shell",
12+
"postinstall": "bunx simple-git-hooks",
1313
"format": "eslint --fix . && prettier -w .",
1414
"web:dev": "bun run --cwd web vite dev",
1515
"web:build": "bun run --cwd web vite build"
@@ -22,34 +22,21 @@
2222
"@sveltejs/adapter-static": "3.0.10",
2323
"@sveltejs/kit": "2.47.3",
2424
"@sveltejs/vite-plugin-svelte": "6.2.1",
25-
"@tailwindcss/vite": "4.0.13",
2625
"@types/bun": "1.3.3",
2726
"@types/eslint": "9.6.1",
28-
"chromium-bidi": "12.0.1",
29-
"daisyui": "5.0.2",
30-
"electron": "39.2.7",
27+
"@types/node": "25.0.3",
3128
"eslint": "9.39.1",
3229
"eslint-config-prettier": "10.1.8",
3330
"eslint-plugin-svelte": "3.13.1",
3431
"file-type": "21.1.1",
3532
"globals": "16.5.0",
36-
"handlebars": "4.7.8",
3733
"husky": "9.1.7",
3834
"install": "0.13.0",
3935
"jiti": "2.6.1",
40-
"mdsvex": "0.12.6",
41-
"playwright-core": "1.57.0",
4236
"prettier": "3.7.4",
4337
"prettier-plugin-svelte": "3.4.1",
4438
"prettier-plugin-tailwindcss": "0.6.11",
45-
"rehype-autolink-headings": "7.1.0",
46-
"rehype-slug-custom-id": "2.0.0",
47-
"svelte": "5.41.4",
48-
"svelte-check": "4.3.3",
49-
"svelte-eslint-parser": "1.4.1",
50-
"svelte-sitemap": "2.7.1",
5139
"tailwind-csstree": "0.1.4",
52-
"tailwindcss": "4.0.13",
5340
"typescript": "5.9.3",
5441
"typescript-eslint": "8.49.0",
5542
"vite": "7.3.0",

0 commit comments

Comments
 (0)