@singlefax/cli 1.0.7 → 1.0.8
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/cli.mjs +23 -1
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -249,6 +249,16 @@ function contentTypeFor(file) {
|
|
|
249
249
|
case ".jpg":
|
|
250
250
|
case ".jpeg":
|
|
251
251
|
return "image/jpeg";
|
|
252
|
+
case ".gif":
|
|
253
|
+
return "image/gif";
|
|
254
|
+
case ".webp":
|
|
255
|
+
return "image/webp";
|
|
256
|
+
case ".bmp":
|
|
257
|
+
return "image/bmp";
|
|
258
|
+
case ".heic":
|
|
259
|
+
return "image/heic";
|
|
260
|
+
case ".heif":
|
|
261
|
+
return "image/heif";
|
|
252
262
|
case ".tif":
|
|
253
263
|
case ".tiff":
|
|
254
264
|
return "image/tiff";
|
|
@@ -256,8 +266,20 @@ function contentTypeFor(file) {
|
|
|
256
266
|
return "application/msword";
|
|
257
267
|
case ".docx":
|
|
258
268
|
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
269
|
+
case ".xls":
|
|
270
|
+
return "application/vnd.ms-excel";
|
|
271
|
+
case ".xlsx":
|
|
272
|
+
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
273
|
+
case ".ppt":
|
|
274
|
+
return "application/vnd.ms-powerpoint";
|
|
275
|
+
case ".pptx":
|
|
276
|
+
return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
|
|
277
|
+
case ".txt":
|
|
278
|
+
return "text/plain";
|
|
279
|
+
case ".rtf":
|
|
280
|
+
return "application/rtf";
|
|
259
281
|
default:
|
|
260
|
-
return "application/
|
|
282
|
+
return "application/octet-stream";
|
|
261
283
|
}
|
|
262
284
|
}
|
|
263
285
|
async function sendFax(client, opts) {
|
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/program.ts","../src/client.ts","../src/config.ts","../src/output.ts","../src/send.ts"],"sourcesContent":["import { runMain } from 'citty'\nimport { main } from './program.ts'\n\nawait runMain(main)\n","import { readFile, stat } from 'node:fs/promises'\nimport { defineCommand, renderUsage } from 'citty'\nimport { ApiError, createClient } from './client.ts'\nimport { readConfigFile, requireApiKey, resolveConfig, writeConfigFile } from './config.ts'\nimport {\n printBuyHuman,\n printCreditsHuman,\n printJson,\n printLine,\n printListHuman,\n printQuoteHuman,\n printSendHuman,\n printSkusHuman,\n printStatusHuman,\n} from './output.ts'\nimport { sendFax } from './send.ts'\n\nconst sharedArgs = {\n json: {\n type: 'boolean' as const,\n description: 'Print the API JSON body',\n },\n 'api-key': {\n type: 'string' as const,\n description: 'API key (sf_live_…). Overrides SINGLEFAX_API_KEY',\n },\n 'api-url': {\n type: 'string' as const,\n description: 'API base URL (default https://api.singlefax.com)',\n },\n}\n\nfunction fail(error: unknown): never {\n if (error instanceof ApiError) {\n throw error\n }\n throw error instanceof Error ? error : new Error(String(error))\n}\n\nexport const sendCommand = defineCommand({\n meta: {\n name: 'send',\n description: 'Upload a document and send it as a fax',\n },\n args: {\n file: {\n type: 'positional',\n description: 'Path to the PDF or office document',\n required: true,\n },\n to: {\n type: 'string',\n description: 'Destination fax number in E.164',\n required: true,\n },\n cover: {\n type: 'boolean',\n description: 'Prepend a cover page',\n },\n wait: {\n type: 'boolean',\n description: 'Poll until delivered or failed',\n },\n ...sharedArgs,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n try {\n const row = await sendFax(client, {\n file: String(args.file),\n to: String(args.to),\n cover: Boolean(args.cover),\n wait: Boolean(args.wait),\n })\n if (config.json) printJson(row)\n else printSendHuman(row)\n } catch (error) {\n fail(error)\n }\n },\n})\n\nconst statusCommand = defineCommand({\n meta: {\n name: 'status',\n description: 'Poll delivery status for an order you own',\n },\n args: {\n id: {\n type: 'positional',\n description: 'Fax order id',\n required: true,\n },\n ...sharedArgs,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n try {\n const row = await client.request({\n method: 'GET',\n path: `/api/v1/faxes/${encodeURIComponent(String(args.id))}`,\n })\n if (config.json) printJson(row)\n else printStatusHuman(row as Parameters<typeof printStatusHuman>[0])\n } catch (error) {\n fail(error)\n }\n },\n})\n\nconst listCommand = defineCommand({\n meta: {\n name: 'list',\n description: 'List recent fax orders',\n },\n args: {\n limit: {\n type: 'string',\n description: 'Page size (max 100)',\n default: '20',\n },\n offset: {\n type: 'string',\n description: 'Offset',\n default: '0',\n },\n ...sharedArgs,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n const limit = Math.min(Number(args.limit) || 20, 100)\n const offset = Number(args.offset) || 0\n try {\n const row = await client.request({\n method: 'GET',\n path: `/api/v1/faxes?limit=${limit}&offset=${offset}`,\n })\n if (config.json) printJson(row)\n else printListHuman(row as Parameters<typeof printListHuman>[0])\n } catch (error) {\n fail(error)\n }\n },\n})\n\nconst creditsBuyCommand = defineCommand({\n meta: {\n name: 'buy',\n description: 'Create a Stripe Checkout session for prepaid credits',\n },\n args: {\n dollars: {\n type: 'string',\n description: 'Credit pack in dollars (default 20)',\n default: '20',\n },\n ...sharedArgs,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n const dollars = Number(args.dollars)\n const amountCents = Number.isFinite(dollars) && dollars > 0 ? Math.round(dollars * 100) : 2000\n try {\n const row = await client.request<{ checkoutUrl?: string }>({\n method: 'POST',\n path: '/api/v1/credits/checkout',\n json: { amountCents },\n })\n if (config.json) printJson(row)\n else printLine(row.checkoutUrl || 'Checkout URL missing')\n } catch (error) {\n fail(error)\n }\n },\n})\n\nconst creditsCommand = defineCommand({\n meta: {\n name: 'credits',\n description: 'Show prepaid credit balance, or buy more',\n },\n args: sharedArgs,\n subCommands: {\n buy: creditsBuyCommand,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n try {\n const row = await client.request({\n method: 'GET',\n path: '/api/v1/credits',\n })\n if (config.json) printJson(row)\n else printCreditsHuman(row as Parameters<typeof printCreditsHuman>[0])\n } catch (error) {\n fail(error)\n }\n },\n})\n\nexport const skusCommand = defineCommand({\n meta: {\n name: 'skus',\n description: 'List product SKUs and prices (no API key required)',\n },\n args: sharedArgs,\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: config.apiKey,\n })\n try {\n const row = await client.request({\n method: 'GET',\n path: '/api/v1/skus',\n })\n if (config.json) printJson(row)\n else printSkusHuman(row as Parameters<typeof printSkusHuman>[0])\n } catch (error) {\n fail(error)\n }\n },\n})\n\nexport const quoteCommand = defineCommand({\n meta: {\n name: 'quote',\n description: 'Quote a retail send without charging',\n },\n args: {\n file: {\n type: 'positional',\n description: 'Optional PDF/office file for a live page count',\n required: false,\n },\n to: {\n type: 'string',\n description: 'Destination fax number in E.164',\n },\n pages: {\n type: 'string',\n description: 'Assumed billable pages when no file is given (default 10)',\n },\n ...sharedArgs,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n const file = args.file ? String(args.file) : ''\n let base64: string | undefined\n if (file) {\n const info = await stat(file)\n if (!info.isFile()) throw new Error('FILE must be a regular file')\n base64 = (await readFile(file)).toString('base64')\n }\n const pages = args.pages != null ? Number(args.pages) : undefined\n try {\n const row = await client.request({\n method: 'POST',\n path: '/api/v1/faxes/quote',\n json: {\n to: args.to ? String(args.to) : undefined,\n pages: Number.isFinite(pages) && pages && pages > 0 ? pages : undefined,\n base64,\n },\n })\n if (config.json) printJson(row)\n else printQuoteHuman(row as Parameters<typeof printQuoteHuman>[0])\n } catch (error) {\n fail(error)\n }\n },\n})\n\nexport const buyCommand = defineCommand({\n meta: {\n name: 'buy',\n description:\n 'Start Stripe Checkout for a SKU (credit_pack, inbound_30day, monthly-basic, annual-basic, monthly-business, annual-business, lifetime-basic, lifetime-pro)',\n },\n args: {\n sku: {\n type: 'positional',\n description: 'Catalog SKU id (see `singlefax skus`)',\n required: true,\n },\n dollars: {\n type: 'string',\n description: 'credit_pack amount in dollars (default 20)',\n },\n country: {\n type: 'string',\n description: 'US or CA for number SKUs (default US)',\n },\n state: {\n type: 'string',\n description: 'Optional US state or CA province for number SKUs',\n },\n ...sharedArgs,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n const sku = String(args.sku)\n const dollars = args.dollars != null ? Number(args.dollars) : undefined\n const amountCents =\n dollars != null && Number.isFinite(dollars) && dollars > 0\n ? Math.round(dollars * 100)\n : undefined\n const json = {\n sku,\n amountCents,\n country: args.country ? String(args.country).toUpperCase() : undefined,\n state: args.state ? String(args.state) : undefined,\n }\n try {\n let row: {\n status?: string\n sku?: string\n checkoutUrl?: string\n websiteUrl?: string\n phoneNumber?: string\n creditCents?: number\n notes?: string\n }\n try {\n row = await client.request({\n method: 'POST',\n path: '/api/v1/checkout',\n json,\n })\n } catch (error) {\n if (\n sku === 'credit_pack' &&\n error instanceof ApiError &&\n error.status === 404\n ) {\n const fallback = await client.request<{\n checkoutUrl?: string\n creditCents?: number\n }>({\n method: 'POST',\n path: '/api/v1/credits/checkout',\n json: { amountCents: amountCents ?? 2000 },\n })\n row = {\n status: 'awaiting_payment',\n sku: 'credit_pack',\n checkoutUrl: fallback.checkoutUrl,\n creditCents: fallback.creditCents,\n }\n } else {\n throw error\n }\n }\n if (config.json) printJson(row)\n else printBuyHuman(row)\n } catch (error) {\n fail(error)\n }\n },\n})\n\nconst configSetCommand = defineCommand({\n meta: {\n name: 'set',\n description: 'Write a local config value (api-key)',\n },\n args: {\n name: {\n type: 'positional',\n description: 'Name (only api-key is supported)',\n required: true,\n },\n value: {\n type: 'positional',\n description: 'Value',\n required: true,\n },\n },\n async run({ args }) {\n const name = String(args.name)\n const value = String(args.value)\n if (name !== 'api-key' && name !== 'apiKey') {\n throw new Error('Supported keys: api-key')\n }\n const current = await readConfigFile()\n const path = await writeConfigFile({ ...current, apiKey: value })\n printLine(`Saved API key to ${path}`)\n },\n})\n\nconst configCommand = defineCommand({\n meta: {\n name: 'config',\n description: 'Store API credentials locally',\n },\n subCommands: {\n set: configSetCommand,\n },\n})\n\nexport const main = defineCommand({\n meta: {\n name: 'singlefax',\n version: '1.0.0',\n description: 'SingleFax CLI — send faxes, quote, and buy SKUs via API key',\n },\n subCommands: {\n send: sendCommand,\n status: statusCommand,\n list: listCommand,\n quote: quoteCommand,\n skus: skusCommand,\n buy: buyCommand,\n credits: creditsCommand,\n config: configCommand,\n },\n})\n\nexport async function usageText(): Promise<string> {\n return renderUsage(main)\n}\n","export class ApiError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly body: unknown,\n ) {\n super(message)\n this.name = 'ApiError'\n }\n}\n\nexport type ApiClient = {\n apiUrl: string\n request: <T>(opts: {\n method: string\n path: string\n json?: unknown\n raw?: Buffer | Uint8Array\n contentType?: string\n idempotencyKey?: string\n }) => Promise<T>\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction formatError(status: number, body: unknown): string {\n if (body && typeof body === 'object') {\n const row = body as {\n statusMessage?: string\n message?: string\n data?: { code?: string; resolution?: string }\n }\n const headline = row.statusMessage || row.message || `HTTP ${status}`\n const resolution = row.data?.resolution\n return resolution ? `${headline}\\n${resolution}` : headline\n }\n return `HTTP ${status}`\n}\n\nfunction retryAfterMs(res: Response): number {\n const header = res.headers.get('retry-after')\n const seconds = header ? Number(header) : 1\n if (!Number.isFinite(seconds) || seconds < 1) return 1000\n return Math.min(seconds, 60) * 1000\n}\n\nexport function createClient(opts: {\n apiUrl: string\n apiKey?: string\n fetch?: typeof fetch\n sleep?: (ms: number) => Promise<void>\n}): ApiClient {\n const doFetch = opts.fetch ?? globalThis.fetch\n const doSleep = opts.sleep ?? sleep\n const apiUrl = opts.apiUrl.replace(/\\/$/, '')\n const apiKey = opts.apiKey?.trim() || ''\n\n async function request<T>(input: {\n method: string\n path: string\n json?: unknown\n raw?: Buffer | Uint8Array\n contentType?: string\n idempotencyKey?: string\n }): Promise<T> {\n const url = input.path.startsWith('http') ? input.path : `${apiUrl}${input.path}`\n const headers: Record<string, string> = {\n accept: 'application/json',\n }\n if (apiKey) headers.authorization = `Bearer ${apiKey}`\n let body: BodyInit | undefined\n if (input.raw) {\n headers['content-type'] = input.contentType || 'application/octet-stream'\n body = input.raw as BodyInit\n } else if (input.json !== undefined) {\n headers['content-type'] = 'application/json'\n body = JSON.stringify(input.json)\n }\n if (input.idempotencyKey) headers['idempotency-key'] = input.idempotencyKey\n\n const send = () =>\n doFetch(url, {\n method: input.method,\n headers,\n body,\n })\n\n let res = await send()\n if (res.status === 429) {\n await doSleep(retryAfterMs(res))\n res = await send()\n }\n\n const text = await res.text()\n let parsed: unknown = text\n if (text) {\n try {\n parsed = JSON.parse(text)\n } catch {\n parsed = { message: text }\n }\n } else {\n parsed = {}\n }\n\n if (!res.ok) {\n throw new ApiError(formatError(res.status, parsed), res.status, parsed)\n }\n return parsed as T\n }\n\n return { apiUrl, request }\n}\n","import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\n\nexport const DEFAULT_API_URL = 'https://api.singlefax.com'\n\nexport type CliConfigFile = {\n apiKey?: string\n apiUrl?: string\n}\n\nexport function configFilePath(): string {\n if (process.env.SINGLEFAX_CONFIG_PATH) return process.env.SINGLEFAX_CONFIG_PATH\n const xdg = process.env.XDG_CONFIG_HOME || join(homedir(), '.config')\n return join(xdg, 'singlefax', 'config.json')\n}\n\nexport async function readConfigFile(): Promise<CliConfigFile> {\n try {\n const raw = await readFile(configFilePath(), 'utf8')\n const parsed = JSON.parse(raw) as CliConfigFile\n return parsed && typeof parsed === 'object' ? parsed : {}\n } catch {\n return {}\n }\n}\n\nexport async function writeConfigFile(next: CliConfigFile): Promise<string> {\n const path = configFilePath()\n await mkdir(dirname(path), { recursive: true, mode: 0o700 })\n await writeFile(path, `${JSON.stringify(next, null, 2)}\\n`, { mode: 0o600 })\n await chmod(path, 0o600)\n return path\n}\n\nexport type ResolvedConfig = {\n apiUrl: string\n apiKey: string\n json: boolean\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined\n}\n\nexport async function resolveConfig(args: Record<string, unknown>): Promise<ResolvedConfig> {\n const file = await readConfigFile()\n const apiUrl =\n asString(args['api-url']) ||\n asString(args.apiUrl) ||\n asString(process.env.SINGLEFAX_API_URL) ||\n file.apiUrl ||\n DEFAULT_API_URL\n const apiKey =\n asString(args['api-key']) ||\n asString(args.apiKey) ||\n asString(process.env.SINGLEFAX_API_KEY) ||\n file.apiKey ||\n ''\n return {\n apiUrl: apiUrl.replace(/\\/$/, ''),\n apiKey,\n json: Boolean(args.json),\n }\n}\n\nexport function requireApiKey(config: ResolvedConfig): string {\n if (config.apiKey) return config.apiKey\n throw new Error(\n 'Missing API key. Set SINGLEFAX_API_KEY, pass --api-key, or run: singlefax config set api-key sf_live_…',\n )\n}\n","export function printJson(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`)\n}\n\nexport function printLine(line: string): void {\n process.stdout.write(`${line}\\n`)\n}\n\nfunction cents(value: unknown): string {\n const n = Number(value)\n if (!Number.isFinite(n)) return '—'\n return `$${(n / 100).toFixed(2)}`\n}\n\nexport function printSendHuman(row: {\n id?: string\n fulfillmentStatus?: string\n billablePages?: number\n totalCents?: number\n subtotalCents?: number\n}): void {\n printLine(\n [\n row.fulfillmentStatus || 'queued',\n row.id || '',\n row.billablePages != null ? `${row.billablePages} pages` : '',\n cents(row.totalCents ?? row.subtotalCents),\n ]\n .filter(Boolean)\n .join(' '),\n )\n}\n\nexport function printStatusHuman(row: {\n id?: string\n fulfillmentStatus?: string\n billablePages?: number\n totalCents?: number\n subtotalCents?: number\n failureClass?: string | null\n}): void {\n const parts = [\n row.fulfillmentStatus || 'unknown',\n row.id || '',\n row.billablePages != null ? `${row.billablePages} pages` : '',\n cents(row.totalCents ?? row.subtotalCents),\n ]\n if (row.failureClass) parts.push(row.failureClass)\n printLine(parts.filter(Boolean).join(' '))\n}\n\nexport function printListHuman(payload: {\n data?: Array<{\n id?: string\n fulfillmentStatus?: string\n billablePages?: number\n totalCents?: number\n destinationCountry?: string | null\n }>\n}): void {\n const rows = payload.data ?? []\n if (!rows.length) {\n printLine('No faxes.')\n return\n }\n for (const row of rows) {\n printLine(\n [\n row.id || '',\n row.fulfillmentStatus || '',\n row.billablePages != null ? `${row.billablePages}p` : '',\n cents(row.totalCents),\n row.destinationCountry || '',\n ]\n .filter((part) => part !== '')\n .join(' '),\n )\n }\n}\n\nexport function printCreditsHuman(row: {\n availableCents?: number\n reservedCents?: number\n}): void {\n printLine(\n `available ${cents(row.availableCents)} reserved ${cents(row.reservedCents)}`,\n )\n}\n\nexport function printSkusHuman(payload: {\n skus?: Array<{\n id?: string\n title?: string\n priceLabel?: string\n availability?: string\n websiteUrl?: string\n }>\n}): void {\n const rows = payload.skus ?? []\n if (!rows.length) {\n printLine('No SKUs.')\n return\n }\n for (const row of rows) {\n printLine(\n [\n row.id || '',\n row.availability || '',\n row.priceLabel || '',\n row.title || '',\n row.availability === 'website' ? row.websiteUrl || '' : '',\n ]\n .filter((part) => part !== '')\n .join(' '),\n )\n }\n}\n\nexport function printQuoteHuman(row: {\n sku?: string\n to?: string\n billablePages?: number\n subtotalCents?: number\n destinationCountry?: string\n priceLabel?: string\n assumedPages?: boolean\n}): void {\n if (row.subtotalCents == null && row.priceLabel) {\n printLine(row.priceLabel)\n return\n }\n printLine(\n [\n row.to || '',\n row.billablePages != null ? `${row.billablePages} pages` : '',\n cents(row.subtotalCents),\n row.destinationCountry || '',\n row.assumedPages ? '(assumed pages)' : '',\n ]\n .filter((part) => part !== '')\n .join(' '),\n )\n}\n\nexport function printBuyHuman(row: {\n status?: string\n sku?: string\n checkoutUrl?: string\n websiteUrl?: string\n phoneNumber?: string\n creditCents?: number\n notes?: string\n}): void {\n const url = row.checkoutUrl || row.websiteUrl || ''\n printLine(\n [\n row.status || '',\n row.sku || '',\n row.phoneNumber || '',\n row.creditCents != null ? cents(row.creditCents) : '',\n ]\n .filter((part) => part !== '')\n .join(' '),\n )\n if (url) printLine(url)\n if (row.notes && row.status === 'website_only') printLine(row.notes)\n}\n","import { randomUUID } from 'node:crypto'\nimport { readFile, stat } from 'node:fs/promises'\nimport { extname } from 'node:path'\nimport type { ApiClient } from './client.ts'\n\nconst TERMINAL = new Set(['delivered', 'failed_final'])\n\nexport type UploadCreated = {\n uploadToken: string\n uploadUrl: string\n contentType?: string\n maxBytes?: number\n}\n\nexport type FaxCreated = {\n id: string\n fulfillmentStatus: string\n billablePages?: number\n totalCents?: number\n subtotalCents?: number\n destinationCountry?: string\n}\n\nfunction contentTypeFor(file: string): string {\n switch (extname(file).toLowerCase()) {\n case '.pdf':\n return 'application/pdf'\n case '.png':\n return 'image/png'\n case '.jpg':\n case '.jpeg':\n return 'image/jpeg'\n case '.tif':\n case '.tiff':\n return 'image/tiff'\n case '.doc':\n return 'application/msword'\n case '.docx':\n return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'\n default:\n return 'application/pdf'\n }\n}\n\nexport async function sendFax(\n client: ApiClient,\n opts: {\n file: string\n to: string\n cover?: boolean\n wait?: boolean\n sleep?: (ms: number) => Promise<void>\n now?: () => number\n },\n): Promise<FaxCreated> {\n const filePath = opts.file\n const info = await stat(filePath)\n if (!info.isFile()) {\n throw new Error('FILE must be a regular file')\n }\n const contentType = contentTypeFor(filePath)\n const bytes = await readFile(filePath)\n\n const upload = await client.request<UploadCreated>({\n method: 'POST',\n path: '/api/v1/uploads',\n json: { contentType, maxBytes: bytes.byteLength },\n })\n\n await client.request({\n method: 'PUT',\n path: upload.uploadUrl,\n raw: bytes,\n contentType,\n })\n\n const fax = await client.request<FaxCreated>({\n method: 'POST',\n path: '/api/v1/faxes',\n json: { to: opts.to, uploadToken: upload.uploadToken, cover: Boolean(opts.cover) },\n idempotencyKey: randomUUID(),\n })\n\n if (!opts.wait) return fax\n\n const doSleep = opts.sleep ?? ((ms: number) => new Promise((r) => setTimeout(r, ms)))\n const started = (opts.now ?? Date.now)()\n const deadline = started + 180_000\n let latest: FaxCreated = fax\n while ((opts.now ?? Date.now)() < deadline) {\n if (TERMINAL.has(latest.fulfillmentStatus)) return latest\n await doSleep(2000)\n latest = await client.request<FaxCreated>({\n method: 'GET',\n path: `/api/v1/faxes/${encodeURIComponent(fax.id)}`,\n })\n }\n return latest\n}\n"],"mappings":"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","names":["readFile","stat","readFile","stat","readFile"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/program.ts","../src/client.ts","../src/config.ts","../src/output.ts","../src/send.ts"],"sourcesContent":["import { runMain } from 'citty'\nimport { main } from './program.ts'\n\nawait runMain(main)\n","import { readFile, stat } from 'node:fs/promises'\nimport { defineCommand, renderUsage } from 'citty'\nimport { ApiError, createClient } from './client.ts'\nimport { readConfigFile, requireApiKey, resolveConfig, writeConfigFile } from './config.ts'\nimport {\n printBuyHuman,\n printCreditsHuman,\n printJson,\n printLine,\n printListHuman,\n printQuoteHuman,\n printSendHuman,\n printSkusHuman,\n printStatusHuman,\n} from './output.ts'\nimport { sendFax } from './send.ts'\n\nconst sharedArgs = {\n json: {\n type: 'boolean' as const,\n description: 'Print the API JSON body',\n },\n 'api-key': {\n type: 'string' as const,\n description: 'API key (sf_live_…). Overrides SINGLEFAX_API_KEY',\n },\n 'api-url': {\n type: 'string' as const,\n description: 'API base URL (default https://api.singlefax.com)',\n },\n}\n\nfunction fail(error: unknown): never {\n if (error instanceof ApiError) {\n throw error\n }\n throw error instanceof Error ? error : new Error(String(error))\n}\n\nexport const sendCommand = defineCommand({\n meta: {\n name: 'send',\n description: 'Upload a document and send it as a fax',\n },\n args: {\n file: {\n type: 'positional',\n description: 'Path to the PDF or office document',\n required: true,\n },\n to: {\n type: 'string',\n description: 'Destination fax number in E.164',\n required: true,\n },\n cover: {\n type: 'boolean',\n description: 'Prepend a cover page',\n },\n wait: {\n type: 'boolean',\n description: 'Poll until delivered or failed',\n },\n ...sharedArgs,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n try {\n const row = await sendFax(client, {\n file: String(args.file),\n to: String(args.to),\n cover: Boolean(args.cover),\n wait: Boolean(args.wait),\n })\n if (config.json) printJson(row)\n else printSendHuman(row)\n } catch (error) {\n fail(error)\n }\n },\n})\n\nconst statusCommand = defineCommand({\n meta: {\n name: 'status',\n description: 'Poll delivery status for an order you own',\n },\n args: {\n id: {\n type: 'positional',\n description: 'Fax order id',\n required: true,\n },\n ...sharedArgs,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n try {\n const row = await client.request({\n method: 'GET',\n path: `/api/v1/faxes/${encodeURIComponent(String(args.id))}`,\n })\n if (config.json) printJson(row)\n else printStatusHuman(row as Parameters<typeof printStatusHuman>[0])\n } catch (error) {\n fail(error)\n }\n },\n})\n\nconst listCommand = defineCommand({\n meta: {\n name: 'list',\n description: 'List recent fax orders',\n },\n args: {\n limit: {\n type: 'string',\n description: 'Page size (max 100)',\n default: '20',\n },\n offset: {\n type: 'string',\n description: 'Offset',\n default: '0',\n },\n ...sharedArgs,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n const limit = Math.min(Number(args.limit) || 20, 100)\n const offset = Number(args.offset) || 0\n try {\n const row = await client.request({\n method: 'GET',\n path: `/api/v1/faxes?limit=${limit}&offset=${offset}`,\n })\n if (config.json) printJson(row)\n else printListHuman(row as Parameters<typeof printListHuman>[0])\n } catch (error) {\n fail(error)\n }\n },\n})\n\nconst creditsBuyCommand = defineCommand({\n meta: {\n name: 'buy',\n description: 'Create a Stripe Checkout session for prepaid credits',\n },\n args: {\n dollars: {\n type: 'string',\n description: 'Credit pack in dollars (default 20)',\n default: '20',\n },\n ...sharedArgs,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n const dollars = Number(args.dollars)\n const amountCents = Number.isFinite(dollars) && dollars > 0 ? Math.round(dollars * 100) : 2000\n try {\n const row = await client.request<{ checkoutUrl?: string }>({\n method: 'POST',\n path: '/api/v1/credits/checkout',\n json: { amountCents },\n })\n if (config.json) printJson(row)\n else printLine(row.checkoutUrl || 'Checkout URL missing')\n } catch (error) {\n fail(error)\n }\n },\n})\n\nconst creditsCommand = defineCommand({\n meta: {\n name: 'credits',\n description: 'Show prepaid credit balance, or buy more',\n },\n args: sharedArgs,\n subCommands: {\n buy: creditsBuyCommand,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n try {\n const row = await client.request({\n method: 'GET',\n path: '/api/v1/credits',\n })\n if (config.json) printJson(row)\n else printCreditsHuman(row as Parameters<typeof printCreditsHuman>[0])\n } catch (error) {\n fail(error)\n }\n },\n})\n\nexport const skusCommand = defineCommand({\n meta: {\n name: 'skus',\n description: 'List product SKUs and prices (no API key required)',\n },\n args: sharedArgs,\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: config.apiKey,\n })\n try {\n const row = await client.request({\n method: 'GET',\n path: '/api/v1/skus',\n })\n if (config.json) printJson(row)\n else printSkusHuman(row as Parameters<typeof printSkusHuman>[0])\n } catch (error) {\n fail(error)\n }\n },\n})\n\nexport const quoteCommand = defineCommand({\n meta: {\n name: 'quote',\n description: 'Quote a retail send without charging',\n },\n args: {\n file: {\n type: 'positional',\n description: 'Optional PDF/office file for a live page count',\n required: false,\n },\n to: {\n type: 'string',\n description: 'Destination fax number in E.164',\n },\n pages: {\n type: 'string',\n description: 'Assumed billable pages when no file is given (default 10)',\n },\n ...sharedArgs,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n const file = args.file ? String(args.file) : ''\n let base64: string | undefined\n if (file) {\n const info = await stat(file)\n if (!info.isFile()) throw new Error('FILE must be a regular file')\n base64 = (await readFile(file)).toString('base64')\n }\n const pages = args.pages != null ? Number(args.pages) : undefined\n try {\n const row = await client.request({\n method: 'POST',\n path: '/api/v1/faxes/quote',\n json: {\n to: args.to ? String(args.to) : undefined,\n pages: Number.isFinite(pages) && pages && pages > 0 ? pages : undefined,\n base64,\n },\n })\n if (config.json) printJson(row)\n else printQuoteHuman(row as Parameters<typeof printQuoteHuman>[0])\n } catch (error) {\n fail(error)\n }\n },\n})\n\nexport const buyCommand = defineCommand({\n meta: {\n name: 'buy',\n description:\n 'Start Stripe Checkout for a SKU (credit_pack, inbound_30day, monthly-basic, annual-basic, monthly-business, annual-business, lifetime-basic, lifetime-pro)',\n },\n args: {\n sku: {\n type: 'positional',\n description: 'Catalog SKU id (see `singlefax skus`)',\n required: true,\n },\n dollars: {\n type: 'string',\n description: 'credit_pack amount in dollars (default 20)',\n },\n country: {\n type: 'string',\n description: 'US or CA for number SKUs (default US)',\n },\n state: {\n type: 'string',\n description: 'Optional US state or CA province for number SKUs',\n },\n ...sharedArgs,\n },\n async run({ args }) {\n const config = await resolveConfig(args)\n const client = createClient({\n apiUrl: config.apiUrl,\n apiKey: requireApiKey(config),\n })\n const sku = String(args.sku)\n const dollars = args.dollars != null ? Number(args.dollars) : undefined\n const amountCents =\n dollars != null && Number.isFinite(dollars) && dollars > 0\n ? Math.round(dollars * 100)\n : undefined\n const json = {\n sku,\n amountCents,\n country: args.country ? String(args.country).toUpperCase() : undefined,\n state: args.state ? String(args.state) : undefined,\n }\n try {\n let row: {\n status?: string\n sku?: string\n checkoutUrl?: string\n websiteUrl?: string\n phoneNumber?: string\n creditCents?: number\n notes?: string\n }\n try {\n row = await client.request({\n method: 'POST',\n path: '/api/v1/checkout',\n json,\n })\n } catch (error) {\n if (\n sku === 'credit_pack' &&\n error instanceof ApiError &&\n error.status === 404\n ) {\n const fallback = await client.request<{\n checkoutUrl?: string\n creditCents?: number\n }>({\n method: 'POST',\n path: '/api/v1/credits/checkout',\n json: { amountCents: amountCents ?? 2000 },\n })\n row = {\n status: 'awaiting_payment',\n sku: 'credit_pack',\n checkoutUrl: fallback.checkoutUrl,\n creditCents: fallback.creditCents,\n }\n } else {\n throw error\n }\n }\n if (config.json) printJson(row)\n else printBuyHuman(row)\n } catch (error) {\n fail(error)\n }\n },\n})\n\nconst configSetCommand = defineCommand({\n meta: {\n name: 'set',\n description: 'Write a local config value (api-key)',\n },\n args: {\n name: {\n type: 'positional',\n description: 'Name (only api-key is supported)',\n required: true,\n },\n value: {\n type: 'positional',\n description: 'Value',\n required: true,\n },\n },\n async run({ args }) {\n const name = String(args.name)\n const value = String(args.value)\n if (name !== 'api-key' && name !== 'apiKey') {\n throw new Error('Supported keys: api-key')\n }\n const current = await readConfigFile()\n const path = await writeConfigFile({ ...current, apiKey: value })\n printLine(`Saved API key to ${path}`)\n },\n})\n\nconst configCommand = defineCommand({\n meta: {\n name: 'config',\n description: 'Store API credentials locally',\n },\n subCommands: {\n set: configSetCommand,\n },\n})\n\nexport const main = defineCommand({\n meta: {\n name: 'singlefax',\n version: '1.0.0',\n description: 'SingleFax CLI — send faxes, quote, and buy SKUs via API key',\n },\n subCommands: {\n send: sendCommand,\n status: statusCommand,\n list: listCommand,\n quote: quoteCommand,\n skus: skusCommand,\n buy: buyCommand,\n credits: creditsCommand,\n config: configCommand,\n },\n})\n\nexport async function usageText(): Promise<string> {\n return renderUsage(main)\n}\n","export class ApiError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly body: unknown,\n ) {\n super(message)\n this.name = 'ApiError'\n }\n}\n\nexport type ApiClient = {\n apiUrl: string\n request: <T>(opts: {\n method: string\n path: string\n json?: unknown\n raw?: Buffer | Uint8Array\n contentType?: string\n idempotencyKey?: string\n }) => Promise<T>\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction formatError(status: number, body: unknown): string {\n if (body && typeof body === 'object') {\n const row = body as {\n statusMessage?: string\n message?: string\n data?: { code?: string; resolution?: string }\n }\n const headline = row.statusMessage || row.message || `HTTP ${status}`\n const resolution = row.data?.resolution\n return resolution ? `${headline}\\n${resolution}` : headline\n }\n return `HTTP ${status}`\n}\n\nfunction retryAfterMs(res: Response): number {\n const header = res.headers.get('retry-after')\n const seconds = header ? Number(header) : 1\n if (!Number.isFinite(seconds) || seconds < 1) return 1000\n return Math.min(seconds, 60) * 1000\n}\n\nexport function createClient(opts: {\n apiUrl: string\n apiKey?: string\n fetch?: typeof fetch\n sleep?: (ms: number) => Promise<void>\n}): ApiClient {\n const doFetch = opts.fetch ?? globalThis.fetch\n const doSleep = opts.sleep ?? sleep\n const apiUrl = opts.apiUrl.replace(/\\/$/, '')\n const apiKey = opts.apiKey?.trim() || ''\n\n async function request<T>(input: {\n method: string\n path: string\n json?: unknown\n raw?: Buffer | Uint8Array\n contentType?: string\n idempotencyKey?: string\n }): Promise<T> {\n const url = input.path.startsWith('http') ? input.path : `${apiUrl}${input.path}`\n const headers: Record<string, string> = {\n accept: 'application/json',\n }\n if (apiKey) headers.authorization = `Bearer ${apiKey}`\n let body: BodyInit | undefined\n if (input.raw) {\n headers['content-type'] = input.contentType || 'application/octet-stream'\n body = input.raw as BodyInit\n } else if (input.json !== undefined) {\n headers['content-type'] = 'application/json'\n body = JSON.stringify(input.json)\n }\n if (input.idempotencyKey) headers['idempotency-key'] = input.idempotencyKey\n\n const send = () =>\n doFetch(url, {\n method: input.method,\n headers,\n body,\n })\n\n let res = await send()\n if (res.status === 429) {\n await doSleep(retryAfterMs(res))\n res = await send()\n }\n\n const text = await res.text()\n let parsed: unknown = text\n if (text) {\n try {\n parsed = JSON.parse(text)\n } catch {\n parsed = { message: text }\n }\n } else {\n parsed = {}\n }\n\n if (!res.ok) {\n throw new ApiError(formatError(res.status, parsed), res.status, parsed)\n }\n return parsed as T\n }\n\n return { apiUrl, request }\n}\n","import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\n\nexport const DEFAULT_API_URL = 'https://api.singlefax.com'\n\nexport type CliConfigFile = {\n apiKey?: string\n apiUrl?: string\n}\n\nexport function configFilePath(): string {\n if (process.env.SINGLEFAX_CONFIG_PATH) return process.env.SINGLEFAX_CONFIG_PATH\n const xdg = process.env.XDG_CONFIG_HOME || join(homedir(), '.config')\n return join(xdg, 'singlefax', 'config.json')\n}\n\nexport async function readConfigFile(): Promise<CliConfigFile> {\n try {\n const raw = await readFile(configFilePath(), 'utf8')\n const parsed = JSON.parse(raw) as CliConfigFile\n return parsed && typeof parsed === 'object' ? parsed : {}\n } catch {\n return {}\n }\n}\n\nexport async function writeConfigFile(next: CliConfigFile): Promise<string> {\n const path = configFilePath()\n await mkdir(dirname(path), { recursive: true, mode: 0o700 })\n await writeFile(path, `${JSON.stringify(next, null, 2)}\\n`, { mode: 0o600 })\n await chmod(path, 0o600)\n return path\n}\n\nexport type ResolvedConfig = {\n apiUrl: string\n apiKey: string\n json: boolean\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined\n}\n\nexport async function resolveConfig(args: Record<string, unknown>): Promise<ResolvedConfig> {\n const file = await readConfigFile()\n const apiUrl =\n asString(args['api-url']) ||\n asString(args.apiUrl) ||\n asString(process.env.SINGLEFAX_API_URL) ||\n file.apiUrl ||\n DEFAULT_API_URL\n const apiKey =\n asString(args['api-key']) ||\n asString(args.apiKey) ||\n asString(process.env.SINGLEFAX_API_KEY) ||\n file.apiKey ||\n ''\n return {\n apiUrl: apiUrl.replace(/\\/$/, ''),\n apiKey,\n json: Boolean(args.json),\n }\n}\n\nexport function requireApiKey(config: ResolvedConfig): string {\n if (config.apiKey) return config.apiKey\n throw new Error(\n 'Missing API key. Set SINGLEFAX_API_KEY, pass --api-key, or run: singlefax config set api-key sf_live_…',\n )\n}\n","export function printJson(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`)\n}\n\nexport function printLine(line: string): void {\n process.stdout.write(`${line}\\n`)\n}\n\nfunction cents(value: unknown): string {\n const n = Number(value)\n if (!Number.isFinite(n)) return '—'\n return `$${(n / 100).toFixed(2)}`\n}\n\nexport function printSendHuman(row: {\n id?: string\n fulfillmentStatus?: string\n billablePages?: number\n totalCents?: number\n subtotalCents?: number\n}): void {\n printLine(\n [\n row.fulfillmentStatus || 'queued',\n row.id || '',\n row.billablePages != null ? `${row.billablePages} pages` : '',\n cents(row.totalCents ?? row.subtotalCents),\n ]\n .filter(Boolean)\n .join(' '),\n )\n}\n\nexport function printStatusHuman(row: {\n id?: string\n fulfillmentStatus?: string\n billablePages?: number\n totalCents?: number\n subtotalCents?: number\n failureClass?: string | null\n}): void {\n const parts = [\n row.fulfillmentStatus || 'unknown',\n row.id || '',\n row.billablePages != null ? `${row.billablePages} pages` : '',\n cents(row.totalCents ?? row.subtotalCents),\n ]\n if (row.failureClass) parts.push(row.failureClass)\n printLine(parts.filter(Boolean).join(' '))\n}\n\nexport function printListHuman(payload: {\n data?: Array<{\n id?: string\n fulfillmentStatus?: string\n billablePages?: number\n totalCents?: number\n destinationCountry?: string | null\n }>\n}): void {\n const rows = payload.data ?? []\n if (!rows.length) {\n printLine('No faxes.')\n return\n }\n for (const row of rows) {\n printLine(\n [\n row.id || '',\n row.fulfillmentStatus || '',\n row.billablePages != null ? `${row.billablePages}p` : '',\n cents(row.totalCents),\n row.destinationCountry || '',\n ]\n .filter((part) => part !== '')\n .join(' '),\n )\n }\n}\n\nexport function printCreditsHuman(row: {\n availableCents?: number\n reservedCents?: number\n}): void {\n printLine(\n `available ${cents(row.availableCents)} reserved ${cents(row.reservedCents)}`,\n )\n}\n\nexport function printSkusHuman(payload: {\n skus?: Array<{\n id?: string\n title?: string\n priceLabel?: string\n availability?: string\n websiteUrl?: string\n }>\n}): void {\n const rows = payload.skus ?? []\n if (!rows.length) {\n printLine('No SKUs.')\n return\n }\n for (const row of rows) {\n printLine(\n [\n row.id || '',\n row.availability || '',\n row.priceLabel || '',\n row.title || '',\n row.availability === 'website' ? row.websiteUrl || '' : '',\n ]\n .filter((part) => part !== '')\n .join(' '),\n )\n }\n}\n\nexport function printQuoteHuman(row: {\n sku?: string\n to?: string\n billablePages?: number\n subtotalCents?: number\n destinationCountry?: string\n priceLabel?: string\n assumedPages?: boolean\n}): void {\n if (row.subtotalCents == null && row.priceLabel) {\n printLine(row.priceLabel)\n return\n }\n printLine(\n [\n row.to || '',\n row.billablePages != null ? `${row.billablePages} pages` : '',\n cents(row.subtotalCents),\n row.destinationCountry || '',\n row.assumedPages ? '(assumed pages)' : '',\n ]\n .filter((part) => part !== '')\n .join(' '),\n )\n}\n\nexport function printBuyHuman(row: {\n status?: string\n sku?: string\n checkoutUrl?: string\n websiteUrl?: string\n phoneNumber?: string\n creditCents?: number\n notes?: string\n}): void {\n const url = row.checkoutUrl || row.websiteUrl || ''\n printLine(\n [\n row.status || '',\n row.sku || '',\n row.phoneNumber || '',\n row.creditCents != null ? cents(row.creditCents) : '',\n ]\n .filter((part) => part !== '')\n .join(' '),\n )\n if (url) printLine(url)\n if (row.notes && row.status === 'website_only') printLine(row.notes)\n}\n","import { randomUUID } from 'node:crypto'\nimport { readFile, stat } from 'node:fs/promises'\nimport { extname } from 'node:path'\nimport type { ApiClient } from './client.ts'\n\nconst TERMINAL = new Set(['delivered', 'failed_final'])\n\nexport type UploadCreated = {\n uploadToken: string\n uploadUrl: string\n contentType?: string\n maxBytes?: number\n}\n\nexport type FaxCreated = {\n id: string\n fulfillmentStatus: string\n billablePages?: number\n totalCents?: number\n subtotalCents?: number\n destinationCountry?: string\n}\n\nfunction contentTypeFor(file: string): string {\n switch (extname(file).toLowerCase()) {\n case '.pdf':\n return 'application/pdf'\n case '.png':\n return 'image/png'\n case '.jpg':\n case '.jpeg':\n return 'image/jpeg'\n case '.gif':\n return 'image/gif'\n case '.webp':\n return 'image/webp'\n case '.bmp':\n return 'image/bmp'\n case '.heic':\n return 'image/heic'\n case '.heif':\n return 'image/heif'\n case '.tif':\n case '.tiff':\n return 'image/tiff'\n case '.doc':\n return 'application/msword'\n case '.docx':\n return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'\n case '.xls':\n return 'application/vnd.ms-excel'\n case '.xlsx':\n return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'\n case '.ppt':\n return 'application/vnd.ms-powerpoint'\n case '.pptx':\n return 'application/vnd.openxmlformats-officedocument.presentationml.presentation'\n case '.txt':\n return 'text/plain'\n case '.rtf':\n return 'application/rtf'\n default:\n return 'application/octet-stream'\n }\n}\n\nexport async function sendFax(\n client: ApiClient,\n opts: {\n file: string\n to: string\n cover?: boolean\n wait?: boolean\n sleep?: (ms: number) => Promise<void>\n now?: () => number\n },\n): Promise<FaxCreated> {\n const filePath = opts.file\n const info = await stat(filePath)\n if (!info.isFile()) {\n throw new Error('FILE must be a regular file')\n }\n const contentType = contentTypeFor(filePath)\n const bytes = await readFile(filePath)\n\n const upload = await client.request<UploadCreated>({\n method: 'POST',\n path: '/api/v1/uploads',\n json: { contentType, maxBytes: bytes.byteLength },\n })\n\n await client.request({\n method: 'PUT',\n path: upload.uploadUrl,\n raw: bytes,\n contentType,\n })\n\n const fax = await client.request<FaxCreated>({\n method: 'POST',\n path: '/api/v1/faxes',\n json: { to: opts.to, uploadToken: upload.uploadToken, cover: Boolean(opts.cover) },\n idempotencyKey: randomUUID(),\n })\n\n if (!opts.wait) return fax\n\n const doSleep = opts.sleep ?? ((ms: number) => new Promise((r) => setTimeout(r, ms)))\n const started = (opts.now ?? Date.now)()\n const deadline = started + 180_000\n let latest: FaxCreated = fax\n while ((opts.now ?? Date.now)() < deadline) {\n if (TERMINAL.has(latest.fulfillmentStatus)) return latest\n await doSleep(2000)\n latest = await client.request<FaxCreated>({\n method: 'GET',\n path: `/api/v1/faxes/${encodeURIComponent(fax.id)}`,\n })\n }\n return latest\n}\n"],"mappings":"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","names":["readFile","stat","readFile","stat","readFile"]}
|