import type { HouseCredential } from "./house-credential.js"; import { type UploadDirSource } from "./pages-output-dir.js"; export type RunFn = (cmd: string, args: string[], env: Record, /** Working directory for the child. Task 1770 — wrangler resolves its * `.wrangler/tmp` scratch dir against a directory it infers, and on a real * install that resolves to the immutable `server/` tree, where the mkdir is * EPERM and the deploy dies before uploading. A caller that has a writable * directory of its own passes it here rather than leaving it to inference. */ opts?: { cwd?: string; }) => Promise<{ stdout: string; }>; export type FetchFn = (url: string, init: { method: string; headers: Record; body?: string | Uint8Array; }) => Promise<{ ok: boolean; status: number; text(): Promise; arrayBuffer(): Promise; }>; export interface R2Object { key: string; size: number; etag: string; lastModified: string; } export interface CfExec { d1List(): Promise<{ name: string; uuid: string; }[]>; d1Create(name: string): Promise<{ uuid: string; }>; d1Query(name: string, sql: string): Promise; /** * One statement with BOUND parameters, over the D1 HTTP API (Task 1910). * * `d1Query` above takes raw SQL and spawns wrangler per statement, so every * caller must interpolate its values. The portal pull writes client-supplied * filenames and paths, which must never be concatenated into SQL — a UUID * gate on one field is not a substitute for binding. * * This is deliberately NOT the convergence of the three D1 clients (Task * 1843); it is one bound path for the callers that need one, added where the * house credential already lives so no second credential path appears. */ d1Exec(name: string, sql: string, params?: unknown[]): Promise; r2List(): Promise<{ name: string; }[]>; r2Create(name: string): Promise; r2ObjectList(bucket: string, prefix?: string): Promise; r2ObjectFind(bucket: string, key: string): Promise; r2ObjectGet(bucket: string, key: string): Promise; r2ObjectPut(bucket: string, key: string, body: Uint8Array): Promise; r2ObjectDelete(bucket: string, key: string): Promise; pagesProjectList(): Promise<{ name: string; }[]>; pagesProjectCreate(name: string, productionBranch: string): Promise; /** `excluded` names the files dropped from the upload set, so the caller can * log what was published rather than assert it (Task 1782). `uploadDir` and * `uploadDirSource` name the asset root that was published and what decided * it, so a root published one level too high is readable from the log * without fetching the site (Task 1917). */ pagesDeploy(dir: string, project: string, branch?: string): Promise<{ url: string; excluded: string[]; uploadDir: string; uploadDirSource: UploadDirSource; }>; } export declare function makeCfExec(cred: HouseCredential, run?: RunFn, fetchFn?: FetchFn): CfExec; export declare function makeHouseCfExec(platformRoot: string, run?: RunFn, fetchFn?: FetchFn): Promise; /** * The Pages twin of makeHouseCfExec (Task 1728). Same house minter, different * scope: "pages" resolves CF_PAGES_D1_TOKEN rather than CF_STORAGE_TOKEN. * * The minter is handed the HOUSE env, which carries a master, so cf-token.sh's * house-fallback branch never runs and caller_is_house() is never consulted. * That is exactly why this works from the ui-server process regardless of its * ACCOUNT_ID, while a client session shelling cf-token.sh directly is denied * reason=not-house. Separate from makeHouseCfExec so hosting never widens the * storage token's scope, and storage never gains Pages Write. */ export declare function makeHousePagesExec(platformRoot: string, run?: RunFn, fetchFn?: FetchFn): Promise; //# sourceMappingURL=cf-exec.d.ts.map