diff options
| author | Adam Soltys <[email protected]> | 2026-07-04 09:10:04 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-07-04 09:10:04 -0700 |
| commit | 11b2a56a320bbd66b98991fd08478d154ff6c717 (patch) | |
| tree | 035e64613eda8ea99cee6c7d7de352ed6bbdf2fe /build.js | |
| parent | 5fb48ee5284dbba34c8fa3b77c36379f49404ac2 (diff) | |
| download | coinosv3-11b2a56a320bbd66b98991fd08478d154ff6c717.tar.gz coinosv3-11b2a56a320bbd66b98991fd08478d154ff6c717.zip | |
Build profiles: HAL_FEATURES selects which features ship
build.js swaps src/features/index.js for a generated module importing
only the enabled features (gifts,swaps,ark,sp — unset means all,
"none" means a plain on-chain wallet), so excluded feature code and
its network endpoints never enter the bundle. Minimal profile:
476KB vs 577KB, with the Ark/gRPC, Boltz, and MuSig2 code verifiably
absent. `bun run build:minimal` builds it.
tools/minimal-smoke.js proves the minimal profile end-to-end: no
receive-mode dropdown, no gift button, no swap/Ark/SP settings cards,
no page errors, and a plain on-chain receive still lands. The two
blessed profiles are full (everything, the existing e2e suites) and
minimal (this smoke test); other combos should work but aren't CI'd.
Gift and SP primitives still live inside wallet.js, so those bytes
remain in the minimal bundle for now — extracting them is the next
step if we want the core leaner still.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
Diffstat (limited to 'build.js')
| -rw-r--r-- | build.js | 30 |
1 files changed, 29 insertions, 1 deletions
@@ -136,11 +136,39 @@ export async function buildSpWorker({ minify = true } = {}) { return result.outputs[0].text(); } -export async function buildHtml({ minify = true, pwa = minify } = {}) { +// Optional-feature selection: HAL_FEATURES is a comma list of enabled +// features (gifts,swaps,ark,sp). Unset means all; "none"/"" means a minimal +// on-chain-only wallet. A build plugin swaps src/features/index.js for a +// generated module that only imports the enabled features, so a disabled +// feature's code (and its network endpoints) never enters the bundle. +const ALL_FEATURES = { gifts: 'giftsFeature', swaps: 'swapsFeature', ark: 'arkFeature', sp: 'spFeature' }; + +export function enabledFeatures(spec = process.env.HAL_FEATURES) { + if (spec == null) return Object.keys(ALL_FEATURES); + return spec.split(',').map((x) => x.trim().toLowerCase()).filter((x) => x in ALL_FEATURES); +} + +function featureIndexSource(enabled) { + return enabled.map((f) => `import { ${ALL_FEATURES[f]} } from './${f}.js';`).join('\n') + + `\nexport function buildFeatures(ctx) { return [${enabled.map((f) => `${ALL_FEATURES[f]}(ctx)`).join(', ')}]; }\n`; +} + +const featurePlugin = (enabled) => ({ + name: 'hal-features', + setup(b) { + b.onLoad({ filter: /src[\/\\]features[\/\\]index\.js$/ }, () => ({ + contents: featureIndexSource(enabled), + loader: 'js', + })); + }, +}); + +export async function buildHtml({ minify = true, pwa = minify, features = process.env.HAL_FEATURES } = {}) { const result = await Bun.build({ entrypoints: ['./src/app.js'], target: 'browser', minify, + plugins: [featurePlugin(enabledFeatures(features))], }); if (!result.success) { for (const log of result.logs) console.error(log); |
