@singlefax/cli 1.0.8 → 1.0.10
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/README.md +8 -2
- package/dist/cli.mjs +92 -3
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,8 +22,12 @@ singlefax config set api-key sf_live_…
|
|
|
22
22
|
|
|
23
23
|
## Send
|
|
24
24
|
|
|
25
|
+
Pass the original file. PDF, Word, Excel, PowerPoint, RTF, plain text, and images
|
|
26
|
+
(JPEG, PNG, TIFF, GIF, WebP, BMP, HEIC) are accepted. **Do not convert to PDF first**
|
|
27
|
+
— send the original; we convert before sending.
|
|
28
|
+
|
|
25
29
|
```bash
|
|
26
|
-
npx @singlefax/cli send ./document.
|
|
30
|
+
npx @singlefax/cli send ./document.docx --to +14155552671
|
|
27
31
|
npx @singlefax/cli send ./document.pdf --to +14155552671 --wait --json
|
|
28
32
|
```
|
|
29
33
|
|
|
@@ -37,13 +41,15 @@ npx @singlefax/cli send ./document.pdf --to +14155552671 --wait --json
|
|
|
37
41
|
| `quote [--to +E164] [--pages 10] [FILE]` | `POST /api/v1/faxes/quote` |
|
|
38
42
|
| `status <id>` | `GET /api/v1/faxes/:id` |
|
|
39
43
|
| `list` | `GET /api/v1/faxes` |
|
|
44
|
+
| `numbers` | `GET /api/v1/numbers` |
|
|
45
|
+
| `numbers buy [--sku inbound_30day] [--country US] [--state CA]` | `POST /api/v1/numbers` |
|
|
40
46
|
| `skus` | `GET /api/v1/skus` |
|
|
41
47
|
| `buy <sku> [--dollars 20] [--country US] [--state CA]` | `POST /api/v1/checkout` |
|
|
42
48
|
| `credits` | `GET /api/v1/credits` |
|
|
43
49
|
| `credits buy [--dollars 20]` | `POST /api/v1/credits/checkout` |
|
|
44
50
|
| `config set api-key sf_live_…` | writes `~/.config/singlefax/config.json` |
|
|
45
51
|
|
|
46
|
-
`buy` SKUs: `credit_pack`, `inbound_30day`, `monthly-basic`, `annual-basic`, `monthly-business`, `annual-business`, `lifetime-basic`, `lifetime-pro`. HIPAA / EIN / IRS print a website URL. Send a
|
|
52
|
+
`buy` SKUs: `credit_pack`, `inbound_30day`, `monthly-basic`, `annual-basic`, `monthly-business`, `annual-business`, `lifetime-basic`, `lifetime-pro`. HIPAA / EIN / IRS print a website URL. Send a document with `send`, not `buy`. Get a number with `numbers buy` (default 30-day). Do not convert to PDF first.
|
|
47
53
|
|
|
48
54
|
Flags: `--json`, `--api-key`, `--api-url` (default `https://api.singlefax.com`).
|
|
49
55
|
|
package/dist/cli.mjs
CHANGED
|
@@ -234,6 +234,24 @@ function printBuyHuman(row) {
|
|
|
234
234
|
if (url) printLine(url);
|
|
235
235
|
if (row.notes && row.status === "website_only") printLine(row.notes);
|
|
236
236
|
}
|
|
237
|
+
function printNumbersHuman(payload) {
|
|
238
|
+
const rows = payload.numbers ?? [];
|
|
239
|
+
if (!rows.length) {
|
|
240
|
+
printLine("No inbound numbers. Buy one with: singlefax numbers buy");
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
for (const row of rows) {
|
|
244
|
+
printLine(
|
|
245
|
+
[
|
|
246
|
+
row.phoneNumber || "",
|
|
247
|
+
row.orderType || "",
|
|
248
|
+
row.status || "",
|
|
249
|
+
row.expiresAt || "no expiry",
|
|
250
|
+
row.isDefault ? "default" : ""
|
|
251
|
+
].filter((part) => part !== "").join(" ")
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
237
255
|
|
|
238
256
|
// src/send.ts
|
|
239
257
|
import { randomUUID } from "crypto";
|
|
@@ -352,7 +370,7 @@ var sendCommand = defineCommand({
|
|
|
352
370
|
args: {
|
|
353
371
|
file: {
|
|
354
372
|
type: "positional",
|
|
355
|
-
description: "Path to the PDF or
|
|
373
|
+
description: "Path to the original document (PDF, Word, Excel, PowerPoint, RTF, text, or image). Do not convert to PDF first.",
|
|
356
374
|
required: true
|
|
357
375
|
},
|
|
358
376
|
to: {
|
|
@@ -520,6 +538,76 @@ var creditsCommand = defineCommand({
|
|
|
520
538
|
}
|
|
521
539
|
}
|
|
522
540
|
});
|
|
541
|
+
var numbersBuyCommand = defineCommand({
|
|
542
|
+
meta: {
|
|
543
|
+
name: "buy",
|
|
544
|
+
description: "Reserve an inbound fax number and open Stripe Checkout (default 30-day)"
|
|
545
|
+
},
|
|
546
|
+
args: {
|
|
547
|
+
sku: {
|
|
548
|
+
type: "string",
|
|
549
|
+
description: "inbound_30day (default) | lifetime-basic | lifetime-pro | monthly-basic | annual-basic | monthly-business | annual-business"
|
|
550
|
+
},
|
|
551
|
+
country: {
|
|
552
|
+
type: "string",
|
|
553
|
+
description: "US or CA (default US)"
|
|
554
|
+
},
|
|
555
|
+
state: {
|
|
556
|
+
type: "string",
|
|
557
|
+
description: "Optional US state or CA province"
|
|
558
|
+
},
|
|
559
|
+
...sharedArgs
|
|
560
|
+
},
|
|
561
|
+
async run({ args }) {
|
|
562
|
+
const config = await resolveConfig(args);
|
|
563
|
+
const client = createClient({
|
|
564
|
+
apiUrl: config.apiUrl,
|
|
565
|
+
apiKey: requireApiKey(config)
|
|
566
|
+
});
|
|
567
|
+
try {
|
|
568
|
+
const row = await client.request({
|
|
569
|
+
method: "POST",
|
|
570
|
+
path: "/api/v1/numbers",
|
|
571
|
+
json: {
|
|
572
|
+
sku: args.sku ? String(args.sku) : void 0,
|
|
573
|
+
country: args.country ? String(args.country).toUpperCase() : void 0,
|
|
574
|
+
state: args.state ? String(args.state) : void 0
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
if (config.json) printJson(row);
|
|
578
|
+
else printBuyHuman(row);
|
|
579
|
+
} catch (error) {
|
|
580
|
+
fail(error);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
var numbersCommand = defineCommand({
|
|
585
|
+
meta: {
|
|
586
|
+
name: "numbers",
|
|
587
|
+
description: "List inbound fax numbers, or buy one"
|
|
588
|
+
},
|
|
589
|
+
args: sharedArgs,
|
|
590
|
+
subCommands: {
|
|
591
|
+
buy: numbersBuyCommand
|
|
592
|
+
},
|
|
593
|
+
async run({ args }) {
|
|
594
|
+
const config = await resolveConfig(args);
|
|
595
|
+
const client = createClient({
|
|
596
|
+
apiUrl: config.apiUrl,
|
|
597
|
+
apiKey: requireApiKey(config)
|
|
598
|
+
});
|
|
599
|
+
try {
|
|
600
|
+
const row = await client.request({
|
|
601
|
+
method: "GET",
|
|
602
|
+
path: "/api/v1/numbers"
|
|
603
|
+
});
|
|
604
|
+
if (config.json) printJson(row);
|
|
605
|
+
else printNumbersHuman(row);
|
|
606
|
+
} catch (error) {
|
|
607
|
+
fail(error);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
});
|
|
523
611
|
var skusCommand = defineCommand({
|
|
524
612
|
meta: {
|
|
525
613
|
name: "skus",
|
|
@@ -552,7 +640,7 @@ var quoteCommand = defineCommand({
|
|
|
552
640
|
args: {
|
|
553
641
|
file: {
|
|
554
642
|
type: "positional",
|
|
555
|
-
description: "Optional
|
|
643
|
+
description: "Optional original file for a live page count (PDF, Word, Excel, PowerPoint, RTF, text, or image). Do not convert to PDF first.",
|
|
556
644
|
required: false
|
|
557
645
|
},
|
|
558
646
|
to: {
|
|
@@ -709,7 +797,7 @@ var main = defineCommand({
|
|
|
709
797
|
meta: {
|
|
710
798
|
name: "singlefax",
|
|
711
799
|
version: "1.0.0",
|
|
712
|
-
description: "SingleFax CLI \u2014 send faxes, quote, and buy SKUs via API key"
|
|
800
|
+
description: "SingleFax CLI \u2014 send faxes, quote, and buy SKUs via API key. Send original Word, Excel, PDF, or images \u2014 do not convert to PDF first."
|
|
713
801
|
},
|
|
714
802
|
subCommands: {
|
|
715
803
|
send: sendCommand,
|
|
@@ -718,6 +806,7 @@ var main = defineCommand({
|
|
|
718
806
|
quote: quoteCommand,
|
|
719
807
|
skus: skusCommand,
|
|
720
808
|
buy: buyCommand,
|
|
809
|
+
numbers: numbersCommand,
|
|
721
810
|
credits: creditsCommand,
|
|
722
811
|
config: configCommand
|
|
723
812
|
}
|
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 '.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"]}
|
|
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 printNumbersHuman,\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:\n 'Path to the original document (PDF, Word, Excel, PowerPoint, RTF, text, or image). Do not convert to PDF first.',\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\nconst numbersBuyCommand = defineCommand({\n meta: {\n name: 'buy',\n description:\n 'Reserve an inbound fax number and open Stripe Checkout (default 30-day)',\n },\n args: {\n sku: {\n type: 'string',\n description:\n 'inbound_30day (default) | lifetime-basic | lifetime-pro | monthly-basic | annual-basic | monthly-business | annual-business',\n },\n country: {\n type: 'string',\n description: 'US or CA (default US)',\n },\n state: {\n type: 'string',\n description: 'Optional US state or CA province',\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: 'POST',\n path: '/api/v1/numbers',\n json: {\n sku: args.sku ? String(args.sku) : undefined,\n country: args.country ? String(args.country).toUpperCase() : undefined,\n state: args.state ? String(args.state) : undefined,\n },\n })\n if (config.json) printJson(row)\n else printBuyHuman(row as Parameters<typeof printBuyHuman>[0])\n } catch (error) {\n fail(error)\n }\n },\n})\n\nexport const numbersCommand = defineCommand({\n meta: {\n name: 'numbers',\n description: 'List inbound fax numbers, or buy one',\n },\n args: sharedArgs,\n subCommands: {\n buy: numbersBuyCommand,\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/numbers',\n })\n if (config.json) printJson(row)\n else printNumbersHuman(row as Parameters<typeof printNumbersHuman>[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:\n 'Optional original file for a live page count (PDF, Word, Excel, PowerPoint, RTF, text, or image). Do not convert to PDF first.',\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. Send original Word, Excel, PDF, or images — do not convert to PDF first.',\n },\n subCommands: {\n send: sendCommand,\n status: statusCommand,\n list: listCommand,\n quote: quoteCommand,\n skus: skusCommand,\n buy: buyCommand,\n numbers: numbersCommand,\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\nexport function printNumbersHuman(payload: {\n numbers?: Array<{\n phoneNumber?: string\n orderType?: string\n status?: string\n expiresAt?: string | null\n isDefault?: boolean\n }>\n}): void {\n const rows = payload.numbers ?? []\n if (!rows.length) {\n printLine('No inbound numbers. Buy one with: singlefax numbers buy')\n return\n }\n for (const row of rows) {\n printLine(\n [\n row.phoneNumber || '',\n row.orderType || '',\n row.status || '',\n row.expiresAt || 'no expiry',\n row.isDefault ? 'default' : '',\n ]\n .filter((part) => part !== '')\n .join(' '),\n )\n }\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"]}
|