ponfw/preload.js
Jon Vanvik 80fd7e8d37 Add bulk OLT PON flooding-mode tool; restore README; docs
Adds a second bulk workflow alongside the firmware upgrader: changing
PON flooding mode (private<->auto) on OLT NNI services across many OLTs.

Flooding mode is encoded by the presence of the "PON FLOOD ID" key on
each OLT-CFG["NNI Networks"] entry (present = private, absent = auto).
private->auto deletes the key; auto->private sets it to 0. The rest of
the OLT-CFG is preserved (PUT-as-replace, same as ONU-CFG).

- src/mcms-api.js: listAllOltConfigs / getOltConfig / putOltConfig, plus
  pure helpers floodModeOfNni, summarizeOltNniNetworks, planFloodChange
  (planFloodChange clones and never mutates its input)
- main.js: api:listOlts + api:executeFloodChange IPC handlers
  (concurrency 3, GET->plan->PUT, streams olt-flood:progress)
- preload.js: expose both channels + onFloodProgress
- renderer: OLT inspector view (#view-olts), two-step APPLY confirm,
  auto-saved pon-olt-flood-*.csv result report
- Restore README.md (lost to a filesystem error) and document the new
  feature in README.md and CLAUDE.md (new section 14)

Verified: npm run check passes; pure helpers unit-tested for the
no-mutation, idempotency, and rollback invariants.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 12:54:06 +02:00

78 lines
2.9 KiB
JavaScript

// Preload: the only bridge between renderer and main. Everything the UI
// can do is enumerated here — the renderer has no direct node access.
const { contextBridge, ipcRenderer } = require('electron');
function call(channel, args) {
return ipcRenderer.invoke(channel, args);
}
contextBridge.exposeInMainWorld('api', {
login: (opts) => call('api:login', opts),
logout: () => call('api:logout'),
listOnuConfigs: (opts) => call('api:listOnuConfigs', opts),
listFleet: (opts) => call('api:listFleet', opts),
fetchStates: (opts) => call('api:fetchStates', opts),
getOnuConfig: (opts) => call('api:getOnuConfig', opts),
listOnuFirmware: () => call('api:listOnuFirmware'),
uploadFirmware: () => call('api:uploadFirmware'),
planUpgrade: (opts) => call('api:planUpgrade', opts),
executePerOnu: (opts) => call('api:executePerOnu', opts),
executeBulkTask: (opts) => call('api:executeBulkTask', opts),
getTaskConfig: (opts) => call('api:getTaskConfig', opts),
getUpgradeStatus: (opts) => call('api:getUpgradeStatus', opts),
deleteOnus: (opts) => call('api:deleteOnus', opts),
listOlts: (opts) => call('api:listOlts', opts),
executeFloodChange: (opts) => call('api:executeFloodChange', opts),
onFloodProgress: (handler) => {
const fn = (_ev, payload) => handler(payload);
ipcRenderer.on('olt-flood:progress', fn);
return () => ipcRenderer.removeListener('olt-flood:progress', fn);
},
fetchFecHealth: (opts) => call('api:fetchFecHealth', opts),
fetchOnuSnapshot: (opts) => call('api:fetchOnuSnapshot', opts),
savePlanCsv: (opts) => call('api:savePlanCsv', opts),
saveCsvFile: (opts) => call('api:saveCsvFile', opts),
openCsvFile: () => call('api:openCsvFile'),
// Streaming FEC pre-flight progress (one event per ONU resolved).
onFecProgress: (handler) => {
const fn = (_ev, payload) => handler(payload);
ipcRenderer.on('fec:progress', fn);
return () => ipcRenderer.removeListener('fec:progress', fn);
},
// Streaming verify-snapshot progress.
onVerifyProgress: (handler) => {
const fn = (_ev, payload) => handler(payload);
ipcRenderer.on('verify:progress', fn);
return () => ipcRenderer.removeListener('verify:progress', fn);
},
// Live progress events from the main process while executePerOnu runs.
onUpgradeProgress: (handler) => {
const fn = (_ev, payload) => handler(payload);
ipcRenderer.on('upgrade:progress', fn);
return () => ipcRenderer.removeListener('upgrade:progress', fn);
},
// Streaming state-fetch progress (Equipment ID population).
onStatesProgress: (handler) => {
const fn = (_ev, payload) => handler(payload);
ipcRenderer.on('states:progress', fn);
return () => ipcRenderer.removeListener('states:progress', fn);
},
// Streaming delete progress.
onDeleteProgress: (handler) => {
const fn = (_ev, payload) => handler(payload);
ipcRenderer.on('delete:progress', fn);
return () => ipcRenderer.removeListener('delete:progress', fn);
},
});