Files
Matiss Janis Aboltins ff0f5bdb35 [AI] lage - move browser build to using lage (#7602)
* Simplify desktop client browser build

* [AI] Move browser build orchestration into vite config and lage

Moves loot-core worker build, public/ staging (migrations, default-db,
sql-wasm, data-file-index), and build-stats wiring from the deleted
packages/desktop-client/bin/build-browser shell script into a
lootCoreBackend vite plugin in packages/desktop-client/vite.config.mts.

Adds a build:browser target to lage.config.js so bin/package-browser
runs as a single `lage build:browser --to=@actual-app/web` call, with
crdt + loot-core built via lage's ^build dependency before the
desktop-client build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Refactor e2e-test workflow and update desktop-client configurations

* [AI] Move plugins-service staging into desktop-client vite config

Declares plugins-service as a workspace devDependency of @actual-app/web
so lage's ^build edge picks it up automatically in the build:browser
pipeline, and moves the cross-package file staging (production copy +
dev serving) into vite.config.mts, mirroring the lootCoreBackend
pattern. Drops the plugins-service shell wrapper script and simplifies
its package.json scripts to invoke vite build directly. Updates root
start:browser to run plugins-service watch in parallel with the dev
server instead of pre-building once.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Sync tsconfig project references for plugins-service edge

Follow-up to the plugins-service workspace edge: adds the
../plugins-service project reference in packages/desktop-client/tsconfig.json
via yarn sync:tsconfig-references.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Release notes

* [AI] Ignore .venv/ so lage's git hasher skips Electron CI's Python venv

Electron CI provisions a Python virtualenv at the repo root for
setuptools. With browser builds now routed through lage, lage's
git hash-object pass walks untracked-not-ignored files and fails on
the venv's broken lib64 symlink ("fatal: Unable to hash .../.venv/lib64").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Bake Weblate translations back into VRT/e2e bundle

build-web set download-translations: false and relied on bin/package-browser's
ad-hoc git clone + git pull. That path is fragile inside the playwright
container, so vite's import.meta.glob('/locale/*.json') frequently produced an
empty languages map and the bundle shipped with no en.json. VRTs then rendered
source-code English and diffed against snapshots authored from Weblate strings.

Route translation provisioning back through actions/checkout (download-translations: true)
in build-web and vrt-update-generate, and add --skip-translations to bin/package-browser
(mirroring bin/package-electron) so the in-script git pull is bypassed when CI
has already staged the locale dir.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [AI] Skip translation cloning in build-web bundle for VRT determinism

bin/package-browser used to unconditionally clone actualbudget/translations
before vite ran, baking Weblate en.json into the build artifact. With the
e2e-test pipeline now serving that artifact via serve-build.mjs, VRT
screenshots ended up rendering Weblate strings — drifting from the snapshots,
which were authored against source-code English (master VRTs ran on vite dev
without a locale dir).

Pass --skip-translations to bin/package-browser from build-web so the bundle
ships with no locale chunks. download-translations stays 'false' across the
e2e-test and vrt-update-generate workflows, matching the prior behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 20:20:13 +00:00

200 lines
8.7 KiB
JSON

{
"name": "@actual-app/web",
"version": "26.4.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/actualbudget/actual.git",
"directory": "packages/desktop-client"
},
"files": [
"build"
],
"imports": {
"#browser-preload": {
"electron-renderer": "./src/browser-preload.electron.ts",
"default": "./src/browser-preload.js"
},
"#accounts": "./src/accounts/index.ts",
"#budget": "./src/budget/index.ts",
"#payees": "./src/payees/index.ts",
"#queries": "./src/queries/index.ts",
"#redux": "./src/redux/index.ts",
"#reports": "./src/reports/index.ts",
"#spreadsheet": "./src/spreadsheet/index.ts",
"#style": "./src/style/index.ts",
"#tags": "./src/tags/index.ts",
"#transactions": "./src/transactions/index.ts",
"#undo": "./src/undo/index.ts",
"#global-events": "./src/global-events.ts",
"#gocardless": "./src/gocardless.ts",
"#i18n": "./src/i18n.ts",
"#mocks": "./src/mocks.tsx",
"#mocks/*": "./src/mocks/*.ts",
"#polyfills": "./src/polyfills.ts",
"#components/forms": "./src/components/forms/index.tsx",
"#components/banksync": "./src/components/banksync/index.tsx",
"#components/banksync/useBankSyncAccountSettings": "./src/components/banksync/useBankSyncAccountSettings.ts",
"#components/budget": "./src/components/budget/index.tsx",
"#components/budget/goals/actions": "./src/components/budget/goals/actions.ts",
"#components/budget/goals/constants": "./src/components/budget/goals/constants.ts",
"#components/budget/goals/reducer": "./src/components/budget/goals/reducer.ts",
"#components/budget/goals/useBudgetAutomationCategories": "./src/components/budget/goals/useBudgetAutomationCategories.ts",
"#components/budget/util": "./src/components/budget/util.ts",
"#components/codemirror/autocompleteTabAccept": "./src/components/codemirror/autocompleteTabAccept.ts",
"#components/mobile/utils": "./src/components/mobile/utils.ts",
"#components/reports/chart-theme": "./src/components/reports/chart-theme.ts",
"#components/reports/constants": "./src/components/reports/constants.ts",
"#components/reports/disabledList": "./src/components/reports/disabledList.ts",
"#components/reports/getCustomTick": "./src/components/reports/getCustomTick.ts",
"#components/reports/getLiveRange": "./src/components/reports/getLiveRange.ts",
"#components/reports/graphs/showActivity": "./src/components/reports/graphs/showActivity.ts",
"#components/reports/numberFormatter": "./src/components/reports/numberFormatter.ts",
"#components/reports/ReportOptions": "./src/components/reports/ReportOptions.ts",
"#components/reports/reportRanges": "./src/components/reports/reportRanges.ts",
"#components/reports/setSessionReport": "./src/components/reports/setSessionReport.ts",
"#components/reports/spreadsheets/cash-flow-spreadsheet": "./src/components/reports/spreadsheets/cash-flow-spreadsheet.tsx",
"#components/reports/spreadsheets/*": "./src/components/reports/spreadsheets/*.ts",
"#components/reports/useDashboardWidgetCopyMenu": "./src/components/reports/useDashboardWidgetCopyMenu.ts",
"#components/reports/useReport": "./src/components/reports/useReport.ts",
"#components/reports/util": "./src/components/reports/util.ts",
"#components/schedules": "./src/components/schedules/index.tsx",
"#components/schedules/schedule-edit-utils": "./src/components/schedules/schedule-edit-utils.ts",
"#components/util/accountValidation": "./src/components/util/accountValidation.ts",
"#components/util/countries": "./src/components/util/countries.ts",
"#components/util/localeToCountry": "./src/components/util/localeToCountry.ts",
"#components/*": "./src/components/*.tsx",
"#hooks/useCachedSchedules": "./src/hooks/useCachedSchedules.tsx",
"#hooks/useDisplayPayee": "./src/hooks/useDisplayPayee.tsx",
"#hooks/useDragDrop": "./src/hooks/useDragDrop.tsx",
"#hooks/useProperFocus": "./src/hooks/useProperFocus.tsx",
"#hooks/useScrollListener": "./src/hooks/useScrollListener.tsx",
"#hooks/useSelected": "./src/hooks/useSelected.tsx",
"#hooks/useSheetName": "./src/hooks/useSheetName.tsx",
"#hooks/useSingleActiveEditForm": "./src/hooks/useSingleActiveEditForm.tsx",
"#hooks/useSplitsExpanded": "./src/hooks/useSplitsExpanded.tsx",
"#hooks/useSpreadsheet": "./src/hooks/useSpreadsheet.tsx",
"#hooks/*": "./src/hooks/*.ts",
"#auth/AuthProvider": "./src/auth/AuthProvider.tsx",
"#auth/ProtectedRoute": "./src/auth/ProtectedRoute.tsx",
"#auth/*": "./src/auth/*.ts",
"#style/theme": "./src/style/theme.tsx",
"#style/*": "./src/style/*.ts",
"#notes/*": "./src/notes/*.tsx",
"#accounts/*": "./src/accounts/*.ts",
"#app/*": "./src/app/*.ts",
"#budget/*": "./src/budget/*.ts",
"#budgetfiles/*": "./src/budgetfiles/*.ts",
"#modals/*": "./src/modals/*.ts",
"#notifications/*": "./src/notifications/*.ts",
"#payees/*": "./src/payees/*.ts",
"#prefs/*": "./src/prefs/*.ts",
"#queries/*": "./src/queries/*.ts",
"#redux/*": "./src/redux/*.ts",
"#reports/*": "./src/reports/*.ts",
"#spreadsheet/*": "./src/spreadsheet/*.ts",
"#tags/*": "./src/tags/*.ts",
"#transactions/*": "./src/transactions/*.ts",
"#undo/*": "./src/undo/*.ts",
"#users/*": "./src/users/*.ts",
"#util/*": "./src/util/*.ts"
},
"scripts": {
"start": "cross-env PORT=3001 vite",
"start:browser": "cross-env ./bin/watch-browser",
"watch": "cross-env BROWSER=none yarn start",
"build": "vite build",
"build:browser": "vite build --mode=browser",
"generate:i18n": "i18next",
"test": "vitest --run",
"validate:theme-catalog": "node --experimental-strip-types bin/validate-theme-catalog.mts",
"e2e": "npx playwright test --browser=chromium",
"vrt": "cross-env VRT=true npx playwright test --browser=chromium",
"playwright": "playwright",
"typecheck": "tsgo -b && tsc-strict"
},
"devDependencies": {
"@actual-app/components": "workspace:*",
"@actual-app/core": "workspace:*",
"@babel/core": "^7.29.0",
"@codemirror/autocomplete": "^6.20.1",
"@codemirror/language": "^6.12.3",
"@codemirror/state": "^6.6.0",
"@codemirror/view": "^6.41.0",
"@emotion/css": "^11.13.5",
"@fontsource-variable/inter": "^5.2.8",
"@fontsource/redacted-script": "^5.2.8",
"@juggle/resize-observer": "^3.4.0",
"@lezer/highlight": "^1.2.3",
"@playwright/test": "1.59.1",
"@react-aria/interactions": "^3.27.1",
"@reduxjs/toolkit": "^2.11.2",
"@rolldown/plugin-babel": "~0.1.8",
"@rollup/plugin-inject": "^5.0.5",
"@tanstack/react-query": "^5.96.2",
"@testing-library/dom": "10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "16.3.2",
"@testing-library/user-event": "14.6.1",
"@types/lodash": "^4",
"@types/pikaday": "^1.7.10",
"@types/promise-retry": "^1.1.6",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@typescript/native-preview": "beta",
"@uiw/react-codemirror": "^4.25.9",
"@use-gesture/react": "^10.3.1",
"@vitejs/plugin-basic-ssl": "^2.3.0",
"@vitejs/plugin-react": "^6.0.1",
"absurd-sql": "0.0.54",
"auto-text-size": "^0.2.3",
"babel-plugin-react-compiler": "^1.0.0",
"cmdk": "^1.1.1",
"cross-env": "^10.1.0",
"date-fns": "^4.1.0",
"downshift": "9.3.2",
"html-to-image": "^1.11.13",
"hyperformula": "^3.2.0",
"i18next": "^25.10.10",
"i18next-parser": "^9.4.0",
"i18next-resources-to-backend": "^1.2.1",
"jsdom": "^27.4.0",
"lodash": "^4.18.1",
"lru-cache": "^11.2.7",
"mdast-util-newline-to-break": "^2.0.0",
"memoize-one": "^6.0.0",
"pikaday": "1.8.2",
"plugins-service": "workspace:*",
"promise-retry": "^2.0.1",
"re-resizable": "^6.11.2",
"react": "19.2.4",
"react-aria": "^3.47.0",
"react-aria-components": "^1.16.0",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "19.2.4",
"react-error-boundary": "^6.1.1",
"react-grid-layout": "^2.2.3",
"react-hotkeys-hook": "^5.2.4",
"react-i18next": "^16.6.6",
"react-markdown": "^10.1.0",
"react-redux": "^9.2.0",
"react-router": "7.13.1",
"react-simple-pull-to-refresh": "^1.3.4",
"react-spring": "^10.0.3",
"react-swipeable": "^7.0.2",
"react-virtualized-auto-sizer": "^2.0.3",
"recharts": "^3.8.1",
"rehype-external-links": "^3.0.0",
"remark-gfm": "^4.0.1",
"rolldown": "^1.0.0-rc.13",
"rollup-plugin-visualizer": "^7.0.1",
"sass": "^1.99.0",
"typescript-strict-plugin": "^2.4.4",
"usehooks-ts": "^3.1.1",
"vite": "^8.0.5",
"vite-plugin-pwa": "^1.2.0",
"vitest": "^4.1.2"
}
}