@tinify-dev/client 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-NYRKB5BB.js → chunk-F4JYNVER.js} +123 -88
- package/dist/chunk-F4JYNVER.js.map +1 -0
- package/dist/cli.cjs +169 -134
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +168 -133
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-NYRKB5BB.js.map +0 -1
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts","../src/errors.ts","../src/inputs.ts","../src/batches.ts","../src/http.ts","../src/client.ts","../src/cli.ts"],"names":["parseArgs","pathToFileURL"],"mappings":"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","file":"cli.cjs","sourcesContent":["/** Default API origin. Override with `baseUrl` or the `TINIFY_BASE_URL` env var. */\nexport const DEFAULT_BASE_URL = \"https://api.tinify.dev\";\n\n/** Environment variable read when `apiKey` is not passed explicitly. */\nexport const ENV_API_KEY = \"TINIFY_API_KEY\";\n\n/** Environment variable read when `baseUrl` is not passed explicitly. */\nexport const ENV_BASE_URL = \"TINIFY_BASE_URL\";\n\n/** Retries performed after the initial attempt for 429/503/network failures. */\nexport const DEFAULT_MAX_RETRIES = 3;\n\n/** Per-attempt request timeout in milliseconds. */\nexport const DEFAULT_TIMEOUT_MS = 60_000;\n\n/** Initial retry backoff in milliseconds (exponential, full jitter). */\nexport const BACKOFF_BASE_MS = 500;\n\n/** Retry backoff ceiling in milliseconds. */\nexport const BACKOFF_CAP_MS = 8_000;\n\n/** Maximum accepted image size in bytes (40 MiB), matching the server limit. */\nexport const MAX_FILE_BYTES = 41_943_040;\n\n/** Maximum number of files per batch. */\nexport const MAX_BATCH_FILES = 200;\n\n/** Default concurrency for presigned batch uploads. */\nexport const DEFAULT_UPLOAD_CONCURRENCY = 4;\n\n/** Batch polling defaults: 1s start, x1.5 growth, 10s cap, 10 min budget. */\nexport const DEFAULT_POLL_INTERVAL_MS = 1_000;\nexport const DEFAULT_POLL_GROWTH = 1.5;\nexport const DEFAULT_MAX_POLL_INTERVAL_MS = 10_000;\nexport const DEFAULT_WAIT_TIMEOUT_MS = 600_000;\n\n/** Batch statuses that will never change again. */\nexport const BATCH_TERMINAL_STATUSES = [\n \"succeeded\",\n \"partially_succeeded\",\n \"failed\",\n \"canceled\",\n \"expired\",\n] as const;\n\n/** Idempotency-Key constraints enforced by the API. */\nexport const IDEMPOTENCY_KEY_MIN_LENGTH = 8;\nexport const IDEMPOTENCY_KEY_MAX_LENGTH = 160;\n","import type { TinifyErrorCode } from \"./types\";\n\n/** Base class for every error thrown by this SDK. */\nexport class TinifyError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"TinifyError\";\n }\n}\n\nexport interface TinifyApiErrorInit {\n status: number;\n code: TinifyErrorCode;\n message: string;\n requestId: string;\n details?: Record<string, unknown>;\n /** Seconds to wait before retrying, parsed from Retry-After when present. */\n retryAfter?: number;\n}\n\n/**\n * A structured error envelope returned by the API:\n * `{ error: { code, message, details }, request_id }`.\n */\nexport class TinifyApiError extends TinifyError {\n readonly status: number;\n readonly code: TinifyErrorCode;\n readonly requestId: string;\n readonly details: Record<string, unknown>;\n readonly retryAfter?: number;\n\n constructor(init: TinifyApiErrorInit) {\n super(`${init.code} (HTTP ${init.status}): ${init.message} [request_id: ${init.requestId}]`);\n this.name = \"TinifyApiError\";\n this.status = init.status;\n this.code = init.code;\n this.requestId = init.requestId;\n this.details = init.details ?? {};\n if (init.retryAfter !== undefined) this.retryAfter = init.retryAfter;\n }\n}\n\n/** The request never produced an HTTP response (DNS, TLS, socket resets...). */\nexport class TinifyNetworkError extends TinifyError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"TinifyNetworkError\";\n }\n}\n\n/** A per-attempt timeout or a `waitForBatch` budget was exceeded. */\nexport class TinifyTimeoutError extends TinifyError {\n readonly timeoutMs: number;\n\n constructor(message: string, timeoutMs: number) {\n super(message);\n this.name = \"TinifyTimeoutError\";\n this.timeoutMs = timeoutMs;\n }\n}\n","import { TinifyError } from \"./errors\";\n\n/**\n * Anything the client accepts as an image input:\n * - a file path (Node.js only),\n * - raw bytes (`Buffer`, `Uint8Array`, `ArrayBuffer`),\n * - a `Blob` / `File`.\n */\nexport type TinifyInput = string | Uint8Array | ArrayBuffer | Blob;\n\nexport interface NormalizedInput {\n blob: Blob;\n filename: string;\n}\n\nconst DEFAULT_FILENAME = \"image\";\n\n/**\n * Normalizes any {@link TinifyInput} into a `Blob` plus multipart filename.\n * File paths lazily import `node:fs` so browser bundles never pull it in;\n * passing a path outside Node.js throws a clear error instead.\n */\nexport async function normalizeInput(\n input: TinifyInput,\n filename?: string,\n): Promise<NormalizedInput> {\n if (typeof input === \"string\") {\n let fs: typeof import(\"node:fs/promises\");\n let path: typeof import(\"node:path\");\n try {\n fs = await import(\"node:fs/promises\");\n path = await import(\"node:path\");\n } catch {\n throw new TinifyError(\n \"File path inputs are only supported in Node.js. Pass a Blob or File instead.\",\n );\n }\n const bytes = await fs.readFile(input);\n return {\n blob: new Blob([bytesToView(bytes)]),\n filename: filename ?? path.basename(input),\n };\n }\n\n if (typeof Blob !== \"undefined\" && input instanceof Blob) {\n const name =\n filename ??\n (typeof File !== \"undefined\" && input instanceof File && input.name\n ? input.name\n : DEFAULT_FILENAME);\n return { blob: input, filename: name };\n }\n\n if (input instanceof ArrayBuffer) {\n return { blob: new Blob([input]), filename: filename ?? DEFAULT_FILENAME };\n }\n\n if (ArrayBuffer.isView(input)) {\n return {\n blob: new Blob([bytesToView(input)]),\n filename: filename ?? DEFAULT_FILENAME,\n };\n }\n\n throw new TypeError(\n \"Unsupported input: expected a file path, Uint8Array, ArrayBuffer, Blob, or File.\",\n );\n}\n\n/**\n * Re-views bytes over a plain ArrayBuffer so the value satisfies `BlobPart`\n * (Buffers may be backed by a pooled or shared ArrayBuffer).\n */\nfunction bytesToView(view: ArrayBufferView): Uint8Array {\n const bytes = new Uint8Array(view.buffer, view.byteOffset, view.byteLength);\n if (\n bytes.buffer instanceof ArrayBuffer &&\n bytes.byteOffset === 0 &&\n bytes.byteLength === bytes.buffer.byteLength\n ) {\n return bytes;\n }\n // Copy when the view is offset into a pooled buffer (Buffer.from) or shared.\n const copy = new Uint8Array(new ArrayBuffer(bytes.byteLength));\n copy.set(bytes);\n return copy;\n}\n","import { BATCH_TERMINAL_STATUSES, DEFAULT_UPLOAD_CONCURRENCY } from \"./constants\";\nimport { TinifyError, TinifyNetworkError } from \"./errors\";\nimport { normalizeInput, type TinifyInput } from \"./inputs\";\nimport type {\n BatchStatus,\n BatchTerminalStatus,\n BatchUpload,\n BatchUploadSession,\n FetchFunction,\n UploadBatchFilesOptions,\n} from \"./types\";\n\nconst TERMINAL: ReadonlySet<string> = new Set(BATCH_TERMINAL_STATUSES);\n\nexport function isTerminalBatchStatus(status: BatchStatus): status is BatchTerminalStatus {\n return TERMINAL.has(status);\n}\n\n/**\n * Uploads batch files to their presigned URLs.\n *\n * Each PUT sends the raw bytes with exactly the headers the API returned for\n * that slot. The Authorization header is deliberately never sent: these are\n * presigned object-storage URLs and an extra auth mechanism would be rejected.\n */\nexport async function uploadBatchFiles(\n fetchImpl: FetchFunction,\n session: BatchUploadSession,\n files: Record<string, TinifyInput>,\n options: UploadBatchFilesOptions = {},\n): Promise<void> {\n const missing = session.uploads\n .map((upload) => upload.client_id)\n .filter((clientId) => !(clientId in files));\n if (missing.length > 0) {\n throw new TinifyError(\n `Missing input for batch client_id(s): ${missing.join(\", \")}. ` +\n \"Pass a { client_id: input } record covering every file in the session.\",\n );\n }\n\n const queue = [...session.uploads];\n const concurrency = Math.max(\n 1,\n Math.min(options.concurrency ?? DEFAULT_UPLOAD_CONCURRENCY, queue.length),\n );\n\n const workers = Array.from({ length: concurrency }, async () => {\n for (;;) {\n const upload = queue.shift();\n if (upload === undefined) return;\n options.signal?.throwIfAborted();\n await putOne(fetchImpl, upload, files[upload.client_id]!, options.signal);\n }\n });\n await Promise.all(workers);\n}\n\nasync function putOne(\n fetchImpl: FetchFunction,\n upload: BatchUpload,\n input: TinifyInput,\n signal?: AbortSignal,\n): Promise<void> {\n const { blob } = await normalizeInput(input);\n let response: Response;\n try {\n response = await fetchImpl(upload.upload_url, {\n method: \"PUT\",\n headers: upload.headers,\n body: blob,\n ...(signal !== undefined ? { signal } : {}),\n });\n } catch (error) {\n throw new TinifyNetworkError(\n `Upload for client_id \"${upload.client_id}\" failed: ` +\n `${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n );\n }\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new TinifyError(\n `Upload for client_id \"${upload.client_id}\" was rejected with HTTP ${response.status}` +\n (text ? `: ${text.slice(0, 200)}` : \".\"),\n );\n }\n // Drain any remaining body.\n await response.arrayBuffer().catch(() => undefined);\n}\n","import {\n BACKOFF_BASE_MS,\n BACKOFF_CAP_MS,\n IDEMPOTENCY_KEY_MAX_LENGTH,\n IDEMPOTENCY_KEY_MIN_LENGTH,\n} from \"./constants\";\nimport { TinifyApiError, TinifyError, TinifyNetworkError, TinifyTimeoutError } from \"./errors\";\nimport type { FetchFunction, RateLimitInfo } from \"./types\";\n\nexport interface HttpClientConfig {\n apiKey: string;\n baseUrl: string;\n maxRetries: number;\n timeoutMs: number;\n fetchImpl: FetchFunction;\n}\n\nexport type RequestBody = string | FormData | Blob | Uint8Array;\n\nexport interface HttpRequestOptions {\n method: \"GET\" | \"POST\" | \"DELETE\";\n path: string;\n /** Rebuilt per attempt so multipart bodies survive retries. */\n body?: () => RequestBody;\n contentType?: string;\n /**\n * When set, the header is sent. `\"auto\"` generates a UUID once per logical\n * call and reuses it across every retry.\n */\n idempotencyKey?: string | \"auto\";\n signal?: AbortSignal;\n}\n\nexport interface HttpResult {\n response: Response;\n requestIdHeader: string | null;\n rateLimit: RateLimitInfo | null;\n}\n\nconst RETRYABLE_STATUSES = new Set([429, 503]);\n\nexport function generateIdempotencyKey(): string {\n return globalThis.crypto.randomUUID();\n}\n\nexport function validateIdempotencyKey(key: string): void {\n if (key.length < IDEMPOTENCY_KEY_MIN_LENGTH || key.length > IDEMPOTENCY_KEY_MAX_LENGTH) {\n throw new TinifyError(\n `Idempotency keys must be ${IDEMPOTENCY_KEY_MIN_LENGTH}-${IDEMPOTENCY_KEY_MAX_LENGTH} characters (got ${key.length}).`,\n );\n }\n}\n\n/** Parses Retry-After (delta-seconds or HTTP-date) into milliseconds. */\nexport function parseRetryAfterMs(header: string | null): number | undefined {\n if (header === null || header.trim() === \"\") return undefined;\n const value = header.trim();\n if (/^\\d+$/.test(value)) return Number(value) * 1000;\n const date = Date.parse(value);\n if (Number.isNaN(date)) return undefined;\n return Math.max(0, date - Date.now());\n}\n\n/** Exponential backoff with full jitter: random(0, min(cap, base * 2^attempt)). */\nexport function backoffMs(attempt: number): number {\n const ceiling = Math.min(BACKOFF_CAP_MS, BACKOFF_BASE_MS * 2 ** attempt);\n return Math.random() * ceiling;\n}\n\nexport function rateLimitFromHeaders(headers: Headers): RateLimitInfo | null {\n const limit = headers.get(\"x-ratelimit-limit\");\n const remaining = headers.get(\"x-ratelimit-remaining\");\n const reset = headers.get(\"x-ratelimit-reset\");\n if (limit === null || remaining === null || reset === null) return null;\n return { limit: Number(limit), remaining: Number(remaining), reset: Number(reset) };\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortReason(signal));\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n function onAbort(): void {\n clearTimeout(timer);\n reject(abortReason(signal!));\n }\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction abortReason(signal: AbortSignal): unknown {\n return signal.reason ?? new TinifyError(\"The operation was aborted.\");\n}\n\n/** Builds and throws a TinifyApiError from a non-2xx response. */\nexport async function throwApiError(response: Response): Promise<never> {\n const text = await response.text().catch(() => \"\");\n let body: unknown;\n try {\n body = text ? JSON.parse(text) : undefined;\n } catch {\n body = undefined;\n }\n const envelope = (body ?? {}) as {\n error?: { code?: string; message?: string; details?: Record<string, unknown> };\n request_id?: string;\n };\n const retryAfterMs = parseRetryAfterMs(response.headers.get(\"retry-after\"));\n throw new TinifyApiError({\n status: response.status,\n code: envelope.error?.code ?? \"unknown_error\",\n message: envelope.error?.message ?? `Unexpected HTTP ${response.status} response.`,\n requestId:\n envelope.request_id ?? response.headers.get(\"x-request-id\") ?? \"unavailable\",\n details: envelope.error?.details ?? {},\n ...(retryAfterMs !== undefined ? { retryAfter: retryAfterMs / 1000 } : {}),\n });\n}\n\nexport class HttpClient {\n private readonly config: HttpClientConfig;\n\n constructor(config: HttpClientConfig) {\n this.config = config;\n }\n\n get baseUrl(): string {\n return this.config.baseUrl;\n }\n\n get fetchImpl(): FetchFunction {\n return this.config.fetchImpl;\n }\n\n /**\n * Performs a request with retry semantics:\n * - retries 429/503 (honoring Retry-After) and network failures,\n * - never retries any other 4xx/5xx,\n * - reuses one Idempotency-Key across every attempt of the call.\n */\n async request(options: HttpRequestOptions): Promise<HttpResult> {\n const url = new URL(options.path, `${this.config.baseUrl}/`).toString();\n let idempotencyKey: string | undefined;\n if (options.idempotencyKey === \"auto\") {\n idempotencyKey = generateIdempotencyKey();\n } else if (options.idempotencyKey !== undefined) {\n validateIdempotencyKey(options.idempotencyKey);\n idempotencyKey = options.idempotencyKey;\n }\n\n let attempt = 0;\n // One extra loop iteration per allowed retry.\n for (;;) {\n options.signal?.throwIfAborted();\n const headers: Record<string, string> = {\n authorization: `Bearer ${this.config.apiKey}`,\n accept: \"application/json\",\n \"user-agent\": \"@tinify-dev/client/0.1.0\",\n };\n if (idempotencyKey !== undefined) headers[\"idempotency-key\"] = idempotencyKey;\n if (options.contentType !== undefined) headers[\"content-type\"] = options.contentType;\n\n let response: Response;\n try {\n response = await this.fetchWithTimeout(\n url,\n {\n method: options.method,\n headers,\n ...(options.body !== undefined ? { body: options.body() } : {}),\n },\n options.signal,\n );\n } catch (error) {\n if (error instanceof TinifyTimeoutError) throw error;\n if (options.signal?.aborted) throw error;\n if (attempt < this.config.maxRetries) {\n await sleep(backoffMs(attempt), options.signal);\n attempt += 1;\n continue;\n }\n throw new TinifyNetworkError(\n `Request to ${url} failed: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n );\n }\n\n if (RETRYABLE_STATUSES.has(response.status) && attempt < this.config.maxRetries) {\n const retryAfter = parseRetryAfterMs(response.headers.get(\"retry-after\"));\n // Drain the body so the failed attempt does not leak resources.\n await response.arrayBuffer().catch(() => undefined);\n await sleep(retryAfter ?? backoffMs(attempt), options.signal);\n attempt += 1;\n continue;\n }\n\n if (!response.ok) await throwApiError(response);\n\n return {\n response,\n requestIdHeader: response.headers.get(\"x-request-id\"),\n rateLimit: rateLimitFromHeaders(response.headers),\n };\n }\n }\n\n /** JSON-parsing wrapper around {@link request}. */\n async requestJson<T>(options: HttpRequestOptions): Promise<{\n body: T;\n requestId: string;\n rateLimit: RateLimitInfo | null;\n }> {\n const result = await this.request(options);\n let body: T;\n if (result.response.status === 204) {\n body = undefined as T;\n } else {\n body = (await result.response.json()) as T;\n }\n const bodyRequestId = (body as { request_id?: string } | undefined)?.request_id;\n return {\n body,\n requestId: bodyRequestId ?? result.requestIdHeader ?? \"unavailable\",\n rateLimit: result.rateLimit,\n };\n }\n\n private async fetchWithTimeout(\n url: string,\n init: RequestInit,\n signal?: AbortSignal,\n ): Promise<Response> {\n const controller = new AbortController();\n const timeoutError = new TinifyTimeoutError(\n `Request timed out after ${this.config.timeoutMs} ms.`,\n this.config.timeoutMs,\n );\n const timer = setTimeout(() => controller.abort(timeoutError), this.config.timeoutMs);\n const onAbort = (): void => controller.abort(abortReason(signal!));\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n try {\n return await this.config.fetchImpl(url, { ...init, signal: controller.signal });\n } catch (error) {\n // undici surfaces the abort reason directly; rethrow our sentinel as-is.\n if (error === timeoutError) throw error;\n if (controller.signal.aborted && controller.signal.reason === timeoutError) {\n throw timeoutError;\n }\n throw error;\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n}\n","import { isTerminalBatchStatus, uploadBatchFiles } from \"./batches\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_POLL_INTERVAL_MS,\n DEFAULT_MAX_RETRIES,\n DEFAULT_POLL_GROWTH,\n DEFAULT_POLL_INTERVAL_MS,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_WAIT_TIMEOUT_MS,\n ENV_API_KEY,\n ENV_BASE_URL,\n} from \"./constants\";\nimport { TinifyError, TinifyTimeoutError } from \"./errors\";\nimport { HttpClient, sleep, throwApiError } from \"./http\";\nimport { normalizeInput, type TinifyInput } from \"./inputs\";\nimport type {\n Batch,\n BatchUploadSession,\n CommitBatchResult,\n CompressOptions,\n ConvertOptions,\n CreateBatchParams,\n CropOptions,\n FetchFunction,\n ImageResultData,\n RequestOptions,\n ResizeOptions,\n TinifyClientOptions,\n TinifyResponse,\n UploadBatchFilesOptions,\n Usage,\n WaitForBatchOptions,\n} from \"./types\";\n\ninterface ImageEnvelope {\n data: ImageResultData;\n request_id?: string;\n}\n\n/**\n * Client for the Tinify.dev image API (https://tinify.dev/developers).\n *\n * Zero runtime dependencies; uses the platform `fetch`, `FormData`, and\n * `Blob`. Works in Node.js >= 20. Browser use is limited to trusted origins:\n * the API rejects untrusted browser origins, so call it server-side.\n */\nexport class TinifyClient {\n private readonly http: HttpClient;\n\n constructor(options: TinifyClientOptions = {}) {\n const env =\n typeof process !== \"undefined\" && process.env !== undefined ? process.env : {};\n const apiKey = options.apiKey ?? env[ENV_API_KEY];\n if (apiKey === undefined || apiKey === \"\") {\n throw new TinifyError(\n `Missing API key. Pass { apiKey } or set ${ENV_API_KEY}. ` +\n \"Keys are created at https://tinify.dev/developers.\",\n );\n }\n const baseUrl = (options.baseUrl ?? env[ENV_BASE_URL] ?? DEFAULT_BASE_URL).replace(\n /\\/+$/,\n \"\",\n );\n const fetchImpl: FetchFunction =\n options.fetch ?? ((input, init) => globalThis.fetch(input, init));\n this.http = new HttpClient({\n apiKey,\n baseUrl,\n maxRetries: options.maxRetries ?? DEFAULT_MAX_RETRIES,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n fetchImpl,\n });\n }\n\n // -------------------------------------------------------------------------\n // Synchronous image operations\n // -------------------------------------------------------------------------\n\n /** Compresses an image. Never returns more bytes than the input. */\n compress(\n input: TinifyInput,\n options: CompressOptions & RequestOptions = {},\n ): Promise<TinifyResponse<ImageResultData>> {\n return this.imageOperation(\n \"compress\",\n input,\n {\n quality_mode: options.quality_mode,\n target_size_bytes: options.target_size_bytes,\n },\n options,\n );\n }\n\n /** Resizes an image by width/height/scale. */\n resize(\n input: TinifyInput,\n options: ResizeOptions & RequestOptions = {},\n ): Promise<TinifyResponse<ImageResultData>> {\n return this.imageOperation(\n \"resize\",\n input,\n {\n width: options.width,\n height: options.height,\n scale: options.scale,\n keep_aspect_ratio: options.keep_aspect_ratio,\n optimize: options.optimize,\n },\n options,\n );\n }\n\n /** Crops an image to the given rectangle. */\n crop(\n input: TinifyInput,\n options: CropOptions & RequestOptions,\n ): Promise<TinifyResponse<ImageResultData>> {\n return this.imageOperation(\n \"crop\",\n input,\n {\n x: options.x,\n y: options.y,\n width: options.width,\n height: options.height,\n },\n options,\n );\n }\n\n /**\n * Converts an image to another format (AVIF, WebP, JPEG, or PNG).\n *\n * @beta The `/api/v1/images/convert` endpoint is rolling out server-side\n * and may not be available on every account yet.\n */\n convert(\n input: TinifyInput,\n options: ConvertOptions & RequestOptions,\n ): Promise<TinifyResponse<ImageResultData>> {\n return this.imageOperation(\n \"convert\",\n input,\n {\n format: options.format,\n quality_mode: options.quality_mode,\n },\n options,\n );\n }\n\n /** Returns the account's current billing-period usage. */\n async usage(options: Pick<RequestOptions, \"signal\"> = {}): Promise<TinifyResponse<Usage>> {\n const { body, requestId, rateLimit } = await this.http.requestJson<Usage>({\n method: \"GET\",\n path: \"/api/v1/usage\",\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n return { data: body, requestId, rateLimit };\n }\n\n /**\n * Downloads a result as a `Blob`. Accepts a result object, a response\n * envelope, or a download URL. Download URLs are unauthenticated and\n * expire two hours after the operation.\n */\n async download(\n resultOrUrl: string | ImageResultData | TinifyResponse<ImageResultData>,\n options: Pick<RequestOptions, \"signal\"> = {},\n ): Promise<Blob> {\n const raw =\n typeof resultOrUrl === \"string\"\n ? resultOrUrl\n : \"download_url\" in resultOrUrl\n ? resultOrUrl.download_url\n : resultOrUrl.data.download_url;\n const url = new URL(raw, `${this.http.baseUrl}/`).toString();\n // Deliberately no Authorization header: result URLs are self-contained\n // and presigned URLs reject requests carrying extra auth.\n const response = await this.http.fetchImpl(url, {\n method: \"GET\",\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n if (!response.ok) await throwApiError(response);\n return response.blob();\n }\n\n // -------------------------------------------------------------------------\n // Batches\n // -------------------------------------------------------------------------\n\n /**\n * Creates a durable batch. Returns one presigned upload slot per file;\n * upload the bytes, then {@link commitBatch}. Requires a paid plan.\n */\n async createBatch(\n params: CreateBatchParams,\n options: RequestOptions = {},\n ): Promise<TinifyResponse<BatchUploadSession>> {\n const { body, requestId, rateLimit } = await this.http.requestJson<BatchUploadSession>({\n method: \"POST\",\n path: \"/api/v1/batches\",\n contentType: \"application/json\",\n body: () => JSON.stringify(params),\n idempotencyKey: options.idempotencyKey ?? \"auto\",\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n return { data: body, requestId, rateLimit };\n }\n\n /**\n * Uploads file bytes to the presigned URLs of an upload session, keyed by\n * `client_id`. Runs up to `concurrency` (default 4) PUTs in parallel.\n */\n uploadBatchFiles(\n session: BatchUploadSession,\n files: Record<string, TinifyInput>,\n options: UploadBatchFilesOptions = {},\n ): Promise<void> {\n return uploadBatchFiles(this.http.fetchImpl, session, files, options);\n }\n\n /** Commits an uploaded batch for processing. */\n async commitBatch(\n batchId: string,\n options: RequestOptions = {},\n ): Promise<TinifyResponse<CommitBatchResult>> {\n const { body, requestId, rateLimit } = await this.http.requestJson<CommitBatchResult>({\n method: \"POST\",\n path: `/api/v1/batches/${encodeURIComponent(batchId)}/commit`,\n idempotencyKey: options.idempotencyKey ?? \"auto\",\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n return { data: body, requestId, rateLimit };\n }\n\n /** Fetches a batch with per-file state. */\n async getBatch(\n batchId: string,\n options: Pick<RequestOptions, \"signal\"> = {},\n ): Promise<TinifyResponse<Batch>> {\n const { body, requestId, rateLimit } = await this.http.requestJson<Batch>({\n method: \"GET\",\n path: `/api/v1/batches/${encodeURIComponent(batchId)}`,\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n return { data: body, requestId, rateLimit };\n }\n\n /** Cancels a batch. Idempotent: canceling a terminal batch is a no-op. */\n async cancelBatch(\n batchId: string,\n options: Pick<RequestOptions, \"signal\"> = {},\n ): Promise<void> {\n await this.http.request({\n method: \"DELETE\",\n path: `/api/v1/batches/${encodeURIComponent(batchId)}`,\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n }\n\n /**\n * Polls {@link getBatch} until the batch reaches a terminal status\n * (`succeeded`, `partially_succeeded`, `failed`, `canceled`, `expired`).\n * Polls start at 1s and grow x1.5 up to 10s; gives up after `timeoutMs`\n * (default 10 minutes) with a {@link TinifyTimeoutError}.\n */\n async waitForBatch(\n batchId: string,\n options: WaitForBatchOptions = {},\n ): Promise<TinifyResponse<Batch>> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS;\n const maxInterval = options.maxPollIntervalMs ?? DEFAULT_MAX_POLL_INTERVAL_MS;\n let interval = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const startedAt = Date.now();\n for (;;) {\n const result = await this.getBatch(batchId, options);\n if (isTerminalBatchStatus(result.data.status)) return result;\n const elapsed = Date.now() - startedAt;\n if (elapsed + interval > timeoutMs) {\n throw new TinifyTimeoutError(\n `Batch ${batchId} did not reach a terminal status within ${timeoutMs} ms ` +\n `(last status: ${result.data.status}).`,\n timeoutMs,\n );\n }\n await sleep(interval, options.signal);\n interval = Math.min(interval * DEFAULT_POLL_GROWTH, maxInterval);\n }\n }\n\n /**\n * Downloads the ZIP archive of a completed batch's successful results.\n * The batch must be in `succeeded`, `partially_succeeded`, or `failed`\n * state and contain at least one successful file.\n */\n async downloadBatchArchive(\n batchId: string,\n options: Pick<RequestOptions, \"signal\"> = {},\n ): Promise<Blob> {\n const result = await this.http.request({\n method: \"GET\",\n path: `/api/v1/batches/${encodeURIComponent(batchId)}/archive`,\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n return result.response.blob();\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private async imageOperation(\n operation: \"compress\" | \"resize\" | \"crop\" | \"convert\",\n input: TinifyInput,\n fields: Record<string, string | number | boolean | undefined>,\n options: RequestOptions,\n ): Promise<TinifyResponse<ImageResultData>> {\n const { blob, filename } = await normalizeInput(input, options.filename);\n const makeForm = (): FormData => {\n const form = new FormData();\n form.append(\"file\", blob, filename);\n for (const [key, value] of Object.entries(fields)) {\n if (value !== undefined) form.append(key, String(value));\n }\n return form;\n };\n const { body, requestId, rateLimit } = await this.http.requestJson<ImageEnvelope>({\n method: \"POST\",\n path: `/api/v1/images/${operation}`,\n body: makeForm,\n idempotencyKey: options.idempotencyKey ?? \"auto\",\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n return { data: body.data, requestId, rateLimit };\n }\n}\n","#!/usr/bin/env node\nimport { parseArgs } from \"node:util\";\nimport { pathToFileURL } from \"node:url\";\nimport { TinifyClient } from \"./client\";\nimport { MAX_FILE_BYTES } from \"./constants\";\nimport { TinifyApiError, TinifyError } from \"./errors\";\nimport type { QualityMode, TargetFormat } from \"./types\";\n\nexport const CLI_COMMANDS = [\"compress\", \"resize\", \"crop\", \"convert\", \"usage\"] as const;\nexport type CliCommand = (typeof CLI_COMMANDS)[number];\n\nconst QUALITY_MODES: ReadonlySet<string> = new Set([\"balanced\", \"best_quality\", \"lossless\"]);\nconst FORMATS: ReadonlySet<string> = new Set([\"avif\", \"webp\", \"jpeg\", \"png\"]);\n\nexport class CliUsageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CliUsageError\";\n }\n}\n\nexport interface ParsedCliArgs {\n command: CliCommand;\n files: string[];\n key?: string;\n baseUrl?: string;\n out?: string;\n quality?: QualityMode;\n targetSizeBytes?: number;\n width?: number;\n height?: number;\n scale?: number;\n x?: number;\n y?: number;\n format?: TargetFormat;\n help: boolean;\n}\n\nexport const HELP_TEXT = `tinify-dev — Tinify.dev image API CLI\n\nUsage:\n tinify-dev <command> [options] <files...>\n\nCommands:\n compress <files...> Compress images (never returns larger files)\n resize <files...> Resize images (--width/--height/--scale)\n crop <files...> Crop images (--x --y --width --height)\n convert <files...> Convert images to another format (--format) [beta]\n usage Show current plan usage\n\nOptions:\n --key <key> API key (default: TINIFY_API_KEY env var)\n --base-url <url> API origin (default: TINIFY_BASE_URL or https://api.tinify.dev)\n --out <dir> Output directory (default: <name>.min.<ext> beside input)\n --quality <mode> balanced | best_quality | lossless\n --target-size <n> Target size in bytes (compress, beta)\n --width <n> Resize/crop width\n --height <n> Resize/crop height\n --scale <n> Resize scale factor (e.g. 0.5)\n --x <n> --y <n> Crop origin\n --format <fmt> avif | webp | jpeg | png (convert)\n -h, --help Show this help\n`;\n\nexport function parseCliArgs(argv: string[]): ParsedCliArgs {\n let parsed;\n try {\n parsed = parseArgs({\n args: argv,\n allowPositionals: true,\n strict: true,\n options: {\n key: { type: \"string\" },\n \"base-url\": { type: \"string\" },\n out: { type: \"string\" },\n quality: { type: \"string\" },\n \"target-size\": { type: \"string\" },\n width: { type: \"string\" },\n height: { type: \"string\" },\n scale: { type: \"string\" },\n x: { type: \"string\" },\n y: { type: \"string\" },\n format: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\" },\n },\n });\n } catch (error) {\n throw new CliUsageError(error instanceof Error ? error.message : String(error));\n }\n\n const { values, positionals } = parsed;\n const help = values.help === true;\n const [command, ...files] = positionals;\n\n if (command === undefined) {\n if (help) return { command: \"usage\", files: [], help: true };\n throw new CliUsageError(`Missing command. Expected one of: ${CLI_COMMANDS.join(\", \")}.`);\n }\n if (!(CLI_COMMANDS as readonly string[]).includes(command)) {\n throw new CliUsageError(\n `Unknown command \"${command}\". Expected one of: ${CLI_COMMANDS.join(\", \")}.`,\n );\n }\n const cliCommand = command as CliCommand;\n\n if (cliCommand !== \"usage\" && files.length === 0 && !help) {\n throw new CliUsageError(`The \"${cliCommand}\" command needs at least one file.`);\n }\n\n const quality = values.quality;\n if (quality !== undefined && !QUALITY_MODES.has(quality)) {\n throw new CliUsageError(\n `Invalid --quality \"${quality}\". Expected balanced, best_quality, or lossless.`,\n );\n }\n\n const format = values.format;\n if (cliCommand === \"convert\" && format === undefined && !help) {\n throw new CliUsageError('The \"convert\" command requires --format (avif|webp|jpeg|png).');\n }\n if (format !== undefined && !FORMATS.has(format)) {\n throw new CliUsageError(`Invalid --format \"${format}\". Expected avif, webp, jpeg, or png.`);\n }\n\n const args: ParsedCliArgs = {\n command: cliCommand,\n files,\n help,\n ...(values.key !== undefined ? { key: values.key } : {}),\n ...(values[\"base-url\"] !== undefined ? { baseUrl: values[\"base-url\"] } : {}),\n ...(values.out !== undefined ? { out: values.out } : {}),\n ...(quality !== undefined ? { quality: quality as QualityMode } : {}),\n ...(format !== undefined ? { format: format as TargetFormat } : {}),\n ...numericFlag(\"target-size\", values[\"target-size\"], \"targetSizeBytes\"),\n ...numericFlag(\"width\", values.width, \"width\"),\n ...numericFlag(\"height\", values.height, \"height\"),\n ...numericFlag(\"scale\", values.scale, \"scale\", true),\n ...numericFlag(\"x\", values.x, \"x\"),\n ...numericFlag(\"y\", values.y, \"y\"),\n };\n\n if (cliCommand === \"crop\" && !help) {\n for (const required of [\"x\", \"y\", \"width\", \"height\"] as const) {\n if (args[required] === undefined) {\n throw new CliUsageError(`The \"crop\" command requires --${required}.`);\n }\n }\n }\n\n return args;\n}\n\nfunction numericFlag(\n flag: string,\n raw: string | undefined,\n key: string,\n allowFloat = false,\n): Record<string, number> {\n if (raw === undefined) return {};\n const value = Number(raw);\n const valid = allowFloat ? Number.isFinite(value) : Number.isInteger(value);\n if (!valid || raw.trim() === \"\") {\n throw new CliUsageError(\n `Invalid --${flag} \"${raw}\". Expected ${allowFloat ? \"a number\" : \"an integer\"}.`,\n );\n }\n return { [key]: value };\n}\n\nexport function formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes)) return String(bytes);\n if (Math.abs(bytes) < 1024) return `${bytes} B`;\n const units = [\"kB\", \"MB\", \"GB\"];\n let value = bytes;\n let unit = \"B\";\n for (const next of units) {\n if (Math.abs(value) < 1024) break;\n value /= 1024;\n unit = next;\n }\n return `${value.toFixed(1)} ${unit}`;\n}\n\ninterface ResultRow {\n file: string;\n before: number;\n after: number;\n note: string;\n}\n\nexport function renderTable(rows: ResultRow[]): string {\n const header = { file: \"file\", before: \"before\", after: \"after\", saved: \"saved\" };\n const printable = rows.map((row) => {\n const savedPct =\n row.before > 0 ? (((row.after - row.before) / row.before) * 100).toFixed(1) : \"0.0\";\n return {\n file: row.file,\n before: formatBytes(row.before),\n after: formatBytes(row.after),\n saved: row.note !== \"\" ? row.note : `${savedPct}%`,\n };\n });\n const all = [header, ...printable];\n const width = (key: keyof typeof header): number =>\n Math.max(...all.map((row) => row[key].length));\n const line = (row: (typeof all)[number]): string =>\n [\n row.file.padEnd(width(\"file\")),\n row.before.padStart(width(\"before\")),\n row.after.padStart(width(\"after\")),\n row.saved.padStart(width(\"saved\")),\n ].join(\" \");\n return all.map(line).join(\"\\n\");\n}\n\nexport async function runCli(argv: string[]): Promise<number> {\n let args: ParsedCliArgs;\n try {\n args = parseCliArgs(argv);\n } catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n\\n`);\n process.stderr.write(HELP_TEXT);\n return 1;\n }\n if (args.help) {\n process.stdout.write(HELP_TEXT);\n return 0;\n }\n\n let client: TinifyClient;\n try {\n client = new TinifyClient({\n ...(args.key !== undefined ? { apiKey: args.key } : {}),\n ...(args.baseUrl !== undefined ? { baseUrl: args.baseUrl } : {}),\n });\n } catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n return 1;\n }\n\n if (args.command === \"usage\") {\n const { data } = await client.usage();\n process.stdout.write(\n [\n `plan ${data.plan}`,\n `period ${data.period_start} → ${data.period_end}`,\n `included ${data.included}`,\n `used ${data.used}`,\n `reserved ${data.reserved}`,\n `remaining ${data.remaining}`,\n \"\",\n ].join(\"\\n\"),\n );\n return 0;\n }\n\n const { default: fs } = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n\n const rows: ResultRow[] = [];\n let failures = 0;\n\n for (const file of args.files) {\n try {\n const stat = await fs.stat(file);\n if (stat.size > MAX_FILE_BYTES) {\n process.stderr.write(\n `warn: skipping ${file} (${formatBytes(stat.size)} exceeds the 40 MB API limit)\\n`,\n );\n rows.push({ file, before: stat.size, after: stat.size, note: \"skipped\" });\n continue;\n }\n\n const result = await dispatch(client, args, file);\n const blob = await client.download(result);\n const outPath = outputPath(path, args, file, result.data.result_format);\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, new Uint8Array(await blob.arrayBuffer()));\n rows.push({\n file,\n before: result.data.original_bytes,\n after: result.data.result_bytes,\n note: result.data.optimized === false ? \"not smaller\" : \"\",\n });\n } catch (error) {\n failures += 1;\n const message =\n error instanceof TinifyApiError\n ? `${error.code}: ${error.message}`\n : error instanceof Error\n ? error.message\n : String(error);\n process.stderr.write(`error: ${file}: ${message}\\n`);\n rows.push({ file, before: 0, after: 0, note: \"failed\" });\n }\n }\n\n process.stdout.write(`${renderTable(rows)}\\n`);\n const before = rows.reduce((sum, row) => sum + row.before, 0);\n const after = rows.reduce((sum, row) => sum + row.after, 0);\n process.stdout.write(\n `total: ${formatBytes(before)} → ${formatBytes(after)} (${formatBytes(after - before)})\\n`,\n );\n return failures > 0 ? 1 : 0;\n}\n\nasync function dispatch(\n client: TinifyClient,\n args: ParsedCliArgs,\n file: string,\n): ReturnType<TinifyClient[\"compress\"]> {\n switch (args.command) {\n case \"compress\":\n return client.compress(file, {\n ...(args.quality !== undefined ? { quality_mode: args.quality } : {}),\n ...(args.targetSizeBytes !== undefined\n ? { target_size_bytes: args.targetSizeBytes }\n : {}),\n });\n case \"resize\":\n return client.resize(file, {\n ...(args.width !== undefined ? { width: args.width } : {}),\n ...(args.height !== undefined ? { height: args.height } : {}),\n ...(args.scale !== undefined ? { scale: args.scale } : {}),\n });\n case \"crop\":\n return client.crop(file, {\n x: args.x!,\n y: args.y!,\n width: args.width!,\n height: args.height!,\n });\n case \"convert\":\n return client.convert(file, {\n format: args.format!,\n ...(args.quality !== undefined ? { quality_mode: args.quality } : {}),\n });\n default:\n throw new TinifyError(`Unhandled command \"${args.command}\".`);\n }\n}\n\nfunction outputPath(\n path: typeof import(\"node:path\"),\n args: ParsedCliArgs,\n file: string,\n resultFormat: string | undefined,\n): string {\n const parsed = path.parse(file);\n const ext =\n args.command === \"convert\" && resultFormat !== undefined\n ? `.${resultFormat === \"jpeg\" ? \"jpg\" : resultFormat}`\n : parsed.ext || \"\";\n const name = `${parsed.name}.min${ext}`;\n return args.out !== undefined ? path.join(args.out, name) : path.join(parsed.dir, name);\n}\n\nconst invokedDirectly = (() => {\n try {\n if (typeof process === \"undefined\" || process.argv[1] === undefined) return false;\n return import.meta.url === pathToFileURL(process.argv[1]).href;\n } catch {\n return false;\n }\n})();\n\nif (invokedDirectly) {\n runCli(process.argv.slice(2)).then(\n (code) => {\n process.exitCode = code;\n },\n (error: unknown) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n },\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/errors.ts","../src/http.ts","../src/inputs.ts","../src/batches.ts","../src/client.ts","../src/cli.ts"],"names":["parseArgs","pathToFileURL"],"mappings":"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","file":"cli.cjs","sourcesContent":["/** Default API origin. Override with `baseUrl` or the `TINIFY_BASE_URL` env var. */\nexport const DEFAULT_BASE_URL = \"https://api.tinify.dev\";\n\n/** Environment variable read when `apiKey` is not passed explicitly. */\nexport const ENV_API_KEY = \"TINIFY_API_KEY\";\n\n/** Environment variable read when `baseUrl` is not passed explicitly. */\nexport const ENV_BASE_URL = \"TINIFY_BASE_URL\";\n\n/** Retries performed after the initial attempt for 429/503/network failures. */\nexport const DEFAULT_MAX_RETRIES = 3;\n\n/** Per-attempt request timeout in milliseconds. */\nexport const DEFAULT_TIMEOUT_MS = 60_000;\n\n/** Initial retry backoff in milliseconds (exponential, full jitter). */\nexport const BACKOFF_BASE_MS = 500;\n\n/** Retry backoff ceiling in milliseconds. */\nexport const BACKOFF_CAP_MS = 8_000;\n\n/**\n * Upper bound on an honored `Retry-After` wait. A hostile or misconfigured\n * server could send `Retry-After: 86400` (or a far-future date); without a cap\n * the client would sleep for hours per retry. Clamp it so retries stay bounded.\n */\nexport const MAX_RETRY_AFTER_MS = 30_000;\n\n/** Maximum accepted image size in bytes (40 MiB), matching the server limit. */\nexport const MAX_FILE_BYTES = 41_943_040;\n\n/** Maximum number of files per batch. */\nexport const MAX_BATCH_FILES = 200;\n\n/** Default concurrency for presigned batch uploads. */\nexport const DEFAULT_UPLOAD_CONCURRENCY = 4;\n\n/** Batch polling defaults: 1s start, x1.5 growth, 10s cap, 10 min budget. */\nexport const DEFAULT_POLL_INTERVAL_MS = 1_000;\nexport const DEFAULT_POLL_GROWTH = 1.5;\nexport const DEFAULT_MAX_POLL_INTERVAL_MS = 10_000;\nexport const DEFAULT_WAIT_TIMEOUT_MS = 600_000;\n\n/** Batch statuses that will never change again. */\nexport const BATCH_TERMINAL_STATUSES = [\n \"succeeded\",\n \"partially_succeeded\",\n \"failed\",\n \"canceled\",\n \"expired\",\n] as const;\n\n/** Idempotency-Key constraints enforced by the API. */\nexport const IDEMPOTENCY_KEY_MIN_LENGTH = 8;\nexport const IDEMPOTENCY_KEY_MAX_LENGTH = 160;\n","import type { TinifyErrorCode } from \"./types\";\n\n/** Base class for every error thrown by this SDK. */\nexport class TinifyError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"TinifyError\";\n }\n}\n\nexport interface TinifyApiErrorInit {\n status: number;\n code: TinifyErrorCode;\n message: string;\n requestId: string;\n details?: Record<string, unknown>;\n /** Seconds to wait before retrying, parsed from Retry-After when present. */\n retryAfter?: number;\n}\n\n/**\n * A structured error envelope returned by the API:\n * `{ error: { code, message, details }, request_id }`.\n */\nexport class TinifyApiError extends TinifyError {\n readonly status: number;\n readonly code: TinifyErrorCode;\n readonly requestId: string;\n readonly details: Record<string, unknown>;\n readonly retryAfter?: number;\n\n constructor(init: TinifyApiErrorInit) {\n super(`${init.code} (HTTP ${init.status}): ${init.message} [request_id: ${init.requestId}]`);\n this.name = \"TinifyApiError\";\n this.status = init.status;\n this.code = init.code;\n this.requestId = init.requestId;\n this.details = init.details ?? {};\n if (init.retryAfter !== undefined) this.retryAfter = init.retryAfter;\n }\n}\n\n/** The request never produced an HTTP response (DNS, TLS, socket resets...). */\nexport class TinifyNetworkError extends TinifyError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"TinifyNetworkError\";\n }\n}\n\n/** A per-attempt timeout or a `waitForBatch` budget was exceeded. */\nexport class TinifyTimeoutError extends TinifyError {\n readonly timeoutMs: number;\n\n constructor(message: string, timeoutMs: number) {\n super(message);\n this.name = \"TinifyTimeoutError\";\n this.timeoutMs = timeoutMs;\n }\n}\n","import {\n BACKOFF_BASE_MS,\n BACKOFF_CAP_MS,\n IDEMPOTENCY_KEY_MAX_LENGTH,\n IDEMPOTENCY_KEY_MIN_LENGTH,\n MAX_RETRY_AFTER_MS,\n} from \"./constants\";\nimport { TinifyApiError, TinifyError, TinifyNetworkError, TinifyTimeoutError } from \"./errors\";\nimport type { FetchFunction, RateLimitInfo } from \"./types\";\n\nexport interface HttpClientConfig {\n apiKey: string;\n baseUrl: string;\n maxRetries: number;\n timeoutMs: number;\n fetchImpl: FetchFunction;\n}\n\nexport type RequestBody = string | FormData | Blob | Uint8Array;\n\nexport interface HttpRequestOptions {\n method: \"GET\" | \"POST\" | \"DELETE\";\n path: string;\n /** Rebuilt per attempt so multipart bodies survive retries. */\n body?: () => RequestBody;\n contentType?: string;\n /**\n * When set, the header is sent. `\"auto\"` generates a UUID once per logical\n * call and reuses it across every retry.\n */\n idempotencyKey?: string | \"auto\";\n signal?: AbortSignal;\n}\n\nexport interface HttpResult {\n response: Response;\n requestIdHeader: string | null;\n rateLimit: RateLimitInfo | null;\n}\n\nconst RETRYABLE_STATUSES = new Set([429, 503]);\n\nexport function generateIdempotencyKey(): string {\n return globalThis.crypto.randomUUID();\n}\n\nexport function validateIdempotencyKey(key: string): void {\n if (key.length < IDEMPOTENCY_KEY_MIN_LENGTH || key.length > IDEMPOTENCY_KEY_MAX_LENGTH) {\n throw new TinifyError(\n `Idempotency keys must be ${IDEMPOTENCY_KEY_MIN_LENGTH}-${IDEMPOTENCY_KEY_MAX_LENGTH} characters (got ${key.length}).`,\n );\n }\n}\n\n/** Parses Retry-After (delta-seconds or HTTP-date) into milliseconds. */\nexport function parseRetryAfterMs(header: string | null): number | undefined {\n if (header === null || header.trim() === \"\") return undefined;\n const value = header.trim();\n if (/^\\d+$/.test(value)) return Number(value) * 1000;\n const date = Date.parse(value);\n if (Number.isNaN(date)) return undefined;\n return Math.max(0, date - Date.now());\n}\n\n/** Exponential backoff with full jitter: random(0, min(cap, base * 2^attempt)). */\nexport function backoffMs(attempt: number): number {\n const ceiling = Math.min(BACKOFF_CAP_MS, BACKOFF_BASE_MS * 2 ** attempt);\n return Math.random() * ceiling;\n}\n\nexport function rateLimitFromHeaders(headers: Headers): RateLimitInfo | null {\n const limit = headers.get(\"x-ratelimit-limit\");\n const remaining = headers.get(\"x-ratelimit-remaining\");\n const reset = headers.get(\"x-ratelimit-reset\");\n if (limit === null || remaining === null || reset === null) return null;\n return { limit: Number(limit), remaining: Number(remaining), reset: Number(reset) };\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortReason(signal));\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n function onAbort(): void {\n clearTimeout(timer);\n reject(abortReason(signal!));\n }\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction abortReason(signal: AbortSignal): unknown {\n return signal.reason ?? new TinifyError(\"The operation was aborted.\");\n}\n\n/** Builds and throws a TinifyApiError from a non-2xx response. */\nexport async function throwApiError(response: Response): Promise<never> {\n const text = await response.text().catch(() => \"\");\n let body: unknown;\n try {\n body = text ? JSON.parse(text) : undefined;\n } catch {\n body = undefined;\n }\n const envelope = (body ?? {}) as {\n error?: { code?: string; message?: string; details?: Record<string, unknown> };\n request_id?: string;\n };\n const retryAfterMs = parseRetryAfterMs(response.headers.get(\"retry-after\"));\n throw new TinifyApiError({\n status: response.status,\n code: envelope.error?.code ?? \"unknown_error\",\n message: envelope.error?.message ?? `Unexpected HTTP ${response.status} response.`,\n requestId:\n envelope.request_id ?? response.headers.get(\"x-request-id\") ?? \"unavailable\",\n details: envelope.error?.details ?? {},\n ...(retryAfterMs !== undefined ? { retryAfter: retryAfterMs / 1000 } : {}),\n });\n}\n\n/**\n * Combines the caller's abort signal with a fresh per-request timeout signal.\n * `AbortSignal.timeout` uses an unref'd timer (it never keeps the event loop\n * alive, so it won't delay a CLI exit) and its abort reason is a DOMException\n * named \"TimeoutError\" - which we map to {@link TinifyTimeoutError}. Unlike a\n * timer cleared when the response headers arrive, this signal stays armed while\n * the body streams, so slow-body reads (.json()/.blob()) are bounded too.\n */\nfunction withTimeoutSignal(\n timeoutMs: number,\n signal?: AbortSignal,\n): { signal: AbortSignal; timeout: AbortSignal } {\n const timeout = AbortSignal.timeout(timeoutMs);\n if (signal === undefined) return { signal: timeout, timeout };\n const anyOf = (AbortSignal as unknown as { any?: (s: AbortSignal[]) => AbortSignal }).any;\n if (typeof anyOf === \"function\") return { signal: anyOf([signal, timeout]), timeout };\n // Fallback for runtimes without AbortSignal.any (Node < 20.3).\n const controller = new AbortController();\n const abortFrom = (src: AbortSignal): void => controller.abort(src.reason);\n if (signal.aborted) controller.abort(signal.reason);\n else if (timeout.aborted) controller.abort(timeout.reason);\n else {\n signal.addEventListener(\"abort\", () => abortFrom(signal), { once: true });\n timeout.addEventListener(\"abort\", () => abortFrom(timeout), { once: true });\n }\n return { signal: controller.signal, timeout };\n}\n\n/**\n * Maps an `AbortSignal.timeout` abort (DOMException \"TimeoutError\") thrown while\n * reading a response body into our typed {@link TinifyTimeoutError}. A plain\n * \"AbortError\" (a caller-initiated abort) is left untouched.\n */\nexport function asTimeoutError(error: unknown, timeoutMs: number): unknown {\n if (\n typeof error === \"object\" &&\n error !== null &&\n (error as { name?: string }).name === \"TimeoutError\"\n ) {\n return new TinifyTimeoutError(`Request timed out after ${timeoutMs} ms.`, timeoutMs);\n }\n return error;\n}\n\n/**\n * `fetch` bounded by a total (connect + headers + body) timeout, plus the\n * caller's optional abort signal. The returned Response's body is still covered\n * by the timeout, so consume it promptly; a body-phase timeout surfaces as a\n * \"TimeoutError\" that callers map with {@link asTimeoutError}.\n */\nexport async function fetchWithTimeout(\n fetchImpl: FetchFunction,\n url: string,\n init: RequestInit,\n timeoutMs: number,\n userSignal?: AbortSignal,\n): Promise<Response> {\n const { signal, timeout } = withTimeoutSignal(timeoutMs, userSignal);\n try {\n return await fetchImpl(url, { ...init, signal });\n } catch (error) {\n if (timeout.aborted) {\n throw new TinifyTimeoutError(`Request timed out after ${timeoutMs} ms.`, timeoutMs);\n }\n throw error;\n }\n}\n\nexport class HttpClient {\n private readonly config: HttpClientConfig;\n\n constructor(config: HttpClientConfig) {\n this.config = config;\n }\n\n get baseUrl(): string {\n return this.config.baseUrl;\n }\n\n get fetchImpl(): FetchFunction {\n return this.config.fetchImpl;\n }\n\n /**\n * Performs a request with retry semantics:\n * - retries 429/503 (honoring Retry-After) and network failures,\n * - never retries any other 4xx/5xx,\n * - reuses one Idempotency-Key across every attempt of the call.\n */\n async request(options: HttpRequestOptions): Promise<HttpResult> {\n const url = new URL(options.path, `${this.config.baseUrl}/`).toString();\n let idempotencyKey: string | undefined;\n if (options.idempotencyKey === \"auto\") {\n idempotencyKey = generateIdempotencyKey();\n } else if (options.idempotencyKey !== undefined) {\n validateIdempotencyKey(options.idempotencyKey);\n idempotencyKey = options.idempotencyKey;\n }\n\n let attempt = 0;\n // One extra loop iteration per allowed retry.\n for (;;) {\n options.signal?.throwIfAborted();\n const headers: Record<string, string> = {\n authorization: `Bearer ${this.config.apiKey}`,\n accept: \"application/json\",\n \"user-agent\": \"@tinify-dev/client/0.1.1\",\n };\n if (idempotencyKey !== undefined) headers[\"idempotency-key\"] = idempotencyKey;\n if (options.contentType !== undefined) headers[\"content-type\"] = options.contentType;\n\n let response: Response;\n try {\n response = await fetchWithTimeout(\n this.config.fetchImpl,\n url,\n {\n method: options.method,\n headers,\n ...(options.body !== undefined ? { body: options.body() } : {}),\n },\n this.config.timeoutMs,\n options.signal,\n );\n } catch (error) {\n if (error instanceof TinifyTimeoutError) throw error;\n if (options.signal?.aborted) throw error;\n if (attempt < this.config.maxRetries) {\n await sleep(backoffMs(attempt), options.signal);\n attempt += 1;\n continue;\n }\n throw new TinifyNetworkError(\n `Request to ${url} failed: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n );\n }\n\n if (RETRYABLE_STATUSES.has(response.status) && attempt < this.config.maxRetries) {\n const retryAfter = parseRetryAfterMs(response.headers.get(\"retry-after\"));\n // Drain the body so the failed attempt does not leak resources.\n await response.arrayBuffer().catch(() => undefined);\n // Clamp Retry-After so a hostile/broken header can't stall for hours.\n const wait = Math.min(retryAfter ?? backoffMs(attempt), MAX_RETRY_AFTER_MS);\n await sleep(wait, options.signal);\n attempt += 1;\n continue;\n }\n\n if (!response.ok) await throwApiError(response);\n\n return {\n response,\n requestIdHeader: response.headers.get(\"x-request-id\"),\n rateLimit: rateLimitFromHeaders(response.headers),\n };\n }\n }\n\n /** JSON-parsing wrapper around {@link request}. */\n async requestJson<T>(options: HttpRequestOptions): Promise<{\n body: T;\n requestId: string;\n rateLimit: RateLimitInfo | null;\n }> {\n const result = await this.request(options);\n let body: T;\n try {\n if (result.response.status === 204) {\n body = undefined as T;\n } else {\n body = (await result.response.json()) as T;\n }\n } catch (error) {\n // A body-phase timeout (armed AbortSignal.timeout) surfaces as a\n // \"TimeoutError\" here; map it to our typed error.\n throw asTimeoutError(error, this.config.timeoutMs);\n }\n const bodyRequestId = (body as { request_id?: string } | undefined)?.request_id;\n return {\n body,\n requestId: bodyRequestId ?? result.requestIdHeader ?? \"unavailable\",\n rateLimit: result.rateLimit,\n };\n }\n\n /** The configured per-request timeout (ms); used by download/upload paths. */\n get timeoutMs(): number {\n return this.config.timeoutMs;\n }\n}\n","import { TinifyError } from \"./errors\";\n\n/**\n * Anything the client accepts as an image input:\n * - a file path (Node.js only),\n * - raw bytes (`Buffer`, `Uint8Array`, `ArrayBuffer`),\n * - a `Blob` / `File`.\n */\nexport type TinifyInput = string | Uint8Array | ArrayBuffer | Blob;\n\nexport interface NormalizedInput {\n blob: Blob;\n filename: string;\n}\n\nconst DEFAULT_FILENAME = \"image\";\n\n/**\n * Normalizes any {@link TinifyInput} into a `Blob` plus multipart filename.\n * File paths lazily import `node:fs` so browser bundles never pull it in;\n * passing a path outside Node.js throws a clear error instead.\n */\nexport async function normalizeInput(\n input: TinifyInput,\n filename?: string,\n): Promise<NormalizedInput> {\n if (typeof input === \"string\") {\n let fs: typeof import(\"node:fs/promises\");\n let path: typeof import(\"node:path\");\n try {\n fs = await import(\"node:fs/promises\");\n path = await import(\"node:path\");\n } catch {\n throw new TinifyError(\n \"File path inputs are only supported in Node.js. Pass a Blob or File instead.\",\n );\n }\n const bytes = await fs.readFile(input);\n return {\n blob: new Blob([bytesToView(bytes)]),\n filename: filename ?? path.basename(input),\n };\n }\n\n if (typeof Blob !== \"undefined\" && input instanceof Blob) {\n const name =\n filename ??\n (typeof File !== \"undefined\" && input instanceof File && input.name\n ? input.name\n : DEFAULT_FILENAME);\n return { blob: input, filename: name };\n }\n\n if (input instanceof ArrayBuffer) {\n return { blob: new Blob([input]), filename: filename ?? DEFAULT_FILENAME };\n }\n\n if (ArrayBuffer.isView(input)) {\n return {\n blob: new Blob([bytesToView(input)]),\n filename: filename ?? DEFAULT_FILENAME,\n };\n }\n\n throw new TypeError(\n \"Unsupported input: expected a file path, Uint8Array, ArrayBuffer, Blob, or File.\",\n );\n}\n\n/**\n * Re-views bytes over a plain ArrayBuffer so the value satisfies `BlobPart`\n * (Buffers may be backed by a pooled or shared ArrayBuffer).\n */\nfunction bytesToView(view: ArrayBufferView): Uint8Array {\n const bytes = new Uint8Array(view.buffer, view.byteOffset, view.byteLength);\n if (\n bytes.buffer instanceof ArrayBuffer &&\n bytes.byteOffset === 0 &&\n bytes.byteLength === bytes.buffer.byteLength\n ) {\n return bytes;\n }\n // Copy when the view is offset into a pooled buffer (Buffer.from) or shared.\n const copy = new Uint8Array(new ArrayBuffer(bytes.byteLength));\n copy.set(bytes);\n return copy;\n}\n","import { BATCH_TERMINAL_STATUSES, DEFAULT_UPLOAD_CONCURRENCY } from \"./constants\";\nimport { TinifyError, TinifyNetworkError, TinifyTimeoutError } from \"./errors\";\nimport { fetchWithTimeout } from \"./http\";\nimport { normalizeInput, type TinifyInput } from \"./inputs\";\nimport type {\n BatchStatus,\n BatchTerminalStatus,\n BatchUpload,\n BatchUploadSession,\n FetchFunction,\n UploadBatchFilesOptions,\n} from \"./types\";\n\nconst TERMINAL: ReadonlySet<string> = new Set(BATCH_TERMINAL_STATUSES);\n\nexport function isTerminalBatchStatus(status: BatchStatus): status is BatchTerminalStatus {\n return TERMINAL.has(status);\n}\n\n/**\n * Uploads batch files to their presigned URLs.\n *\n * Each PUT sends the raw bytes with exactly the headers the API returned for\n * that slot. The Authorization header is deliberately never sent: these are\n * presigned object-storage URLs and an extra auth mechanism would be rejected.\n */\nexport async function uploadBatchFiles(\n fetchImpl: FetchFunction,\n session: BatchUploadSession,\n files: Record<string, TinifyInput>,\n options: UploadBatchFilesOptions,\n timeoutMs: number,\n): Promise<void> {\n const missing = session.uploads\n .map((upload) => upload.client_id)\n .filter((clientId) => !(clientId in files));\n if (missing.length > 0) {\n throw new TinifyError(\n `Missing input for batch client_id(s): ${missing.join(\", \")}. ` +\n \"Pass a { client_id: input } record covering every file in the session.\",\n );\n }\n\n const queue = [...session.uploads];\n const concurrency = Math.max(\n 1,\n Math.min(options.concurrency ?? DEFAULT_UPLOAD_CONCURRENCY, queue.length),\n );\n\n const workers = Array.from({ length: concurrency }, async () => {\n for (;;) {\n const upload = queue.shift();\n if (upload === undefined) return;\n options.signal?.throwIfAborted();\n await putOne(fetchImpl, upload, files[upload.client_id]!, timeoutMs, options.signal);\n }\n });\n await Promise.all(workers);\n}\n\nasync function putOne(\n fetchImpl: FetchFunction,\n upload: BatchUpload,\n input: TinifyInput,\n timeoutMs: number,\n signal?: AbortSignal,\n): Promise<void> {\n const { blob } = await normalizeInput(input);\n let response: Response;\n try {\n // Bounded by the client timeout so a stalled presigned PUT can't hang the\n // whole batch upload (Promise.all waits on every worker).\n response = await fetchWithTimeout(\n fetchImpl,\n upload.upload_url,\n { method: \"PUT\", headers: upload.headers, body: blob },\n timeoutMs,\n signal,\n );\n } catch (error) {\n if (error instanceof TinifyTimeoutError) throw error;\n throw new TinifyNetworkError(\n `Upload for client_id \"${upload.client_id}\" failed: ` +\n `${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n );\n }\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new TinifyError(\n `Upload for client_id \"${upload.client_id}\" was rejected with HTTP ${response.status}` +\n (text ? `: ${text.slice(0, 200)}` : \".\"),\n );\n }\n // Drain any remaining body.\n await response.arrayBuffer().catch(() => undefined);\n}\n","import { isTerminalBatchStatus, uploadBatchFiles } from \"./batches\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_POLL_INTERVAL_MS,\n DEFAULT_MAX_RETRIES,\n DEFAULT_POLL_GROWTH,\n DEFAULT_POLL_INTERVAL_MS,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_WAIT_TIMEOUT_MS,\n ENV_API_KEY,\n ENV_BASE_URL,\n} from \"./constants\";\nimport { TinifyError, TinifyTimeoutError } from \"./errors\";\nimport { asTimeoutError, fetchWithTimeout, HttpClient, sleep, throwApiError } from \"./http\";\nimport { normalizeInput, type TinifyInput } from \"./inputs\";\nimport type {\n Batch,\n BatchUploadSession,\n CommitBatchResult,\n CompressOptions,\n ConvertOptions,\n CreateBatchParams,\n CropOptions,\n FetchFunction,\n ImageResultData,\n RequestOptions,\n ResizeOptions,\n TinifyClientOptions,\n TinifyResponse,\n UploadBatchFilesOptions,\n Usage,\n WaitForBatchOptions,\n} from \"./types\";\n\ninterface ImageEnvelope {\n data: ImageResultData;\n request_id?: string;\n}\n\n/**\n * Client for the Tinify.dev image API (https://tinify.dev/developers).\n *\n * Zero runtime dependencies; uses the platform `fetch`, `FormData`, and\n * `Blob`. Works in Node.js >= 20. Browser use is limited to trusted origins:\n * the API rejects untrusted browser origins, so call it server-side.\n */\nexport class TinifyClient {\n private readonly http: HttpClient;\n\n constructor(options: TinifyClientOptions = {}) {\n const env =\n typeof process !== \"undefined\" && process.env !== undefined ? process.env : {};\n const apiKey = options.apiKey ?? env[ENV_API_KEY];\n if (apiKey === undefined || apiKey === \"\") {\n throw new TinifyError(\n `Missing API key. Pass { apiKey } or set ${ENV_API_KEY}. ` +\n \"Keys are created at https://tinify.dev/developers.\",\n );\n }\n const baseUrl = (options.baseUrl ?? env[ENV_BASE_URL] ?? DEFAULT_BASE_URL).replace(\n /\\/+$/,\n \"\",\n );\n const fetchImpl: FetchFunction =\n options.fetch ?? ((input, init) => globalThis.fetch(input, init));\n this.http = new HttpClient({\n apiKey,\n baseUrl,\n maxRetries: options.maxRetries ?? DEFAULT_MAX_RETRIES,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n fetchImpl,\n });\n }\n\n // -------------------------------------------------------------------------\n // Synchronous image operations\n // -------------------------------------------------------------------------\n\n /** Compresses an image. Never returns more bytes than the input. */\n compress(\n input: TinifyInput,\n options: CompressOptions & RequestOptions = {},\n ): Promise<TinifyResponse<ImageResultData>> {\n return this.imageOperation(\n \"compress\",\n input,\n {\n quality_mode: options.quality_mode,\n target_size_bytes: options.target_size_bytes,\n },\n options,\n );\n }\n\n /** Resizes an image by width/height/scale. */\n resize(\n input: TinifyInput,\n options: ResizeOptions & RequestOptions = {},\n ): Promise<TinifyResponse<ImageResultData>> {\n return this.imageOperation(\n \"resize\",\n input,\n {\n width: options.width,\n height: options.height,\n scale: options.scale,\n keep_aspect_ratio: options.keep_aspect_ratio,\n optimize: options.optimize,\n },\n options,\n );\n }\n\n /** Crops an image to the given rectangle. */\n crop(\n input: TinifyInput,\n options: CropOptions & RequestOptions,\n ): Promise<TinifyResponse<ImageResultData>> {\n return this.imageOperation(\n \"crop\",\n input,\n {\n x: options.x,\n y: options.y,\n width: options.width,\n height: options.height,\n },\n options,\n );\n }\n\n /**\n * Converts an image to another format (AVIF, WebP, JPEG, or PNG).\n *\n * @beta The `/api/v1/images/convert` endpoint is rolling out server-side\n * and may not be available on every account yet.\n */\n convert(\n input: TinifyInput,\n options: ConvertOptions & RequestOptions,\n ): Promise<TinifyResponse<ImageResultData>> {\n return this.imageOperation(\n \"convert\",\n input,\n {\n format: options.format,\n quality_mode: options.quality_mode,\n },\n options,\n );\n }\n\n /** Returns the account's current billing-period usage. */\n async usage(options: Pick<RequestOptions, \"signal\"> = {}): Promise<TinifyResponse<Usage>> {\n const { body, requestId, rateLimit } = await this.http.requestJson<Usage>({\n method: \"GET\",\n path: \"/api/v1/usage\",\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n return { data: body, requestId, rateLimit };\n }\n\n /**\n * Downloads a result as a `Blob`. Accepts a result object, a response\n * envelope, or a download URL. Download URLs are unauthenticated and\n * expire two hours after the operation.\n */\n async download(\n resultOrUrl: string | ImageResultData | TinifyResponse<ImageResultData>,\n options: Pick<RequestOptions, \"signal\"> = {},\n ): Promise<Blob> {\n const raw =\n typeof resultOrUrl === \"string\"\n ? resultOrUrl\n : \"download_url\" in resultOrUrl\n ? resultOrUrl.download_url\n : resultOrUrl.data.download_url;\n const url = new URL(raw, `${this.http.baseUrl}/`).toString();\n // Deliberately no Authorization header: result URLs are self-contained\n // and presigned URLs reject requests carrying extra auth. Routed through\n // fetchWithTimeout so a stalled result URL can't hang forever (the bug the\n // raw fetchImpl used to have - this is the most-used post-compress call).\n const response = await fetchWithTimeout(\n this.http.fetchImpl,\n url,\n { method: \"GET\" },\n this.http.timeoutMs,\n options.signal,\n );\n if (!response.ok) await throwApiError(response);\n try {\n return await response.blob();\n } catch (error) {\n throw asTimeoutError(error, this.http.timeoutMs);\n }\n }\n\n // -------------------------------------------------------------------------\n // Batches\n // -------------------------------------------------------------------------\n\n /**\n * Creates a durable batch. Returns one presigned upload slot per file;\n * upload the bytes, then {@link commitBatch}. Requires a paid plan.\n */\n async createBatch(\n params: CreateBatchParams,\n options: RequestOptions = {},\n ): Promise<TinifyResponse<BatchUploadSession>> {\n const { body, requestId, rateLimit } = await this.http.requestJson<BatchUploadSession>({\n method: \"POST\",\n path: \"/api/v1/batches\",\n contentType: \"application/json\",\n body: () => JSON.stringify(params),\n idempotencyKey: options.idempotencyKey ?? \"auto\",\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n return { data: body, requestId, rateLimit };\n }\n\n /**\n * Uploads file bytes to the presigned URLs of an upload session, keyed by\n * `client_id`. Runs up to `concurrency` (default 4) PUTs in parallel.\n */\n uploadBatchFiles(\n session: BatchUploadSession,\n files: Record<string, TinifyInput>,\n options: UploadBatchFilesOptions = {},\n ): Promise<void> {\n return uploadBatchFiles(this.http.fetchImpl, session, files, options, this.http.timeoutMs);\n }\n\n /** Commits an uploaded batch for processing. */\n async commitBatch(\n batchId: string,\n options: RequestOptions = {},\n ): Promise<TinifyResponse<CommitBatchResult>> {\n const { body, requestId, rateLimit } = await this.http.requestJson<CommitBatchResult>({\n method: \"POST\",\n path: `/api/v1/batches/${encodeURIComponent(batchId)}/commit`,\n idempotencyKey: options.idempotencyKey ?? \"auto\",\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n return { data: body, requestId, rateLimit };\n }\n\n /** Fetches a batch with per-file state. */\n async getBatch(\n batchId: string,\n options: Pick<RequestOptions, \"signal\"> = {},\n ): Promise<TinifyResponse<Batch>> {\n const { body, requestId, rateLimit } = await this.http.requestJson<Batch>({\n method: \"GET\",\n path: `/api/v1/batches/${encodeURIComponent(batchId)}`,\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n return { data: body, requestId, rateLimit };\n }\n\n /** Cancels a batch. Idempotent: canceling a terminal batch is a no-op. */\n async cancelBatch(\n batchId: string,\n options: Pick<RequestOptions, \"signal\"> = {},\n ): Promise<void> {\n await this.http.request({\n method: \"DELETE\",\n path: `/api/v1/batches/${encodeURIComponent(batchId)}`,\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n }\n\n /**\n * Polls {@link getBatch} until the batch reaches a terminal status\n * (`succeeded`, `partially_succeeded`, `failed`, `canceled`, `expired`).\n * Polls start at 1s and grow x1.5 up to 10s; gives up after `timeoutMs`\n * (default 10 minutes) with a {@link TinifyTimeoutError}.\n */\n async waitForBatch(\n batchId: string,\n options: WaitForBatchOptions = {},\n ): Promise<TinifyResponse<Batch>> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS;\n const maxInterval = options.maxPollIntervalMs ?? DEFAULT_MAX_POLL_INTERVAL_MS;\n let interval = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const startedAt = Date.now();\n for (;;) {\n const result = await this.getBatch(batchId, options);\n if (isTerminalBatchStatus(result.data.status)) return result;\n const elapsed = Date.now() - startedAt;\n if (elapsed + interval > timeoutMs) {\n throw new TinifyTimeoutError(\n `Batch ${batchId} did not reach a terminal status within ${timeoutMs} ms ` +\n `(last status: ${result.data.status}).`,\n timeoutMs,\n );\n }\n await sleep(interval, options.signal);\n interval = Math.min(interval * DEFAULT_POLL_GROWTH, maxInterval);\n }\n }\n\n /**\n * Downloads the ZIP archive of a completed batch's successful results.\n * The batch must be in `succeeded`, `partially_succeeded`, or `failed`\n * state and contain at least one successful file.\n */\n async downloadBatchArchive(\n batchId: string,\n options: Pick<RequestOptions, \"signal\"> = {},\n ): Promise<Blob> {\n const result = await this.http.request({\n method: \"GET\",\n path: `/api/v1/batches/${encodeURIComponent(batchId)}/archive`,\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n try {\n return await result.response.blob();\n } catch (error) {\n throw asTimeoutError(error, this.http.timeoutMs);\n }\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private async imageOperation(\n operation: \"compress\" | \"resize\" | \"crop\" | \"convert\",\n input: TinifyInput,\n fields: Record<string, string | number | boolean | undefined>,\n options: RequestOptions,\n ): Promise<TinifyResponse<ImageResultData>> {\n const { blob, filename } = await normalizeInput(input, options.filename);\n const makeForm = (): FormData => {\n const form = new FormData();\n form.append(\"file\", blob, filename);\n for (const [key, value] of Object.entries(fields)) {\n if (value !== undefined) form.append(key, String(value));\n }\n return form;\n };\n const { body, requestId, rateLimit } = await this.http.requestJson<ImageEnvelope>({\n method: \"POST\",\n path: `/api/v1/images/${operation}`,\n body: makeForm,\n idempotencyKey: options.idempotencyKey ?? \"auto\",\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n });\n return { data: body.data, requestId, rateLimit };\n }\n}\n","#!/usr/bin/env node\nimport { parseArgs } from \"node:util\";\nimport { pathToFileURL } from \"node:url\";\nimport { TinifyClient } from \"./client\";\nimport { MAX_FILE_BYTES } from \"./constants\";\nimport { TinifyApiError, TinifyError } from \"./errors\";\nimport type { QualityMode, TargetFormat } from \"./types\";\n\nexport const CLI_COMMANDS = [\"compress\", \"resize\", \"crop\", \"convert\", \"usage\"] as const;\nexport type CliCommand = (typeof CLI_COMMANDS)[number];\n\nconst QUALITY_MODES: ReadonlySet<string> = new Set([\"balanced\", \"best_quality\", \"lossless\"]);\nconst FORMATS: ReadonlySet<string> = new Set([\"avif\", \"webp\", \"jpeg\", \"png\"]);\n\nexport class CliUsageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CliUsageError\";\n }\n}\n\nexport interface ParsedCliArgs {\n command: CliCommand;\n files: string[];\n key?: string;\n baseUrl?: string;\n out?: string;\n quality?: QualityMode;\n targetSizeBytes?: number;\n width?: number;\n height?: number;\n scale?: number;\n x?: number;\n y?: number;\n format?: TargetFormat;\n help: boolean;\n}\n\nexport const HELP_TEXT = `tinify-dev - Tinify.dev image API CLI\n\nUsage:\n tinify-dev <command> [options] <files...>\n\nCommands:\n compress <files...> Compress images (never returns larger files)\n resize <files...> Resize images (--width/--height/--scale)\n crop <files...> Crop images (--x --y --width --height)\n convert <files...> Convert images to another format (--format) [beta]\n usage Show current plan usage\n\nOptions:\n --key <key> API key (default: TINIFY_API_KEY env var)\n --base-url <url> API origin (default: TINIFY_BASE_URL or https://api.tinify.dev)\n --out <dir> Output directory (default: <name>.min.<ext> beside input)\n --quality <mode> balanced | best_quality | lossless\n --target-size <n> Target size in bytes (compress, beta)\n --width <n> Resize/crop width\n --height <n> Resize/crop height\n --scale <n> Resize scale factor (e.g. 0.5)\n --x <n> --y <n> Crop origin\n --format <fmt> avif | webp | jpeg | png (convert)\n -h, --help Show this help\n`;\n\nexport function parseCliArgs(argv: string[]): ParsedCliArgs {\n let parsed;\n try {\n parsed = parseArgs({\n args: argv,\n allowPositionals: true,\n strict: true,\n options: {\n key: { type: \"string\" },\n \"base-url\": { type: \"string\" },\n out: { type: \"string\" },\n quality: { type: \"string\" },\n \"target-size\": { type: \"string\" },\n width: { type: \"string\" },\n height: { type: \"string\" },\n scale: { type: \"string\" },\n x: { type: \"string\" },\n y: { type: \"string\" },\n format: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\" },\n },\n });\n } catch (error) {\n throw new CliUsageError(error instanceof Error ? error.message : String(error));\n }\n\n const { values, positionals } = parsed;\n const help = values.help === true;\n const [command, ...files] = positionals;\n\n if (command === undefined) {\n if (help) return { command: \"usage\", files: [], help: true };\n throw new CliUsageError(`Missing command. Expected one of: ${CLI_COMMANDS.join(\", \")}.`);\n }\n if (!(CLI_COMMANDS as readonly string[]).includes(command)) {\n throw new CliUsageError(\n `Unknown command \"${command}\". Expected one of: ${CLI_COMMANDS.join(\", \")}.`,\n );\n }\n const cliCommand = command as CliCommand;\n\n if (cliCommand !== \"usage\" && files.length === 0 && !help) {\n throw new CliUsageError(`The \"${cliCommand}\" command needs at least one file.`);\n }\n\n const quality = values.quality;\n if (quality !== undefined && !QUALITY_MODES.has(quality)) {\n throw new CliUsageError(\n `Invalid --quality \"${quality}\". Expected balanced, best_quality, or lossless.`,\n );\n }\n\n const format = values.format;\n if (cliCommand === \"convert\" && format === undefined && !help) {\n throw new CliUsageError('The \"convert\" command requires --format (avif|webp|jpeg|png).');\n }\n if (format !== undefined && !FORMATS.has(format)) {\n throw new CliUsageError(`Invalid --format \"${format}\". Expected avif, webp, jpeg, or png.`);\n }\n\n const args: ParsedCliArgs = {\n command: cliCommand,\n files,\n help,\n ...(values.key !== undefined ? { key: values.key } : {}),\n ...(values[\"base-url\"] !== undefined ? { baseUrl: values[\"base-url\"] } : {}),\n ...(values.out !== undefined ? { out: values.out } : {}),\n ...(quality !== undefined ? { quality: quality as QualityMode } : {}),\n ...(format !== undefined ? { format: format as TargetFormat } : {}),\n ...numericFlag(\"target-size\", values[\"target-size\"], \"targetSizeBytes\"),\n ...numericFlag(\"width\", values.width, \"width\"),\n ...numericFlag(\"height\", values.height, \"height\"),\n ...numericFlag(\"scale\", values.scale, \"scale\", true),\n ...numericFlag(\"x\", values.x, \"x\"),\n ...numericFlag(\"y\", values.y, \"y\"),\n };\n\n if (cliCommand === \"crop\" && !help) {\n for (const required of [\"x\", \"y\", \"width\", \"height\"] as const) {\n if (args[required] === undefined) {\n throw new CliUsageError(`The \"crop\" command requires --${required}.`);\n }\n }\n }\n\n return args;\n}\n\nfunction numericFlag(\n flag: string,\n raw: string | undefined,\n key: string,\n allowFloat = false,\n): Record<string, number> {\n if (raw === undefined) return {};\n const value = Number(raw);\n const valid = allowFloat ? Number.isFinite(value) : Number.isInteger(value);\n if (!valid || raw.trim() === \"\") {\n throw new CliUsageError(\n `Invalid --${flag} \"${raw}\". Expected ${allowFloat ? \"a number\" : \"an integer\"}.`,\n );\n }\n return { [key]: value };\n}\n\nexport function formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes)) return String(bytes);\n if (Math.abs(bytes) < 1024) return `${bytes} B`;\n const units = [\"kB\", \"MB\", \"GB\"];\n let value = bytes;\n let unit = \"B\";\n for (const next of units) {\n if (Math.abs(value) < 1024) break;\n value /= 1024;\n unit = next;\n }\n return `${value.toFixed(1)} ${unit}`;\n}\n\ninterface ResultRow {\n file: string;\n before: number;\n after: number;\n note: string;\n}\n\nexport function renderTable(rows: ResultRow[]): string {\n const header = { file: \"file\", before: \"before\", after: \"after\", saved: \"saved\" };\n const printable = rows.map((row) => {\n const savedPct =\n row.before > 0 ? (((row.after - row.before) / row.before) * 100).toFixed(1) : \"0.0\";\n return {\n file: row.file,\n before: formatBytes(row.before),\n after: formatBytes(row.after),\n saved: row.note !== \"\" ? row.note : `${savedPct}%`,\n };\n });\n const all = [header, ...printable];\n const width = (key: keyof typeof header): number =>\n Math.max(...all.map((row) => row[key].length));\n const line = (row: (typeof all)[number]): string =>\n [\n row.file.padEnd(width(\"file\")),\n row.before.padStart(width(\"before\")),\n row.after.padStart(width(\"after\")),\n row.saved.padStart(width(\"saved\")),\n ].join(\" \");\n return all.map(line).join(\"\\n\");\n}\n\nexport async function runCli(argv: string[]): Promise<number> {\n let args: ParsedCliArgs;\n try {\n args = parseCliArgs(argv);\n } catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n\\n`);\n process.stderr.write(HELP_TEXT);\n return 1;\n }\n if (args.help) {\n process.stdout.write(HELP_TEXT);\n return 0;\n }\n\n let client: TinifyClient;\n try {\n client = new TinifyClient({\n ...(args.key !== undefined ? { apiKey: args.key } : {}),\n ...(args.baseUrl !== undefined ? { baseUrl: args.baseUrl } : {}),\n });\n } catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n return 1;\n }\n\n if (args.command === \"usage\") {\n const { data } = await client.usage();\n process.stdout.write(\n [\n `plan ${data.plan}`,\n `period ${data.period_start} → ${data.period_end}`,\n `included ${data.included}`,\n `used ${data.used}`,\n `reserved ${data.reserved}`,\n `remaining ${data.remaining}`,\n \"\",\n ].join(\"\\n\"),\n );\n return 0;\n }\n\n const { default: fs } = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n\n const rows: ResultRow[] = [];\n let failures = 0;\n\n for (const file of args.files) {\n try {\n const stat = await fs.stat(file);\n if (stat.size > MAX_FILE_BYTES) {\n process.stderr.write(\n `warn: skipping ${file} (${formatBytes(stat.size)} exceeds the 40 MB API limit)\\n`,\n );\n rows.push({ file, before: stat.size, after: stat.size, note: \"skipped\" });\n continue;\n }\n\n const result = await dispatch(client, args, file);\n const blob = await client.download(result);\n const outPath = outputPath(path, args, file, result.data.result_format);\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, new Uint8Array(await blob.arrayBuffer()));\n rows.push({\n file,\n before: result.data.original_bytes,\n after: result.data.result_bytes,\n note: result.data.optimized === false ? \"not smaller\" : \"\",\n });\n } catch (error) {\n failures += 1;\n const message =\n error instanceof TinifyApiError\n ? `${error.code}: ${error.message}`\n : error instanceof Error\n ? error.message\n : String(error);\n process.stderr.write(`error: ${file}: ${message}\\n`);\n rows.push({ file, before: 0, after: 0, note: \"failed\" });\n }\n }\n\n process.stdout.write(`${renderTable(rows)}\\n`);\n const before = rows.reduce((sum, row) => sum + row.before, 0);\n const after = rows.reduce((sum, row) => sum + row.after, 0);\n process.stdout.write(\n `total: ${formatBytes(before)} → ${formatBytes(after)} (${formatBytes(after - before)})\\n`,\n );\n return failures > 0 ? 1 : 0;\n}\n\nasync function dispatch(\n client: TinifyClient,\n args: ParsedCliArgs,\n file: string,\n): ReturnType<TinifyClient[\"compress\"]> {\n switch (args.command) {\n case \"compress\":\n return client.compress(file, {\n ...(args.quality !== undefined ? { quality_mode: args.quality } : {}),\n ...(args.targetSizeBytes !== undefined\n ? { target_size_bytes: args.targetSizeBytes }\n : {}),\n });\n case \"resize\":\n return client.resize(file, {\n ...(args.width !== undefined ? { width: args.width } : {}),\n ...(args.height !== undefined ? { height: args.height } : {}),\n ...(args.scale !== undefined ? { scale: args.scale } : {}),\n });\n case \"crop\":\n return client.crop(file, {\n x: args.x!,\n y: args.y!,\n width: args.width!,\n height: args.height!,\n });\n case \"convert\":\n return client.convert(file, {\n format: args.format!,\n ...(args.quality !== undefined ? { quality_mode: args.quality } : {}),\n });\n default:\n throw new TinifyError(`Unhandled command \"${args.command}\".`);\n }\n}\n\nfunction outputPath(\n path: typeof import(\"node:path\"),\n args: ParsedCliArgs,\n file: string,\n resultFormat: string | undefined,\n): string {\n const parsed = path.parse(file);\n const ext =\n args.command === \"convert\" && resultFormat !== undefined\n ? `.${resultFormat === \"jpeg\" ? \"jpg\" : resultFormat}`\n : parsed.ext || \"\";\n const name = `${parsed.name}.min${ext}`;\n return args.out !== undefined ? path.join(args.out, name) : path.join(parsed.dir, name);\n}\n\nconst invokedDirectly = (() => {\n try {\n if (typeof process === \"undefined\" || process.argv[1] === undefined) return false;\n return import.meta.url === pathToFileURL(process.argv[1]).href;\n } catch {\n return false;\n }\n})();\n\nif (invokedDirectly) {\n runCli(process.argv.slice(2)).then(\n (code) => {\n process.exitCode = code;\n },\n (error: unknown) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n },\n );\n}\n"]}
|
package/dist/cli.d.cts
CHANGED
|
@@ -22,7 +22,7 @@ interface ParsedCliArgs {
|
|
|
22
22
|
format?: TargetFormat;
|
|
23
23
|
help: boolean;
|
|
24
24
|
}
|
|
25
|
-
declare const HELP_TEXT = "tinify-dev
|
|
25
|
+
declare const HELP_TEXT = "tinify-dev - Tinify.dev image API CLI\n\nUsage:\n tinify-dev <command> [options] <files...>\n\nCommands:\n compress <files...> Compress images (never returns larger files)\n resize <files...> Resize images (--width/--height/--scale)\n crop <files...> Crop images (--x --y --width --height)\n convert <files...> Convert images to another format (--format) [beta]\n usage Show current plan usage\n\nOptions:\n --key <key> API key (default: TINIFY_API_KEY env var)\n --base-url <url> API origin (default: TINIFY_BASE_URL or https://api.tinify.dev)\n --out <dir> Output directory (default: <name>.min.<ext> beside input)\n --quality <mode> balanced | best_quality | lossless\n --target-size <n> Target size in bytes (compress, beta)\n --width <n> Resize/crop width\n --height <n> Resize/crop height\n --scale <n> Resize scale factor (e.g. 0.5)\n --x <n> --y <n> Crop origin\n --format <fmt> avif | webp | jpeg | png (convert)\n -h, --help Show this help\n";
|
|
26
26
|
declare function parseCliArgs(argv: string[]): ParsedCliArgs;
|
|
27
27
|
declare function formatBytes(bytes: number): string;
|
|
28
28
|
interface ResultRow {
|
package/dist/cli.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ interface ParsedCliArgs {
|
|
|
22
22
|
format?: TargetFormat;
|
|
23
23
|
help: boolean;
|
|
24
24
|
}
|
|
25
|
-
declare const HELP_TEXT = "tinify-dev
|
|
25
|
+
declare const HELP_TEXT = "tinify-dev - Tinify.dev image API CLI\n\nUsage:\n tinify-dev <command> [options] <files...>\n\nCommands:\n compress <files...> Compress images (never returns larger files)\n resize <files...> Resize images (--width/--height/--scale)\n crop <files...> Crop images (--x --y --width --height)\n convert <files...> Convert images to another format (--format) [beta]\n usage Show current plan usage\n\nOptions:\n --key <key> API key (default: TINIFY_API_KEY env var)\n --base-url <url> API origin (default: TINIFY_BASE_URL or https://api.tinify.dev)\n --out <dir> Output directory (default: <name>.min.<ext> beside input)\n --quality <mode> balanced | best_quality | lossless\n --target-size <n> Target size in bytes (compress, beta)\n --width <n> Resize/crop width\n --height <n> Resize/crop height\n --scale <n> Resize scale factor (e.g. 0.5)\n --x <n> --y <n> Crop origin\n --format <fmt> avif | webp | jpeg | png (convert)\n -h, --help Show this help\n";
|
|
26
26
|
declare function parseCliArgs(argv: string[]): ParsedCliArgs;
|
|
27
27
|
declare function formatBytes(bytes: number): string;
|
|
28
28
|
interface ResultRow {
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { TinifyClient, MAX_FILE_BYTES, TinifyApiError, TinifyError } from './chunk-
|
|
2
|
+
import { TinifyClient, MAX_FILE_BYTES, TinifyApiError, TinifyError } from './chunk-F4JYNVER.js';
|
|
3
3
|
import { parseArgs } from 'util';
|
|
4
4
|
import { pathToFileURL } from 'url';
|
|
5
5
|
|
|
@@ -12,7 +12,7 @@ var CliUsageError = class extends Error {
|
|
|
12
12
|
this.name = "CliUsageError";
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
|
-
var HELP_TEXT = `tinify-dev
|
|
15
|
+
var HELP_TEXT = `tinify-dev - Tinify.dev image API CLI
|
|
16
16
|
|
|
17
17
|
Usage:
|
|
18
18
|
tinify-dev <command> [options] <files...>
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"names":[],"mappings":"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","file":"cli.js","sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from \"node:util\";\nimport { pathToFileURL } from \"node:url\";\nimport { TinifyClient } from \"./client\";\nimport { MAX_FILE_BYTES } from \"./constants\";\nimport { TinifyApiError, TinifyError } from \"./errors\";\nimport type { QualityMode, TargetFormat } from \"./types\";\n\nexport const CLI_COMMANDS = [\"compress\", \"resize\", \"crop\", \"convert\", \"usage\"] as const;\nexport type CliCommand = (typeof CLI_COMMANDS)[number];\n\nconst QUALITY_MODES: ReadonlySet<string> = new Set([\"balanced\", \"best_quality\", \"lossless\"]);\nconst FORMATS: ReadonlySet<string> = new Set([\"avif\", \"webp\", \"jpeg\", \"png\"]);\n\nexport class CliUsageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CliUsageError\";\n }\n}\n\nexport interface ParsedCliArgs {\n command: CliCommand;\n files: string[];\n key?: string;\n baseUrl?: string;\n out?: string;\n quality?: QualityMode;\n targetSizeBytes?: number;\n width?: number;\n height?: number;\n scale?: number;\n x?: number;\n y?: number;\n format?: TargetFormat;\n help: boolean;\n}\n\nexport const HELP_TEXT = `tinify-dev — Tinify.dev image API CLI\n\nUsage:\n tinify-dev <command> [options] <files...>\n\nCommands:\n compress <files...> Compress images (never returns larger files)\n resize <files...> Resize images (--width/--height/--scale)\n crop <files...> Crop images (--x --y --width --height)\n convert <files...> Convert images to another format (--format) [beta]\n usage Show current plan usage\n\nOptions:\n --key <key> API key (default: TINIFY_API_KEY env var)\n --base-url <url> API origin (default: TINIFY_BASE_URL or https://api.tinify.dev)\n --out <dir> Output directory (default: <name>.min.<ext> beside input)\n --quality <mode> balanced | best_quality | lossless\n --target-size <n> Target size in bytes (compress, beta)\n --width <n> Resize/crop width\n --height <n> Resize/crop height\n --scale <n> Resize scale factor (e.g. 0.5)\n --x <n> --y <n> Crop origin\n --format <fmt> avif | webp | jpeg | png (convert)\n -h, --help Show this help\n`;\n\nexport function parseCliArgs(argv: string[]): ParsedCliArgs {\n let parsed;\n try {\n parsed = parseArgs({\n args: argv,\n allowPositionals: true,\n strict: true,\n options: {\n key: { type: \"string\" },\n \"base-url\": { type: \"string\" },\n out: { type: \"string\" },\n quality: { type: \"string\" },\n \"target-size\": { type: \"string\" },\n width: { type: \"string\" },\n height: { type: \"string\" },\n scale: { type: \"string\" },\n x: { type: \"string\" },\n y: { type: \"string\" },\n format: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\" },\n },\n });\n } catch (error) {\n throw new CliUsageError(error instanceof Error ? error.message : String(error));\n }\n\n const { values, positionals } = parsed;\n const help = values.help === true;\n const [command, ...files] = positionals;\n\n if (command === undefined) {\n if (help) return { command: \"usage\", files: [], help: true };\n throw new CliUsageError(`Missing command. Expected one of: ${CLI_COMMANDS.join(\", \")}.`);\n }\n if (!(CLI_COMMANDS as readonly string[]).includes(command)) {\n throw new CliUsageError(\n `Unknown command \"${command}\". Expected one of: ${CLI_COMMANDS.join(\", \")}.`,\n );\n }\n const cliCommand = command as CliCommand;\n\n if (cliCommand !== \"usage\" && files.length === 0 && !help) {\n throw new CliUsageError(`The \"${cliCommand}\" command needs at least one file.`);\n }\n\n const quality = values.quality;\n if (quality !== undefined && !QUALITY_MODES.has(quality)) {\n throw new CliUsageError(\n `Invalid --quality \"${quality}\". Expected balanced, best_quality, or lossless.`,\n );\n }\n\n const format = values.format;\n if (cliCommand === \"convert\" && format === undefined && !help) {\n throw new CliUsageError('The \"convert\" command requires --format (avif|webp|jpeg|png).');\n }\n if (format !== undefined && !FORMATS.has(format)) {\n throw new CliUsageError(`Invalid --format \"${format}\". Expected avif, webp, jpeg, or png.`);\n }\n\n const args: ParsedCliArgs = {\n command: cliCommand,\n files,\n help,\n ...(values.key !== undefined ? { key: values.key } : {}),\n ...(values[\"base-url\"] !== undefined ? { baseUrl: values[\"base-url\"] } : {}),\n ...(values.out !== undefined ? { out: values.out } : {}),\n ...(quality !== undefined ? { quality: quality as QualityMode } : {}),\n ...(format !== undefined ? { format: format as TargetFormat } : {}),\n ...numericFlag(\"target-size\", values[\"target-size\"], \"targetSizeBytes\"),\n ...numericFlag(\"width\", values.width, \"width\"),\n ...numericFlag(\"height\", values.height, \"height\"),\n ...numericFlag(\"scale\", values.scale, \"scale\", true),\n ...numericFlag(\"x\", values.x, \"x\"),\n ...numericFlag(\"y\", values.y, \"y\"),\n };\n\n if (cliCommand === \"crop\" && !help) {\n for (const required of [\"x\", \"y\", \"width\", \"height\"] as const) {\n if (args[required] === undefined) {\n throw new CliUsageError(`The \"crop\" command requires --${required}.`);\n }\n }\n }\n\n return args;\n}\n\nfunction numericFlag(\n flag: string,\n raw: string | undefined,\n key: string,\n allowFloat = false,\n): Record<string, number> {\n if (raw === undefined) return {};\n const value = Number(raw);\n const valid = allowFloat ? Number.isFinite(value) : Number.isInteger(value);\n if (!valid || raw.trim() === \"\") {\n throw new CliUsageError(\n `Invalid --${flag} \"${raw}\". Expected ${allowFloat ? \"a number\" : \"an integer\"}.`,\n );\n }\n return { [key]: value };\n}\n\nexport function formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes)) return String(bytes);\n if (Math.abs(bytes) < 1024) return `${bytes} B`;\n const units = [\"kB\", \"MB\", \"GB\"];\n let value = bytes;\n let unit = \"B\";\n for (const next of units) {\n if (Math.abs(value) < 1024) break;\n value /= 1024;\n unit = next;\n }\n return `${value.toFixed(1)} ${unit}`;\n}\n\ninterface ResultRow {\n file: string;\n before: number;\n after: number;\n note: string;\n}\n\nexport function renderTable(rows: ResultRow[]): string {\n const header = { file: \"file\", before: \"before\", after: \"after\", saved: \"saved\" };\n const printable = rows.map((row) => {\n const savedPct =\n row.before > 0 ? (((row.after - row.before) / row.before) * 100).toFixed(1) : \"0.0\";\n return {\n file: row.file,\n before: formatBytes(row.before),\n after: formatBytes(row.after),\n saved: row.note !== \"\" ? row.note : `${savedPct}%`,\n };\n });\n const all = [header, ...printable];\n const width = (key: keyof typeof header): number =>\n Math.max(...all.map((row) => row[key].length));\n const line = (row: (typeof all)[number]): string =>\n [\n row.file.padEnd(width(\"file\")),\n row.before.padStart(width(\"before\")),\n row.after.padStart(width(\"after\")),\n row.saved.padStart(width(\"saved\")),\n ].join(\" \");\n return all.map(line).join(\"\\n\");\n}\n\nexport async function runCli(argv: string[]): Promise<number> {\n let args: ParsedCliArgs;\n try {\n args = parseCliArgs(argv);\n } catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n\\n`);\n process.stderr.write(HELP_TEXT);\n return 1;\n }\n if (args.help) {\n process.stdout.write(HELP_TEXT);\n return 0;\n }\n\n let client: TinifyClient;\n try {\n client = new TinifyClient({\n ...(args.key !== undefined ? { apiKey: args.key } : {}),\n ...(args.baseUrl !== undefined ? { baseUrl: args.baseUrl } : {}),\n });\n } catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n return 1;\n }\n\n if (args.command === \"usage\") {\n const { data } = await client.usage();\n process.stdout.write(\n [\n `plan ${data.plan}`,\n `period ${data.period_start} → ${data.period_end}`,\n `included ${data.included}`,\n `used ${data.used}`,\n `reserved ${data.reserved}`,\n `remaining ${data.remaining}`,\n \"\",\n ].join(\"\\n\"),\n );\n return 0;\n }\n\n const { default: fs } = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n\n const rows: ResultRow[] = [];\n let failures = 0;\n\n for (const file of args.files) {\n try {\n const stat = await fs.stat(file);\n if (stat.size > MAX_FILE_BYTES) {\n process.stderr.write(\n `warn: skipping ${file} (${formatBytes(stat.size)} exceeds the 40 MB API limit)\\n`,\n );\n rows.push({ file, before: stat.size, after: stat.size, note: \"skipped\" });\n continue;\n }\n\n const result = await dispatch(client, args, file);\n const blob = await client.download(result);\n const outPath = outputPath(path, args, file, result.data.result_format);\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, new Uint8Array(await blob.arrayBuffer()));\n rows.push({\n file,\n before: result.data.original_bytes,\n after: result.data.result_bytes,\n note: result.data.optimized === false ? \"not smaller\" : \"\",\n });\n } catch (error) {\n failures += 1;\n const message =\n error instanceof TinifyApiError\n ? `${error.code}: ${error.message}`\n : error instanceof Error\n ? error.message\n : String(error);\n process.stderr.write(`error: ${file}: ${message}\\n`);\n rows.push({ file, before: 0, after: 0, note: \"failed\" });\n }\n }\n\n process.stdout.write(`${renderTable(rows)}\\n`);\n const before = rows.reduce((sum, row) => sum + row.before, 0);\n const after = rows.reduce((sum, row) => sum + row.after, 0);\n process.stdout.write(\n `total: ${formatBytes(before)} → ${formatBytes(after)} (${formatBytes(after - before)})\\n`,\n );\n return failures > 0 ? 1 : 0;\n}\n\nasync function dispatch(\n client: TinifyClient,\n args: ParsedCliArgs,\n file: string,\n): ReturnType<TinifyClient[\"compress\"]> {\n switch (args.command) {\n case \"compress\":\n return client.compress(file, {\n ...(args.quality !== undefined ? { quality_mode: args.quality } : {}),\n ...(args.targetSizeBytes !== undefined\n ? { target_size_bytes: args.targetSizeBytes }\n : {}),\n });\n case \"resize\":\n return client.resize(file, {\n ...(args.width !== undefined ? { width: args.width } : {}),\n ...(args.height !== undefined ? { height: args.height } : {}),\n ...(args.scale !== undefined ? { scale: args.scale } : {}),\n });\n case \"crop\":\n return client.crop(file, {\n x: args.x!,\n y: args.y!,\n width: args.width!,\n height: args.height!,\n });\n case \"convert\":\n return client.convert(file, {\n format: args.format!,\n ...(args.quality !== undefined ? { quality_mode: args.quality } : {}),\n });\n default:\n throw new TinifyError(`Unhandled command \"${args.command}\".`);\n }\n}\n\nfunction outputPath(\n path: typeof import(\"node:path\"),\n args: ParsedCliArgs,\n file: string,\n resultFormat: string | undefined,\n): string {\n const parsed = path.parse(file);\n const ext =\n args.command === \"convert\" && resultFormat !== undefined\n ? `.${resultFormat === \"jpeg\" ? \"jpg\" : resultFormat}`\n : parsed.ext || \"\";\n const name = `${parsed.name}.min${ext}`;\n return args.out !== undefined ? path.join(args.out, name) : path.join(parsed.dir, name);\n}\n\nconst invokedDirectly = (() => {\n try {\n if (typeof process === \"undefined\" || process.argv[1] === undefined) return false;\n return import.meta.url === pathToFileURL(process.argv[1]).href;\n } catch {\n return false;\n }\n})();\n\nif (invokedDirectly) {\n runCli(process.argv.slice(2)).then(\n (code) => {\n process.exitCode = code;\n },\n (error: unknown) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n },\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"names":[],"mappings":"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","file":"cli.js","sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from \"node:util\";\nimport { pathToFileURL } from \"node:url\";\nimport { TinifyClient } from \"./client\";\nimport { MAX_FILE_BYTES } from \"./constants\";\nimport { TinifyApiError, TinifyError } from \"./errors\";\nimport type { QualityMode, TargetFormat } from \"./types\";\n\nexport const CLI_COMMANDS = [\"compress\", \"resize\", \"crop\", \"convert\", \"usage\"] as const;\nexport type CliCommand = (typeof CLI_COMMANDS)[number];\n\nconst QUALITY_MODES: ReadonlySet<string> = new Set([\"balanced\", \"best_quality\", \"lossless\"]);\nconst FORMATS: ReadonlySet<string> = new Set([\"avif\", \"webp\", \"jpeg\", \"png\"]);\n\nexport class CliUsageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CliUsageError\";\n }\n}\n\nexport interface ParsedCliArgs {\n command: CliCommand;\n files: string[];\n key?: string;\n baseUrl?: string;\n out?: string;\n quality?: QualityMode;\n targetSizeBytes?: number;\n width?: number;\n height?: number;\n scale?: number;\n x?: number;\n y?: number;\n format?: TargetFormat;\n help: boolean;\n}\n\nexport const HELP_TEXT = `tinify-dev - Tinify.dev image API CLI\n\nUsage:\n tinify-dev <command> [options] <files...>\n\nCommands:\n compress <files...> Compress images (never returns larger files)\n resize <files...> Resize images (--width/--height/--scale)\n crop <files...> Crop images (--x --y --width --height)\n convert <files...> Convert images to another format (--format) [beta]\n usage Show current plan usage\n\nOptions:\n --key <key> API key (default: TINIFY_API_KEY env var)\n --base-url <url> API origin (default: TINIFY_BASE_URL or https://api.tinify.dev)\n --out <dir> Output directory (default: <name>.min.<ext> beside input)\n --quality <mode> balanced | best_quality | lossless\n --target-size <n> Target size in bytes (compress, beta)\n --width <n> Resize/crop width\n --height <n> Resize/crop height\n --scale <n> Resize scale factor (e.g. 0.5)\n --x <n> --y <n> Crop origin\n --format <fmt> avif | webp | jpeg | png (convert)\n -h, --help Show this help\n`;\n\nexport function parseCliArgs(argv: string[]): ParsedCliArgs {\n let parsed;\n try {\n parsed = parseArgs({\n args: argv,\n allowPositionals: true,\n strict: true,\n options: {\n key: { type: \"string\" },\n \"base-url\": { type: \"string\" },\n out: { type: \"string\" },\n quality: { type: \"string\" },\n \"target-size\": { type: \"string\" },\n width: { type: \"string\" },\n height: { type: \"string\" },\n scale: { type: \"string\" },\n x: { type: \"string\" },\n y: { type: \"string\" },\n format: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\" },\n },\n });\n } catch (error) {\n throw new CliUsageError(error instanceof Error ? error.message : String(error));\n }\n\n const { values, positionals } = parsed;\n const help = values.help === true;\n const [command, ...files] = positionals;\n\n if (command === undefined) {\n if (help) return { command: \"usage\", files: [], help: true };\n throw new CliUsageError(`Missing command. Expected one of: ${CLI_COMMANDS.join(\", \")}.`);\n }\n if (!(CLI_COMMANDS as readonly string[]).includes(command)) {\n throw new CliUsageError(\n `Unknown command \"${command}\". Expected one of: ${CLI_COMMANDS.join(\", \")}.`,\n );\n }\n const cliCommand = command as CliCommand;\n\n if (cliCommand !== \"usage\" && files.length === 0 && !help) {\n throw new CliUsageError(`The \"${cliCommand}\" command needs at least one file.`);\n }\n\n const quality = values.quality;\n if (quality !== undefined && !QUALITY_MODES.has(quality)) {\n throw new CliUsageError(\n `Invalid --quality \"${quality}\". Expected balanced, best_quality, or lossless.`,\n );\n }\n\n const format = values.format;\n if (cliCommand === \"convert\" && format === undefined && !help) {\n throw new CliUsageError('The \"convert\" command requires --format (avif|webp|jpeg|png).');\n }\n if (format !== undefined && !FORMATS.has(format)) {\n throw new CliUsageError(`Invalid --format \"${format}\". Expected avif, webp, jpeg, or png.`);\n }\n\n const args: ParsedCliArgs = {\n command: cliCommand,\n files,\n help,\n ...(values.key !== undefined ? { key: values.key } : {}),\n ...(values[\"base-url\"] !== undefined ? { baseUrl: values[\"base-url\"] } : {}),\n ...(values.out !== undefined ? { out: values.out } : {}),\n ...(quality !== undefined ? { quality: quality as QualityMode } : {}),\n ...(format !== undefined ? { format: format as TargetFormat } : {}),\n ...numericFlag(\"target-size\", values[\"target-size\"], \"targetSizeBytes\"),\n ...numericFlag(\"width\", values.width, \"width\"),\n ...numericFlag(\"height\", values.height, \"height\"),\n ...numericFlag(\"scale\", values.scale, \"scale\", true),\n ...numericFlag(\"x\", values.x, \"x\"),\n ...numericFlag(\"y\", values.y, \"y\"),\n };\n\n if (cliCommand === \"crop\" && !help) {\n for (const required of [\"x\", \"y\", \"width\", \"height\"] as const) {\n if (args[required] === undefined) {\n throw new CliUsageError(`The \"crop\" command requires --${required}.`);\n }\n }\n }\n\n return args;\n}\n\nfunction numericFlag(\n flag: string,\n raw: string | undefined,\n key: string,\n allowFloat = false,\n): Record<string, number> {\n if (raw === undefined) return {};\n const value = Number(raw);\n const valid = allowFloat ? Number.isFinite(value) : Number.isInteger(value);\n if (!valid || raw.trim() === \"\") {\n throw new CliUsageError(\n `Invalid --${flag} \"${raw}\". Expected ${allowFloat ? \"a number\" : \"an integer\"}.`,\n );\n }\n return { [key]: value };\n}\n\nexport function formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes)) return String(bytes);\n if (Math.abs(bytes) < 1024) return `${bytes} B`;\n const units = [\"kB\", \"MB\", \"GB\"];\n let value = bytes;\n let unit = \"B\";\n for (const next of units) {\n if (Math.abs(value) < 1024) break;\n value /= 1024;\n unit = next;\n }\n return `${value.toFixed(1)} ${unit}`;\n}\n\ninterface ResultRow {\n file: string;\n before: number;\n after: number;\n note: string;\n}\n\nexport function renderTable(rows: ResultRow[]): string {\n const header = { file: \"file\", before: \"before\", after: \"after\", saved: \"saved\" };\n const printable = rows.map((row) => {\n const savedPct =\n row.before > 0 ? (((row.after - row.before) / row.before) * 100).toFixed(1) : \"0.0\";\n return {\n file: row.file,\n before: formatBytes(row.before),\n after: formatBytes(row.after),\n saved: row.note !== \"\" ? row.note : `${savedPct}%`,\n };\n });\n const all = [header, ...printable];\n const width = (key: keyof typeof header): number =>\n Math.max(...all.map((row) => row[key].length));\n const line = (row: (typeof all)[number]): string =>\n [\n row.file.padEnd(width(\"file\")),\n row.before.padStart(width(\"before\")),\n row.after.padStart(width(\"after\")),\n row.saved.padStart(width(\"saved\")),\n ].join(\" \");\n return all.map(line).join(\"\\n\");\n}\n\nexport async function runCli(argv: string[]): Promise<number> {\n let args: ParsedCliArgs;\n try {\n args = parseCliArgs(argv);\n } catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n\\n`);\n process.stderr.write(HELP_TEXT);\n return 1;\n }\n if (args.help) {\n process.stdout.write(HELP_TEXT);\n return 0;\n }\n\n let client: TinifyClient;\n try {\n client = new TinifyClient({\n ...(args.key !== undefined ? { apiKey: args.key } : {}),\n ...(args.baseUrl !== undefined ? { baseUrl: args.baseUrl } : {}),\n });\n } catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n return 1;\n }\n\n if (args.command === \"usage\") {\n const { data } = await client.usage();\n process.stdout.write(\n [\n `plan ${data.plan}`,\n `period ${data.period_start} → ${data.period_end}`,\n `included ${data.included}`,\n `used ${data.used}`,\n `reserved ${data.reserved}`,\n `remaining ${data.remaining}`,\n \"\",\n ].join(\"\\n\"),\n );\n return 0;\n }\n\n const { default: fs } = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n\n const rows: ResultRow[] = [];\n let failures = 0;\n\n for (const file of args.files) {\n try {\n const stat = await fs.stat(file);\n if (stat.size > MAX_FILE_BYTES) {\n process.stderr.write(\n `warn: skipping ${file} (${formatBytes(stat.size)} exceeds the 40 MB API limit)\\n`,\n );\n rows.push({ file, before: stat.size, after: stat.size, note: \"skipped\" });\n continue;\n }\n\n const result = await dispatch(client, args, file);\n const blob = await client.download(result);\n const outPath = outputPath(path, args, file, result.data.result_format);\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, new Uint8Array(await blob.arrayBuffer()));\n rows.push({\n file,\n before: result.data.original_bytes,\n after: result.data.result_bytes,\n note: result.data.optimized === false ? \"not smaller\" : \"\",\n });\n } catch (error) {\n failures += 1;\n const message =\n error instanceof TinifyApiError\n ? `${error.code}: ${error.message}`\n : error instanceof Error\n ? error.message\n : String(error);\n process.stderr.write(`error: ${file}: ${message}\\n`);\n rows.push({ file, before: 0, after: 0, note: \"failed\" });\n }\n }\n\n process.stdout.write(`${renderTable(rows)}\\n`);\n const before = rows.reduce((sum, row) => sum + row.before, 0);\n const after = rows.reduce((sum, row) => sum + row.after, 0);\n process.stdout.write(\n `total: ${formatBytes(before)} → ${formatBytes(after)} (${formatBytes(after - before)})\\n`,\n );\n return failures > 0 ? 1 : 0;\n}\n\nasync function dispatch(\n client: TinifyClient,\n args: ParsedCliArgs,\n file: string,\n): ReturnType<TinifyClient[\"compress\"]> {\n switch (args.command) {\n case \"compress\":\n return client.compress(file, {\n ...(args.quality !== undefined ? { quality_mode: args.quality } : {}),\n ...(args.targetSizeBytes !== undefined\n ? { target_size_bytes: args.targetSizeBytes }\n : {}),\n });\n case \"resize\":\n return client.resize(file, {\n ...(args.width !== undefined ? { width: args.width } : {}),\n ...(args.height !== undefined ? { height: args.height } : {}),\n ...(args.scale !== undefined ? { scale: args.scale } : {}),\n });\n case \"crop\":\n return client.crop(file, {\n x: args.x!,\n y: args.y!,\n width: args.width!,\n height: args.height!,\n });\n case \"convert\":\n return client.convert(file, {\n format: args.format!,\n ...(args.quality !== undefined ? { quality_mode: args.quality } : {}),\n });\n default:\n throw new TinifyError(`Unhandled command \"${args.command}\".`);\n }\n}\n\nfunction outputPath(\n path: typeof import(\"node:path\"),\n args: ParsedCliArgs,\n file: string,\n resultFormat: string | undefined,\n): string {\n const parsed = path.parse(file);\n const ext =\n args.command === \"convert\" && resultFormat !== undefined\n ? `.${resultFormat === \"jpeg\" ? \"jpg\" : resultFormat}`\n : parsed.ext || \"\";\n const name = `${parsed.name}.min${ext}`;\n return args.out !== undefined ? path.join(args.out, name) : path.join(parsed.dir, name);\n}\n\nconst invokedDirectly = (() => {\n try {\n if (typeof process === \"undefined\" || process.argv[1] === undefined) return false;\n return import.meta.url === pathToFileURL(process.argv[1]).href;\n } catch {\n return false;\n }\n})();\n\nif (invokedDirectly) {\n runCli(process.argv.slice(2)).then(\n (code) => {\n process.exitCode = code;\n },\n (error: unknown) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n },\n );\n}\n"]}
|