2026-08-12 01:49:54 +07:00
|
|
|
/**
|
|
|
|
|
* Pro web-flash registry.
|
|
|
|
|
*
|
|
|
|
|
* Flashing a real board over Web Serial (esptool-js) is implemented in the
|
|
|
|
|
* pro overlay; the OSS app only knows the doorbell. Mirrors the other
|
|
|
|
|
* OSS->Pro seams (`proBoardGate.ts`, `proSaveAction.ts`, `proRoutes.ts`):
|
|
|
|
|
* the OSS app defines a stable interface, the overlay plugs in.
|
|
|
|
|
*
|
|
|
|
|
* - OSS without an overlay -> no impl installed. The board context menu
|
|
|
|
|
* keeps its desktop-only gate and the web build behaves exactly as
|
|
|
|
|
* before this seam existed.
|
|
|
|
|
* - With the pro overlay -> installWebFlashImpl() provides the real
|
|
|
|
|
* flasher; the "Flash to real board" menu item appears in supported
|
|
|
|
|
* browsers for supported board kinds.
|
|
|
|
|
*
|
|
|
|
|
* The seam speaks plain data only (base64 program, progress callbacks) —
|
|
|
|
|
* OSS must never see esptool-js types.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
export interface WebFlashProgress {
|
2026-08-12 03:55:47 +07:00
|
|
|
phase: 'connecting' | 'erasing' | 'writing' | 'uploading' | 'resetting';
|
|
|
|
|
/** 0-100, meaningful during 'writing' and 'uploading'. */
|
2026-08-12 01:49:54 +07:00
|
|
|
pct: number;
|
|
|
|
|
/** Optional log line to append to the modal's console. */
|
|
|
|
|
line?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface WebFlashRequest {
|
|
|
|
|
boardId: string;
|
|
|
|
|
boardKind: string;
|
|
|
|
|
/** The board's compiled program: base64 of the merged flash image. */
|
|
|
|
|
binaryBase64: string;
|
|
|
|
|
onProgress: (p: WebFlashProgress) => void;
|
|
|
|
|
/** Aborting disconnects the transport; the chip stays recoverable. */
|
|
|
|
|
signal: AbortSignal;
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-12 03:55:47 +07:00
|
|
|
/** A workspace source file, as the editor stores it. */
|
|
|
|
|
export interface WebFlashFile {
|
|
|
|
|
name: string;
|
|
|
|
|
content: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface MicroPythonFlashRequest {
|
|
|
|
|
boardId: string;
|
|
|
|
|
boardKind: string;
|
|
|
|
|
/** The project's files; .py files are written to the board's filesystem. */
|
|
|
|
|
files: WebFlashFile[];
|
|
|
|
|
onProgress: (p: WebFlashProgress) => void;
|
|
|
|
|
signal: AbortSignal;
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-12 01:49:54 +07:00
|
|
|
export interface WebFlashResult {
|
|
|
|
|
/** Chip name as detected by the loader, e.g. "ESP32-S3". */
|
|
|
|
|
chipName: string;
|
|
|
|
|
elapsedMs: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface WebFlashImpl {
|
|
|
|
|
/**
|
|
|
|
|
* Whether this board kind can be flashed over Web Serial in this
|
|
|
|
|
* browser (chip family supported AND `navigator.serial` present).
|
|
|
|
|
*/
|
|
|
|
|
available(boardKind: string): boolean;
|
|
|
|
|
/**
|
|
|
|
|
* Request a port, connect, write the image and hard-reset. Rejects
|
|
|
|
|
* with an Error whose message is user-presentable.
|
|
|
|
|
*/
|
|
|
|
|
flash(req: WebFlashRequest): Promise<WebFlashResult>;
|
2026-08-12 03:55:47 +07:00
|
|
|
/**
|
|
|
|
|
* MicroPython path: install the MicroPython firmware if the board
|
|
|
|
|
* doesn't answer as a REPL, then upload the project's .py files over
|
|
|
|
|
* raw REPL and soft-reset so main.py runs. Optional — absent means
|
|
|
|
|
* MicroPython projects can't be flashed and the UI says so.
|
|
|
|
|
*/
|
|
|
|
|
flashMicroPython?(req: MicroPythonFlashRequest): Promise<WebFlashResult>;
|
2026-08-12 01:49:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let _impl: WebFlashImpl | null = null;
|
|
|
|
|
|
|
|
|
|
/** Installed by the pro overlay (mountPro). Pass null to clear (hot reload). */
|
|
|
|
|
export function installWebFlashImpl(impl: WebFlashImpl | null): void {
|
|
|
|
|
_impl = impl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** The overlay's flasher, or null in a pure OSS build. */
|
|
|
|
|
export function getWebFlashImpl(): WebFlashImpl | null {
|
|
|
|
|
return _impl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Whether the installed flasher (if any) supports `boardKind` here.
|
|
|
|
|
* Safe to call unconditionally — false in OSS builds and on browsers
|
|
|
|
|
* without Web Serial.
|
|
|
|
|
*/
|
|
|
|
|
export function webFlashAvailable(boardKind: string): boolean {
|
|
|
|
|
if (!_impl) return false;
|
|
|
|
|
try {
|
|
|
|
|
return _impl.available(boardKind);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
|
console.warn('[oss] web-flash impl threw in available():', err);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-08-12 03:55:47 +07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Whether MicroPython projects on `boardKind` can be flashed here:
|
|
|
|
|
* the installed impl must support the board AND implement the
|
|
|
|
|
* MicroPython path.
|
|
|
|
|
*/
|
|
|
|
|
export function webFlashMpyAvailable(boardKind: string): boolean {
|
|
|
|
|
if (!_impl?.flashMicroPython) return false;
|
|
|
|
|
return webFlashAvailable(boardKind);
|
|
|
|
|
}
|