mirror of
https://github.com/actualbudget/actual.git
synced 2026-07-15 22:54:03 -05:00
* api: make the browser build work in consumer production bundles
The browser build shipped `new Worker(new URL("./worker.js", import.meta.url))`
in dist/browser.js. A consumer bundler (Vite/Rollup) recognizes that as a worker
entry and re-bundles the already-prebuilt worker.js from scratch, which desyncs
the absurd-sql/connection RPC so `init` throws a structured-clone error. It only
worked in dev and in the package's own e2e because both serve dist verbatim.
Make the browser build fully self-contained instead:
- Inline the worker into browser.js and spawn it from a Blob URL, so consumer
bundlers never see a worker entry to re-bundle. The worker is built as an IIFE
(classic worker), mirroring the web app's kcab.worker.
- Embed the sql.js wasm and the default filesystem data (migrations + default
DB) into the worker so it performs no PUBLIC_URL asset fetches:
- loot-core sqlite gains an opt-in `setWasmBinary` (dormant for web/node);
- the worker installs a scoped fetch shim serving the embedded data/* files
from a sentinel base URL.
- Share the asset-collection logic between the Node disk copy and the embedded
build via scripts/embedded-assets.mjs so the two never drift.
Result: `import '@actual-app/api'` + `init()` works in any bundler with zero
config; only COOP/COEP headers remain required (SharedArrayBuffer).
Adds an e2e (e2e/consumer + e2e/global-setup.mjs) that builds a real consumer
app for production and boots it under COOP/COEP — coverage the verbatim-dist
harness can't provide. Docs note the build is self-contained and that
cross-origin isolation is still required.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* [AI] api: address review feedback (guard DOM lookup, revoke blob URL on worker failure)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* [AI] api: address review nitpicks (drop BodyInit cast, reword release note)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* [AI] api: build the browser worker via Vite ?worker&inline
Replace the hand-rolled worker inlining (a custom Vite plugin that read the
prebuilt worker.js off disk and inlined it as a string, plus a second build
config and a build-ordering dependency) with Vite's native `?worker&inline`
import. This collapses the two browser build configs into one, removes the
`virtual:actual-worker-code` module and the manual Blob URL spawn, and drops
the worker-before-facade build step.
Vite's `?worker&inline` sub-build doesn't receive vite-plugin-node-polyfills'
global-shim injection (the plugin writes it to `build.rollupOptions`, but the
worker sub-build reads `worker.rollupOptions`), so the worker crashed on
`process is not defined`. Patch the plugin to also emit the injection on
`worker.rollupOptions` — additive and backwards compatible (the web app build,
including loot-core's nodePolyfills worker, is unaffected).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* [AI] api: embed browser assets via Vite, drop the embedded-assets script
Replace scripts/embedded-assets.mjs with Vite-native asset imports in the
worker entry: `?inline` for the sql.js wasm and default DB, `import.meta.glob`
(`?raw`) for the migrations. The worker builds the default-filesystem wire
format from those at module load, so the embedded set comes straight from
loot-core and can't drift.
The Node build only needs migrations + the default DB on disk (it reads them at
runtime); the old script also wrote sql-wasm.wasm and the data/ fetch tree,
which are dead now that the browser worker is self-contained. Replace
writeEmbeddedAssetsToDist with a small closeBundle copy of just those two.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* [AI] api: simplify embedded data map; drop loot-core comment churn
Merge the worker's binData/textData into a single dataFiles map (Response
accepts both bytes and strings), collapsing the fetch shim's two lookups into
one. Revert the unrelated comment edits to loot-core's backend-worker.ts and
fs/index.ts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* [AI] api: rename e2e consumer-dist to consumer/dist; drop a prose comment
Use the standard `dist` directory name for the consumer fixture's build output
(now e2e/consumer/dist), and remove the verbose comment from index.browser.ts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* [AI] loot-core: own the default-filesystem assets; consumers stop reaching in
Add packages/loot-core/default-filesystem.mjs as the single source of truth for
loot-core's runtime assets (sql.js wasm, default DB, migrations) and the
data-file-index wire format, exported as @actual-app/core/default-filesystem.
- @actual-app/api: the browser worker embeds them via the actual-embedded-assets
Vite plugin (which calls collectEmbeddedAssets), replacing the relative
?inline/?raw/import.meta.glob reaches into ../loot-core; the Node build copies
migrations + default DB using the helper's paths. Drops the direct
@jlongster/sql.js devDependency (loot-core resolves the wasm).
- @actual-app/web: stagePublicData copies from the helper's paths instead of
hardcoding loot-core's tree and the sql.js wasm location.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* [AI] loot-core: scan migrations once when collecting embedded assets
collectEmbeddedAssets() read the migrations directory twice — once in its
own loop and once via buildDataFileIndex(). List the names once and pass
them through, keeping the index wire-format defined in a single place.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
129 lines
5.0 KiB
JSON
129 lines
5.0 KiB
JSON
{
|
|
"name": "actual",
|
|
"version": "0.0.1",
|
|
"private": true,
|
|
"description": "A local-first personal finance system",
|
|
"homepage": "https://github.com/actualbudget/actual/",
|
|
"bugs": {
|
|
"url": "https://github.com/actualbudget/actual/issues/"
|
|
},
|
|
"license": "MIT",
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "git@github.com:actualbudget/actual.git"
|
|
},
|
|
"workspaces": {
|
|
"packages": [
|
|
"packages/*"
|
|
]
|
|
},
|
|
"scripts": {
|
|
"start": "yarn start:browser",
|
|
"start:server": "yarn workspace @actual-app/sync-server start",
|
|
"start:server-monitor": "yarn workspace @actual-app/sync-server start-monitor",
|
|
"start:server-dev": "NODE_ENV=development BROWSER_OPEN=localhost:5006 yarn npm-run-all --parallel 'start:server-monitor' 'start'",
|
|
"start:desktop": "yarn desktop-dependencies && npm-run-all --parallel 'start:desktop-*'",
|
|
"start:docs": "yarn workspace docs start",
|
|
"desktop-dependencies": "npm-run-all --parallel rebuild-electron build:plugins-service",
|
|
"start:desktop-node": "yarn workspace @actual-app/core watch:node",
|
|
"start:desktop-client": "yarn workspace @actual-app/web watch",
|
|
"start:desktop-server-client": "yarn workspace @actual-app/web build:browser",
|
|
"start:desktop-electron": "yarn workspace desktop-electron watch",
|
|
"start:browser": "npm-run-all --parallel 'start:browser-*' 'start:service-plugins'",
|
|
"start:service-plugins": "yarn workspace plugins-service watch",
|
|
"start:browser-frontend": "yarn workspace @actual-app/web start:browser",
|
|
"start:storybook": "yarn workspace @actual-app/components start:storybook",
|
|
"build": "lage build",
|
|
"build:server": "yarn build:browser && yarn workspace @actual-app/sync-server build",
|
|
"build:browser": "./bin/package-browser",
|
|
"build:desktop": "./bin/package-electron",
|
|
"build:plugins-service": "yarn workspace plugins-service build",
|
|
"build:api": "yarn build --scope=@actual-app/api",
|
|
"build:cli": "yarn build --scope=@actual-app/cli",
|
|
"build:docs": "yarn workspace docs build",
|
|
"build:storybook": "yarn workspace @actual-app/components build:storybook",
|
|
"deploy:docs": "yarn workspace docs deploy",
|
|
"generate:i18n": "yarn workspace @actual-app/web generate:i18n",
|
|
"generate:release-notes": "node ./bin/release-note-generator.mts",
|
|
"test": "lage test --continue",
|
|
"test:debug": "lage test --no-cache --continue",
|
|
"e2e": "yarn workspace @actual-app/web run e2e",
|
|
"e2e:desktop": "yarn build:desktop --skip-exe-build --skip-translations && yarn workspace desktop-electron e2e",
|
|
"playwright": "yarn workspace @actual-app/web run playwright",
|
|
"vrt": "yarn workspace @actual-app/web run vrt",
|
|
"vrt:docker": "./bin/run-vrt",
|
|
"rebuild-electron": "./node_modules/.bin/electron-rebuild -m ./packages/desktop-electron -o better-sqlite3,bcrypt --build-from-source -f",
|
|
"rebuild-node": "yarn workspace @actual-app/core rebuild",
|
|
"lint": "oxfmt --check . && oxlint --type-aware --quiet",
|
|
"lint:fix": "oxfmt . && oxlint --fix --type-aware --quiet",
|
|
"knip": "knip",
|
|
"install:server": "yarn workspaces focus @actual-app/sync-server --production",
|
|
"constraints": "yarn constraints",
|
|
"typecheck": "tsgo -p tsconfig.root.json --noEmit && lage typecheck",
|
|
"check:tsconfig-references": "workspaces-to-typescript-project-references --check",
|
|
"sync:tsconfig-references": "workspaces-to-typescript-project-references",
|
|
"prepare": "husky"
|
|
},
|
|
"devDependencies": {
|
|
"@monorepo-utils/workspaces-to-typescript-project-references": "^2.11.0",
|
|
"@octokit/rest": "^22.0.1",
|
|
"@types/node": "^22.19.21",
|
|
"@types/prompts": "^2.4.9",
|
|
"@typescript/native-preview": "beta",
|
|
"@yarnpkg/types": "^4.0.1",
|
|
"eslint": "^10.5.0",
|
|
"eslint-plugin-perfectionist": "^5.9.0",
|
|
"eslint-plugin-typescript-paths": "^0.0.33",
|
|
"husky": "^9.1.7",
|
|
"knip": "^6.17.1",
|
|
"lage": "^2.15.13",
|
|
"minimatch": "^10.2.5",
|
|
"nano-staged": "^1.0.2",
|
|
"npm-run-all": "^4.1.5",
|
|
"oxfmt": "^0.44.0",
|
|
"oxlint": "^1.69.0",
|
|
"oxlint-tsgolint": "^0.23.0",
|
|
"p-limit": "^7.3.0",
|
|
"prompts": "^2.4.2",
|
|
"typescript": "^6.0.3",
|
|
"vitest": "^4.1.8"
|
|
},
|
|
"dependenciesMeta": {
|
|
"bcrypt": {
|
|
"built": true
|
|
},
|
|
"better-sqlite3": {
|
|
"built": true
|
|
},
|
|
"electron": {
|
|
"built": true
|
|
},
|
|
"esbuild": {
|
|
"built": true
|
|
},
|
|
"sharp": {
|
|
"built": true
|
|
}
|
|
},
|
|
"optionalDependencies": {
|
|
"glob-hasher-linux-arm64-gnu": "1.4.2"
|
|
},
|
|
"resolutions": {
|
|
"adm-zip": "patch:adm-zip@npm%3A0.5.16#~/.yarn/patches/adm-zip-npm-0.5.16-4556fea098.patch",
|
|
"minimatch@3.1.2": "3.1.5",
|
|
"serialize-javascript": "^7.0.5",
|
|
"socks": ">=2.8.3",
|
|
"vite-plugin-node-polyfills": "patch:vite-plugin-node-polyfills@npm%3A0.28.0#~/.yarn/patches/vite-plugin-node-polyfills-npm-0.28.0-bac39616ee.patch",
|
|
"webpackbar": "^7.0.0"
|
|
},
|
|
"browserslist": [
|
|
"electron >= 35.0",
|
|
"defaults"
|
|
],
|
|
"engines": {
|
|
"node": ">=22.18.0",
|
|
"yarn": "^4.9.1"
|
|
},
|
|
"packageManager": "yarn@4.13.0"
|
|
}
|