import type { Transport } from "./transport.js"; export interface FileObject { path: string; size: number; content_type?: string; etag?: string; last_modified?: string; url: string; } export interface FileListResult { files: FileObject[]; next_cursor?: string; } export interface PutOptions { /** Override the MIME type guessed from the path extension. */ contentType?: string; /** Refuse to overwrite an existing object (gateway returns 409). */ ifNoneMatch?: boolean; signal?: AbortSignal; } export interface ListOptions { prefix?: string; cursor?: string; limit?: number; /** * Shell-style pattern, post-filtered after the underlying S3 list: * * any chars except `/` * ** any chars including `/` * ? single non-slash char * [abc] character class * * Examples: * client.files.list({ glob: "*.png" }) * client.files.list({ glob: "projects/*\/assets/*.png" }) * client.files.list({ prefix: "projects/", glob: "**\/*.wav" }) * * S3 has no native glob — the gateway extracts the longest literal * head of the pattern as the underlying prefix scan, then filters * the rest in process. Patterns must match the WHOLE path; no * implicit anchoring needed. */ glob?: string; signal?: AbortSignal; } export interface PutFromURLOptions { contentType?: string; ifNoneMatch?: boolean; signal?: AbortSignal; } export type BatchOp = { op: "put_url"; path: string; src_url: string; content_type?: string; if_none_match?: boolean; } | { op: "del"; path: string; } | { op: "move"; from: string; to: string; } | { op: "copy"; from: string; to: string; } | { op: "exists"; path: string; } | { op: "stat"; path: string; }; export interface BatchResult { ok: boolean; error?: string; object?: FileObject; exists?: boolean; } export declare class FilesService { private readonly transport; /** * URL prefix for every file call. * * When the client was constructed with `project`, requests go to the * project-scoped form — `/v1/p//files/...` — instead of the * bare `/v1/files/...`. * * This matters because the unscoped URL is byte-identical across apps: * two bundles built from the same template both read * `projects/index.json`, so anything keying on URL alone (starting * with the browser's HTTP cache, which ignores request headers and is * partitioned by registrable domain, not by subdomain) cannot tell * them apart. Putting the project in the path makes the URL unique * per app. The gateway still authorizes purely from the token and * rejects a scope that disagrees with it, so this is a correctness * measure, not a permission one. */ private readonly base; constructor(transport: Transport, project?: string); /** * Upload `body` to `path`. Returns the resulting FileObject — its * `url` is the stable public address for that path. * * `body` accepts anything `fetch` accepts as a request body: Blob, * File, ArrayBuffer, ArrayBufferView, FormData (rare here), * ReadableStream, or a string. */ put(path: string, body: BodyInit, opts?: PutOptions): Promise; /** Convenience: upload string content with sensible content-type. */ putString(path: string, content: string, opts?: PutOptions): Promise; /** * Download the bytes at `path` as a Blob. Use `URL.createObjectURL` * to get a temporary local URL, or persist the bytes elsewhere. * Bundles that just need to render an asset should use the FileObject's * `.url` directly instead — that's a stable public URL with no token. */ get(path: string, init?: { signal?: AbortSignal; }): Promise; /** Stat: HEAD-only object metadata. */ stat(path: string, init?: { signal?: AbortSignal; }): Promise; /** Returns true iff the path resolves to an existing object. */ exists(path: string, init?: { signal?: AbortSignal; }): Promise; /** Delete the object at `path`. Idempotent. */ del(path: string, init?: { signal?: AbortSignal; }): Promise; /** List objects. Pass an empty / omitted prefix for the root. */ list(opts?: ListOptions): Promise; /** * Bulk delete: removes every object whose path starts with `prefix` * AND (when set) matches `glob`. Returns the count of deleted * objects. Refuses an empty prefix + empty glob — the caller must * be explicit about wiping the project namespace. * * client.files.deleteMany({ prefix: "tmp/" }) // wipe a directory * client.files.deleteMany({ glob: "**\/*.tmp" }) // wipe by pattern * client.files.deleteMany({ prefix: "logs/", glob: "*.bak" }) */ deleteMany(opts: { prefix?: string; glob?: string; }, init?: { signal?: AbortSignal; }): Promise<{ deleted: number; }>; /** Atomic rename (copy + delete server-side). */ move(from: string, to: string, init?: { signal?: AbortSignal; }): Promise; /** Server-side copy. */ copy(from: string, to: string, init?: { signal?: AbortSignal; }): Promise; /** * Ask the gateway to fetch `srcURL` and store the body at `path`. * Saves a round trip vs downloading then re-uploading. `srcURL` * must be a public http(s) URL (private/loopback hosts rejected). */ putFromURL(path: string, srcURL: string, opts?: PutFromURLOptions): Promise; /** * Pipeline several file ops in one round trip. Operations execute * sequentially server-side; one op failing does not abort the rest. * Inspect each result.ok individually. * * Auto-chunks: the gateway caps a single batch at 64 ops and returns * 400 "too many ops" above that. This method splits long input into * 30-op chunks, awaits each chunk in order, and concatenates the * results — so callers can hand it 1000 ops in a single call. * Chunks run serially (not in parallel) to preserve the * "operations execute in submission order" contract. */ batch(ops: BatchOp[], init?: { signal?: AbortSignal; }): Promise; } //# sourceMappingURL=files.d.ts.map