scripts/build-components.ts 3.0 K raw
1
import { mkdir, copyFile, readFile, writeFile } from "node:fs/promises";
2
import { existsSync } from "node:fs";
3
4
async function buildComponents() {
5
	console.log("🔨 Building components...");
6
7
	// Ensure dist/components directory exists
8
	const distComponentsDir = "dist/components";
9
	if (!existsSync(distComponentsDir)) {
10
		await mkdir(distComponentsDir, { recursive: true });
11
	}
12
13
	// Copy connect-wallet.js as-is (no dependencies)
14
	await copyFile(
15
		"src/components/connect-wallet.js",
16
		"dist/components/connect-wallet.js",
17
	);
18
	console.log("✅ Copied connect-wallet.js");
19
20
	// Helper function to bundle and reorganize component with dependencies
21
	async function bundleComponent(componentName: string, className: string) {
22
		const result = await Bun.build({
23
			entrypoints: [`src/components/${componentName}.js`],
24
			target: "browser",
25
			format: "esm",
26
			minify: false,
27
			sourcemap: "none",
28
			splitting: false,
29
			outdir: "dist/components",
30
			naming: "[dir]/[name].[ext]",
31
			external: [], // Bundle all dependencies
32
			plugins: [
33
				{
34
					name: "Keep JSDocs",
35
					setup(build) {
36
						build.onLoad({ filter: /\.(js)$/ }, async ({ path }) => {
37
							let text = await Bun.file(path).text();
38
							// Replace '/**' with '/*! *' to mark comments as "important" for minifiers
39
							let contents = text.replaceAll("/**", "/*! *");
40
							return { contents, loader: "js" };
41
						});
42
					},
43
				},
44
			],
45
		});
46
47
		if (!result.success) {
48
			console.error(`❌ Build failed for ${componentName}:`);
49
			for (const log of result.logs) {
50
				console.error(log);
51
			}
52
			process.exit(1);
53
		}
54
55
		console.log(`✅ Bundled ${componentName}.js with dependencies`);
56
57
		// Read the bundled file
58
		const bundledContent = await readFile(
59
			`dist/components/${componentName}.js`,
60
			"utf8",
61
		);
62
63
		// Split content to move dependencies to bottom
64
		const lines = bundledContent.split("\n");
65
		const componentStartIndex = lines.findIndex((line) =>
66
			line.includes(`class ${className} extends HTMLElement`),
67
		);
68
69
		if (componentStartIndex > 0) {
70
			// Dependencies are at the top (before the component class)
71
			const dependencies = lines.slice(0, componentStartIndex).join("\n");
72
			const componentCode = lines.slice(componentStartIndex).join("\n");
73
74
			// Create new content with component first, then dependencies
75
			const newContent = `// User-editable ${componentName} component
76
// @noble/hashes are bundled at the bottom of this file
77
78
${componentCode}
79
80
// ==========================================
81
// BUNDLED DEPENDENCIES BELOW
82
// ==========================================
83
84
${dependencies}`;
85
86
			await writeFile(
87
				`dist/components/${componentName}.js`,
88
				newContent,
89
				"utf8",
90
			);
91
			console.log(
92
				`✅ Reorganized ${componentName}.js (component code first, dependencies at bottom)`,
93
			);
94
		}
95
	}
96
97
	// Bundle contract-call.js with its dependencies
98
	await bundleComponent("contract-call", "ContractCall");
99
100
	// Bundle contract-read.js with its dependencies
101
	await bundleComponent("contract-read", "ContractRead");
102
103
	console.log("🎉 Component build complete!");
104
}
105
106
buildComponents().catch(console.error);