import { type LocalEditorLabels } from "./config.js"; import type { CommonLogger } from "./interfaces.js"; import type { ChangeNotifier, EditorPreferencesPort, FileSystemPort } from "./ports.js"; /** * The built SPA, however the platform happens to hold it. * * `serve` is handed the request rather than the Hono context this app is holding * when it calls: hono is bundled into the published package, so nothing that * installs it can resolve a type naming `Context`. Which costs nothing here, * because a request is already what the Worker's implementation wants — * Cloudflare's assets binding takes one — and the Node implementation runs * `serveStatic` in a Hono app of its own to get a real context rather than a * synthesised one. */ export interface AssetSource { /** * The `index.html` template, or `undefined` when there's no client build. * * Returned as a string because the config injection rewrites it per request. */ readDocument(): Promise; /** The built asset the request is for, or `undefined` if there isn't one. */ serve(request: Request): Promise; } /** * A request handler, in the shape every listener the editor runs behind already * wants: `serve` from `@hono/node-server` takes exactly this, and so does a * Worker's `fetch` export. * * Stated structurally instead of as the `Hono` the app really is, for the same * reason `AssetSource.serve` takes a request — hono is bundled, so it can't * appear in the published types. * * The trailing arguments are the Worker's `env` and `ExecutionContext`, which * Hono passes through to route handlers; nothing in this package reads them. * They're `any[]` rather than `unknown[]` because parameters are checked * contravariantly: the type has to accept Hono's own `fetch`, whose third * parameter is a Cloudflare `ExecutionContext` and so cannot be handed an * `unknown`. Here `any` is how you say "this type doesn't constrain these", * which is the opposite of what `unknown` says in this position. */ export type EditorFetch = (request: Request, ...rest: any[]) => Response | Promise; export interface EditorAppOptions { /** The project the editor reads and writes. */ fs: FileSystemPort; /** Where the user's external-editor choice is kept. */ preferences: EditorPreferencesPort; /** * The built SPA. Omit to run without one — Vite serves the client in * development, and this app only answers `/api` in that case. */ assets?: AssetSource; /** * Reports files changing underneath the editor, so the SPA can reload them. * Omit to leave live-reload dormant. */ changes?: ChangeNotifier; logger: CommonLogger; /** The gateway the test console relays requests to. */ deploymentUrl: string; /** * The project's location on the machine running the editor. Used only to build * external-editor deep links; all file access goes through `fs`. */ sourceDirectory: string; /** Overrides for the account/environment names the portal displays. */ labels?: LocalEditorLabels; } export interface EditorApp { /** * Hand this to whatever is listening — `@hono/node-server` on Node, the * Worker's default export on Cloudflare. */ fetch: EditorFetch; /** Releases SSE clients and stops listening for changes. */ dispose: () => Promise; } /** * Builds the editor's HTTP app from injected platform capabilities. * * This is the whole server minus the platform: no listener, no filesystem, no * file watcher, no logger implementation. `LocalEditorServer` wraps it for Node * and the preview Worker wraps it for Cloudflare, so both run these exact * routes rather than approximations of each other. */ export declare function createEditorApp(options: EditorAppOptions): EditorApp;