docfast/sdk/nodejs/src/index.ts
DocFast Bot 2e29d564ab
Some checks failed
Build & Deploy to Staging / Build & Deploy to Staging (push) Has been cancelled
feat: add official Node.js and Python SDKs
- Node.js SDK (sdk/nodejs/): TypeScript, zero deps, native fetch, Node 18+
- Python SDK (sdk/python/): sync + async clients via httpx, Python 3.8+
- Both wrap all conversion endpoints (html, markdown, url, templates)
- Proper error handling with DocFastError
- Full README documentation for each
2026-02-20 20:25:43 +00:00

129 lines
3.3 KiB
TypeScript

/**
* DocFast — Official Node.js SDK
* https://docfast.dev
*/
export interface PdfMargin {
top?: string;
bottom?: string;
left?: string;
right?: string;
}
export interface HeaderFooter {
content?: string;
height?: string;
}
export interface PdfOptions {
format?: 'A4' | 'Letter' | 'Legal' | 'A3' | 'A5' | 'Tabloid';
landscape?: boolean;
margin?: PdfMargin;
header?: HeaderFooter;
footer?: HeaderFooter;
scale?: number;
printBackground?: boolean;
}
export interface Template {
id: string;
name: string;
description?: string;
}
export interface DocFastOptions {
baseUrl?: string;
}
export class DocFastError extends Error {
readonly status: number;
readonly code?: string;
constructor(message: string, status: number, code?: string) {
super(message);
this.name = 'DocFastError';
this.status = status;
this.code = code;
}
}
export class DocFast {
private readonly apiKey: string;
private readonly baseUrl: string;
constructor(apiKey: string, options?: DocFastOptions) {
if (!apiKey) throw new Error('API key is required');
this.apiKey = apiKey;
this.baseUrl = options?.baseUrl?.replace(/\/+$/, '') ?? 'https://docfast.dev';
}
private async request(path: string, body: Record<string, unknown>): Promise<Buffer> {
const res = await fetch(`${this.baseUrl}${path}`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
if (!res.ok) {
let message = `HTTP ${res.status}`;
let code: string | undefined;
try {
const err = await res.json() as { error?: string; code?: string };
if (err.error) message = err.error;
code = err.code;
} catch {}
throw new DocFastError(message, res.status, code);
}
const arrayBuffer = await res.arrayBuffer();
return Buffer.from(arrayBuffer);
}
private async requestJson<T>(method: string, path: string): Promise<T> {
const res = await fetch(`${this.baseUrl}${path}`, {
method,
headers: { 'Authorization': `Bearer ${this.apiKey}` },
});
if (!res.ok) {
let message = `HTTP ${res.status}`;
try {
const err = await res.json() as { error?: string };
if (err.error) message = err.error;
} catch {}
throw new DocFastError(message, res.status);
}
return res.json() as Promise<T>;
}
/** Convert HTML to PDF */
async html(html: string, options?: PdfOptions): Promise<Buffer> {
return this.request('/v1/convert/html', { html, options });
}
/** Convert Markdown to PDF */
async markdown(markdown: string, options?: PdfOptions): Promise<Buffer> {
return this.request('/v1/convert/markdown', { markdown, options });
}
/** Convert a URL to PDF */
async url(url: string, options?: PdfOptions): Promise<Buffer> {
return this.request('/v1/convert/url', { url, options });
}
/** List available templates */
async templates(): Promise<Template[]> {
return this.requestJson<Template[]>('GET', '/v1/templates');
}
/** Render a template to PDF */
async renderTemplate(id: string, data: Record<string, unknown>, options?: PdfOptions): Promise<Buffer> {
return this.request(`/v1/templates/${encodeURIComponent(id)}/render`, { data, options });
}
}
export default DocFast;