Skip to content

v1.64: split js/app.js by area into app-*.js - #62

Merged
RickUsingGitHub merged 2 commits into
mainfrom
claude/sleepy-bardeen-z0ss8o-split-app
Nov 10, 2026
Merged

RickUsingGitHub merged 2 commits into
mainfrom
claude/sleepy-bardeen-z0ss8o-split-app

Conversation

@RickUsingGitHub

Copy link
Copy Markdown
Owner

Step 2 of 2 of the structural clean-up from the v1.62 code review. No change in behaviour.

Stacked on #61 (ESLint, v1.63): this pull request's base is that branch, so the diff here is only the split. Merge #61 first, then point this one at main.

The files

js/app.js was one 3,000-line IIFE. It is now eight classic scripts, each an IIFE on window.Amber as before, with no build step:

File Lines What's in it
app-core.js 180 state, Amber.app, $, storedJson, the selected site and state, Amber's fixed charges (readAmberRates), fmtDate, messages
app-plan-form.js 620 The plan form: TOU and feed-in windows, the plan picker, createPlanObjectFromForm, applyPlanTemplate, saved settings, custom plans
app-results.js 680 displayResults, renderAllPlansTable, updatePlanSavings, renderMonthly, the Usage tab's daily graph and More Stats
app-imports.js 450 The site picker, imported households, Amber CSV import, NEM12
app-bill.js 260 Reading a bill, ensureBillLoaded, renderBillCheck
app-free.js 250 The Free? tab: renderBatteryShift, drawBatteryShift
app-settings.js 120 The settings menu
app.js 700 Tabs, the Start tab's account fields, the dates bar and Download menu, fetchAndCompare, init() (still last)

How they share state

  • app-core.js loads first and creates Amber.app = { state, $, … }.
  • Every other file starts with const app = Amber.app; const state = app.state; const $ = app.$;.
  • A function in another file is called as app.name(…), looked up when the call runs. The files call each other in both directions (results call the plan form; the plan form asks for a recalculation), so this is what lets the load order between them not matter.
  • Each file ends with Object.assign(app, { … }) listing only what another file uses: 52 names in all, out of about 130 functions. Anything not listed is private to its file.
  • Amber._appState and Amber.appApi are unchanged, so the tests and planner-ui.js needed no edits. Amber.app is internal to the app files.

How it was done, and how to review it

Two commits:

  1. Group init()'s event wiring into one setup function per area (still one file). init() added every listener itself; now setupPlanForm, setupImports, setupFreeTab, setupAccount, setupResultTools and setupSettingsMenu do, and init() calls them in order. This is the only commit with hand-moved code, and it is a small diff. The full browser suite passed on this commit on its own.
  2. The split. Done by a script that parses the file, moves each top-level function or constant whole to its file, and puts app. in front of each reference that now crosses a file (199 of them, found by scope analysis, not by text search). Nothing was retyped. I checked afterwards that every code line of the old file is in the new files and nothing else is, apart from the app. prefixes and the wrappers. git diff --color-moved shows it as moves.

One deliberate ordering change: in app.js, the Object.assign(app, …) and Amber.appApi lines now come before the DOMContentLoaded hook instead of after it, so everything is in place before init() could run.

Guards against a broken cross-file call

  • ESLint's no-undef reports a call to another file's function written without app..
  • tests/unit-syntax.js now also checks that every app.<name> used is put on Amber.app by exactly one file, that everything on it is used by another file, that no other module touches Amber.app, and that app-core.js is the first app script and app.js the last.

Checks

  • npm run lint: clean.
  • npm run test:unit: passes (388 ok lines).
  • Playwright: 66 of 66 pass, with no spec edited. The only test files touched are unit-syntax.js (the new checks) and the version assert in unit-time.js.
  • npm run build:css leaves css/app.css unchanged.
  • A plain page load, a click through all six tabs and the settings menu give no console errors.
  • Version bumped to 1.64 in index.html, js/constants.js and tests/unit-time.js. docs/ARCHITECTURE.md (load order, module map, a new section on the page controller), docs/REVIEW.md, docs/FRONTEND.md and CLAUDE.md updated.

What this doesn't do

The files still read and write one shared state object, so they are separate files more than separate modules. docs/REVIEW.md now says so and names narrowing each file's slice of state as the next step. planner-ui.js is untouched.


Generated by Claude Code

Still one file. init() in js/app.js added every listener itself; each
area now has its own setup function (setupPlanForm, setupImports,
setupFreeTab, setupAccount, setupResultTools, setupSettingsMenu, and the
Start tab's bill upload joins setupBillCheck), and init() calls them in
order. tryLoadSites and resetSitesIfKeyChanged move out of init().
The statements are the same; this makes the split that follows a move
of whole functions.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016net8VqMzbBJe1deXahjg6
The 3,000-line page controller becomes eight classic scripts, each an
IIFE on window.Amber as before, with no build step:

  app-core.js       state, Amber.app, the selected site and state,
                    Amber's fixed charges, saved JSON, messages
  app-plan-form.js  the plan form, saved settings, custom plans
  app-results.js    the answer, every plan, month by month, Usage
  app-imports.js    the site picker, Amber CSV and NEM12 imports
  app-bill.js       reading a bill and the Bill? tab
  app-free.js       the Free? tab
  app-settings.js   the settings menu
  app.js            tabs, Start, the dates bar, fetchAndCompare, init

Shared state is exposed deliberately: app-core.js creates Amber.app with
`state` and the shared helpers, each file lists what others may call in
Object.assign(app, { ... }), and calls across files are app.name(),
looked up at call time. Amber._appState and Amber.appApi are unchanged.
The code was moved by script, statement for statement; the only edits
are the app. prefixes on calls that now cross a file.

tests/unit-syntax.js also checks that every app.<name> used is put on
Amber.app by one file and used by another, and that app-core.js loads
first. Docs: module map, load order and review notes updated.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016net8VqMzbBJe1deXahjg6
@RickUsingGitHub
RickUsingGitHub marked this pull request as ready for review November 10, 2026 20:43
Base automatically changed from claude/sleepy-bardeen-z0ss8o to main November 10, 2026 20:43
@RickUsingGitHub
RickUsingGitHub merged commit 6261b69 into main Nov 10, 2026
1 check passed
@RickUsingGitHub
RickUsingGitHub deleted the claude/sleepy-bardeen-z0ss8o-split-app branch November 10, 2026 20:46
RickUsingGitHub added a commit that referenced this pull request Nov 15, 2026
…s8o-split-app

v1.64: split js/app.js by area into app-*.js
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants