siteforge-pdf 1.0.0
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/LICENSE +21 -0
- package/README.md +183 -0
- package/package.json +43 -0
- package/src/cli.js +179 -0
- package/src/index.d.ts +79 -0
- package/src/index.js +179 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SiteForge
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# SiteForge PDF
|
|
2
|
+
|
|
3
|
+
Official Node.js SDK for [SiteForge PDF](https://pdf.siteforge.build) — simple HTML to PDF conversion API.
|
|
4
|
+
|
|
5
|
+
- ⚡ **100 free conversions/month**
|
|
6
|
+
- 💳 **Pay-as-you-go**: $0.02 per conversion after free tier
|
|
7
|
+
- 🚀 **Fast**: Sub-second conversion times
|
|
8
|
+
- 📄 **Simple**: Just send HTML, get PDF
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install siteforge-pdf
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
const pdf = require('siteforge-pdf');
|
|
20
|
+
const fs = require('fs');
|
|
21
|
+
|
|
22
|
+
// Initialize with your API key
|
|
23
|
+
const client = pdf('sf_pdf_your_api_key');
|
|
24
|
+
|
|
25
|
+
// Convert HTML to PDF
|
|
26
|
+
const buffer = await client.convert('<h1>Hello World</h1>');
|
|
27
|
+
fs.writeFileSync('hello.pdf', buffer);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Get Your API Key
|
|
31
|
+
|
|
32
|
+
1. Sign up at [pdf.siteforge.build](https://pdf.siteforge.build)
|
|
33
|
+
2. Get your API key from the dashboard
|
|
34
|
+
3. Start converting!
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
### Convert HTML
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
const pdf = require('siteforge-pdf');
|
|
42
|
+
const client = pdf('sf_pdf_your_key');
|
|
43
|
+
|
|
44
|
+
// Simple HTML
|
|
45
|
+
const buffer = await client.convert('<h1>Invoice #123</h1><p>Amount: $100</p>');
|
|
46
|
+
|
|
47
|
+
// With options
|
|
48
|
+
const buffer = await client.convert(html, {
|
|
49
|
+
format: 'Letter', // A4, Letter, Legal
|
|
50
|
+
landscape: true, // Landscape orientation
|
|
51
|
+
margin: 'small', // none, small, default, large
|
|
52
|
+
printBackground: true // Include background colors/images
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
fs.writeFileSync('invoice.pdf', buffer);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Convert URL
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
// Convert any public URL to PDF
|
|
62
|
+
const buffer = await client.convertUrl('https://example.com');
|
|
63
|
+
|
|
64
|
+
// With options
|
|
65
|
+
const buffer = await client.convertUrl('https://example.com', {
|
|
66
|
+
format: 'A4',
|
|
67
|
+
waitMs: 1000 // Wait for JS to render
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
fs.writeFileSync('example.pdf', buffer);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Check Usage
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
const usage = await client.usage();
|
|
77
|
+
console.log(usage);
|
|
78
|
+
// {
|
|
79
|
+
// plan: 'free',
|
|
80
|
+
// period: '2024-01',
|
|
81
|
+
// currentMonth: { conversions: 42, ... },
|
|
82
|
+
// limits: { monthly: 100, remaining: 58 }
|
|
83
|
+
// }
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## CLI
|
|
87
|
+
|
|
88
|
+
The package includes a command-line tool:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Set your API key
|
|
92
|
+
export SITEFORGE_PDF_KEY=sf_pdf_your_key
|
|
93
|
+
|
|
94
|
+
# Convert HTML
|
|
95
|
+
siteforge-pdf --html "<h1>Hello</h1>" -o hello.pdf
|
|
96
|
+
|
|
97
|
+
# Convert a file
|
|
98
|
+
siteforge-pdf --file invoice.html -o invoice.pdf
|
|
99
|
+
|
|
100
|
+
# Convert a URL
|
|
101
|
+
siteforge-pdf --url https://example.com -o example.pdf
|
|
102
|
+
|
|
103
|
+
# With options
|
|
104
|
+
siteforge-pdf --html "<h1>Report</h1>" -o report.pdf --landscape --format Letter
|
|
105
|
+
|
|
106
|
+
# Check usage
|
|
107
|
+
siteforge-pdf --usage
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## TypeScript
|
|
111
|
+
|
|
112
|
+
Full TypeScript support included:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import pdf, { SiteForgePDF, ConvertOptions } from 'siteforge-pdf';
|
|
116
|
+
|
|
117
|
+
const client: SiteForgePDF = pdf('sf_pdf_your_key');
|
|
118
|
+
|
|
119
|
+
const options: ConvertOptions = {
|
|
120
|
+
format: 'A4',
|
|
121
|
+
landscape: false
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const buffer: Buffer = await client.convert('<h1>Hello</h1>', options);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Options
|
|
128
|
+
|
|
129
|
+
### Client Options
|
|
130
|
+
|
|
131
|
+
| Option | Type | Default | Description |
|
|
132
|
+
|--------|------|---------|-------------|
|
|
133
|
+
| `baseUrl` | string | `https://pdf.siteforge.build` | API base URL |
|
|
134
|
+
| `timeout` | number | `60000` | Request timeout in ms |
|
|
135
|
+
|
|
136
|
+
### Convert Options
|
|
137
|
+
|
|
138
|
+
| Option | Type | Default | Description |
|
|
139
|
+
|--------|------|---------|-------------|
|
|
140
|
+
| `format` | string | `'A4'` | Page format: A4, Letter, Legal |
|
|
141
|
+
| `landscape` | boolean | `false` | Landscape orientation |
|
|
142
|
+
| `margin` | string | `'default'` | Margin: none, small, default, large |
|
|
143
|
+
| `printBackground` | boolean | `true` | Include background graphics |
|
|
144
|
+
| `waitMs` | number | `0` | Wait before capture (for JS rendering) |
|
|
145
|
+
|
|
146
|
+
## Error Handling
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
const pdf = require('siteforge-pdf');
|
|
150
|
+
const client = pdf('sf_pdf_your_key');
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
const buffer = await client.convert('<h1>Hello</h1>');
|
|
154
|
+
fs.writeFileSync('output.pdf', buffer);
|
|
155
|
+
} catch (err) {
|
|
156
|
+
if (err.statusCode === 401) {
|
|
157
|
+
console.error('Invalid API key');
|
|
158
|
+
} else if (err.statusCode === 429) {
|
|
159
|
+
console.error('Rate limit exceeded');
|
|
160
|
+
} else {
|
|
161
|
+
console.error('Conversion failed:', err.message);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Pricing
|
|
167
|
+
|
|
168
|
+
| Plan | Monthly Conversions | Price |
|
|
169
|
+
|------|---------------------|-------|
|
|
170
|
+
| Free | 100 | $0 |
|
|
171
|
+
| Pay-as-you-go | Unlimited | $0.02 each |
|
|
172
|
+
|
|
173
|
+
Free tier includes a small watermark. Upgrade to PAYG for watermark-free PDFs.
|
|
174
|
+
|
|
175
|
+
## Links
|
|
176
|
+
|
|
177
|
+
- 🌐 [Website](https://pdf.siteforge.build)
|
|
178
|
+
- 📖 [API Docs](https://pdf.siteforge.build/docs)
|
|
179
|
+
- 🐛 [Issues](https://github.com/rmoen/siteforge-pdf-node/issues)
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
MIT © [SiteForge](https://siteforge.build)
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "siteforge-pdf",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official Node.js SDK for SiteForge PDF - HTML to PDF conversion API",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"types": "src/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"siteforge-pdf": "src/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "node test/test.js"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"pdf",
|
|
15
|
+
"html-to-pdf",
|
|
16
|
+
"html2pdf",
|
|
17
|
+
"pdf-generation",
|
|
18
|
+
"siteforge",
|
|
19
|
+
"convert",
|
|
20
|
+
"document",
|
|
21
|
+
"api"
|
|
22
|
+
],
|
|
23
|
+
"author": "SiteForge <support@siteforge.build>",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"homepage": "https://pdf.siteforge.build",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/rmoen/siteforge-pdf-node.git"
|
|
29
|
+
},
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/rmoen/siteforge-pdf-node/issues"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=14.0.0"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"src/index.js",
|
|
38
|
+
"src/index.d.ts",
|
|
39
|
+
"src/cli.js",
|
|
40
|
+
"README.md",
|
|
41
|
+
"LICENSE"
|
|
42
|
+
]
|
|
43
|
+
}
|
package/src/cli.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SiteForge PDF CLI
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* siteforge-pdf --html "<h1>Hello</h1>" -o output.pdf
|
|
8
|
+
* siteforge-pdf --url https://example.com -o output.pdf
|
|
9
|
+
* siteforge-pdf --usage
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const createClient = require('./index');
|
|
15
|
+
|
|
16
|
+
const HELP = `
|
|
17
|
+
SiteForge PDF - HTML to PDF Conversion
|
|
18
|
+
|
|
19
|
+
Usage:
|
|
20
|
+
siteforge-pdf [options]
|
|
21
|
+
|
|
22
|
+
Options:
|
|
23
|
+
--html <string> HTML content to convert
|
|
24
|
+
--file <path> HTML file to convert
|
|
25
|
+
--url <url> URL to convert
|
|
26
|
+
-o, --output <path> Output PDF path (default: output.pdf)
|
|
27
|
+
--format <format> Page format: A4, Letter, Legal (default: A4)
|
|
28
|
+
--landscape Use landscape orientation
|
|
29
|
+
--no-background Disable background graphics
|
|
30
|
+
--usage Show usage statistics
|
|
31
|
+
--key <key> API key (or set SITEFORGE_PDF_KEY env var)
|
|
32
|
+
-h, --help Show this help
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
siteforge-pdf --html "<h1>Hello World</h1>" -o hello.pdf
|
|
36
|
+
siteforge-pdf --file invoice.html -o invoice.pdf
|
|
37
|
+
siteforge-pdf --url https://example.com -o example.pdf --landscape
|
|
38
|
+
siteforge-pdf --usage
|
|
39
|
+
|
|
40
|
+
Get your API key at https://pdf.siteforge.build
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
function parseArgs(args) {
|
|
44
|
+
const opts = {
|
|
45
|
+
output: 'output.pdf',
|
|
46
|
+
format: 'A4',
|
|
47
|
+
landscape: false,
|
|
48
|
+
printBackground: true
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
for (let i = 0; i < args.length; i++) {
|
|
52
|
+
const arg = args[i];
|
|
53
|
+
const next = args[i + 1];
|
|
54
|
+
|
|
55
|
+
switch (arg) {
|
|
56
|
+
case '-h':
|
|
57
|
+
case '--help':
|
|
58
|
+
opts.help = true;
|
|
59
|
+
break;
|
|
60
|
+
case '--html':
|
|
61
|
+
opts.html = next;
|
|
62
|
+
i++;
|
|
63
|
+
break;
|
|
64
|
+
case '--file':
|
|
65
|
+
opts.file = next;
|
|
66
|
+
i++;
|
|
67
|
+
break;
|
|
68
|
+
case '--url':
|
|
69
|
+
opts.url = next;
|
|
70
|
+
i++;
|
|
71
|
+
break;
|
|
72
|
+
case '-o':
|
|
73
|
+
case '--output':
|
|
74
|
+
opts.output = next;
|
|
75
|
+
i++;
|
|
76
|
+
break;
|
|
77
|
+
case '--format':
|
|
78
|
+
opts.format = next;
|
|
79
|
+
i++;
|
|
80
|
+
break;
|
|
81
|
+
case '--landscape':
|
|
82
|
+
opts.landscape = true;
|
|
83
|
+
break;
|
|
84
|
+
case '--no-background':
|
|
85
|
+
opts.printBackground = false;
|
|
86
|
+
break;
|
|
87
|
+
case '--usage':
|
|
88
|
+
opts.usage = true;
|
|
89
|
+
break;
|
|
90
|
+
case '--key':
|
|
91
|
+
opts.key = next;
|
|
92
|
+
i++;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return opts;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function main() {
|
|
101
|
+
const args = process.argv.slice(2);
|
|
102
|
+
|
|
103
|
+
if (args.length === 0) {
|
|
104
|
+
console.log(HELP);
|
|
105
|
+
process.exit(0);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const opts = parseArgs(args);
|
|
109
|
+
|
|
110
|
+
if (opts.help) {
|
|
111
|
+
console.log(HELP);
|
|
112
|
+
process.exit(0);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Get API key
|
|
116
|
+
const apiKey = opts.key || process.env.SITEFORGE_PDF_KEY;
|
|
117
|
+
if (!apiKey) {
|
|
118
|
+
console.error('Error: API key required. Use --key or set SITEFORGE_PDF_KEY env var');
|
|
119
|
+
console.error('Get your key at https://pdf.siteforge.build');
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const client = createClient(apiKey);
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
// Usage check
|
|
127
|
+
if (opts.usage) {
|
|
128
|
+
const usage = await client.usage();
|
|
129
|
+
console.log('\nSiteForge PDF Usage\n');
|
|
130
|
+
console.log(`Plan: ${usage.plan}`);
|
|
131
|
+
console.log(`Period: ${usage.period}`);
|
|
132
|
+
console.log(`Conversions this month: ${usage.currentMonth.conversions}`);
|
|
133
|
+
if (usage.limits.monthly) {
|
|
134
|
+
console.log(`Remaining: ${usage.limits.remaining}/${usage.limits.monthly}`);
|
|
135
|
+
}
|
|
136
|
+
if (usage.plan === 'payg') {
|
|
137
|
+
console.log(`Estimated cost: $${usage.currentMonth.estimatedCost}`);
|
|
138
|
+
}
|
|
139
|
+
console.log(`All-time conversions: ${usage.allTime.conversions}`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Get HTML content
|
|
144
|
+
let html = opts.html;
|
|
145
|
+
if (opts.file) {
|
|
146
|
+
html = fs.readFileSync(opts.file, 'utf8');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Convert
|
|
150
|
+
let buffer;
|
|
151
|
+
const convertOpts = {
|
|
152
|
+
format: opts.format,
|
|
153
|
+
landscape: opts.landscape,
|
|
154
|
+
printBackground: opts.printBackground
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
if (opts.url) {
|
|
158
|
+
console.log(`Converting URL: ${opts.url}`);
|
|
159
|
+
buffer = await client.convertUrl(opts.url, convertOpts);
|
|
160
|
+
} else if (html) {
|
|
161
|
+
console.log('Converting HTML...');
|
|
162
|
+
buffer = await client.convert(html, convertOpts);
|
|
163
|
+
} else {
|
|
164
|
+
console.error('Error: Provide --html, --file, or --url');
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Write output
|
|
169
|
+
const outputPath = path.resolve(opts.output);
|
|
170
|
+
fs.writeFileSync(outputPath, buffer);
|
|
171
|
+
console.log(`✓ PDF saved: ${outputPath} (${(buffer.length / 1024).toFixed(1)} KB)`);
|
|
172
|
+
|
|
173
|
+
} catch (err) {
|
|
174
|
+
console.error(`Error: ${err.message}`);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
main();
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SiteForge PDF - TypeScript Definitions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface ConvertOptions {
|
|
6
|
+
/** Page format: A4, Letter, Legal (default: A4) */
|
|
7
|
+
format?: 'A4' | 'Letter' | 'Legal';
|
|
8
|
+
/** Landscape orientation (default: false) */
|
|
9
|
+
landscape?: boolean;
|
|
10
|
+
/** Margin size (default: 'default') */
|
|
11
|
+
margin?: 'none' | 'small' | 'default' | 'large';
|
|
12
|
+
/** Include background graphics (default: true) */
|
|
13
|
+
printBackground?: boolean;
|
|
14
|
+
/** Wait time before capture in ms (for convertUrl) */
|
|
15
|
+
waitMs?: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ClientOptions {
|
|
19
|
+
/** API base URL (default: https://pdf.siteforge.build) */
|
|
20
|
+
baseUrl?: string;
|
|
21
|
+
/** Request timeout in ms (default: 60000) */
|
|
22
|
+
timeout?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface UsageStats {
|
|
26
|
+
plan: 'free' | 'payg' | 'pro';
|
|
27
|
+
period: string;
|
|
28
|
+
currentMonth: {
|
|
29
|
+
conversions: number;
|
|
30
|
+
totalBytes: number;
|
|
31
|
+
avgProcessingMs: number;
|
|
32
|
+
estimatedCost: string;
|
|
33
|
+
};
|
|
34
|
+
allTime: {
|
|
35
|
+
conversions: number;
|
|
36
|
+
totalBytes: number;
|
|
37
|
+
};
|
|
38
|
+
limits: {
|
|
39
|
+
monthly: number | null;
|
|
40
|
+
remaining: number | null;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface HealthStatus {
|
|
45
|
+
status: 'ok' | 'error';
|
|
46
|
+
service: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export declare class SiteForgePDF {
|
|
50
|
+
constructor(apiKey: string, options?: ClientOptions);
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Convert HTML to PDF
|
|
54
|
+
*/
|
|
55
|
+
convert(html: string, options?: ConvertOptions): Promise<Buffer>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Convert a URL to PDF
|
|
59
|
+
*/
|
|
60
|
+
convertUrl(url: string, options?: ConvertOptions): Promise<Buffer>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get usage statistics
|
|
64
|
+
*/
|
|
65
|
+
usage(): Promise<UsageStats>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Health check
|
|
69
|
+
*/
|
|
70
|
+
health(): Promise<HealthStatus>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Create a SiteForge PDF client
|
|
75
|
+
*/
|
|
76
|
+
declare function createClient(apiKey: string, options?: ClientOptions): SiteForgePDF;
|
|
77
|
+
|
|
78
|
+
export { createClient };
|
|
79
|
+
export default createClient;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SiteForge PDF - Official Node.js SDK
|
|
3
|
+
* https://pdf.siteforge.build
|
|
4
|
+
*
|
|
5
|
+
* Simple HTML to PDF conversion API
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const https = require('https');
|
|
9
|
+
const http = require('http');
|
|
10
|
+
|
|
11
|
+
const DEFAULT_BASE_URL = 'https://pdf.siteforge.build';
|
|
12
|
+
|
|
13
|
+
class SiteForgePDF {
|
|
14
|
+
/**
|
|
15
|
+
* Create a SiteForge PDF client
|
|
16
|
+
* @param {string} apiKey - Your API key (starts with sf_pdf_)
|
|
17
|
+
* @param {object} options - Optional configuration
|
|
18
|
+
* @param {string} options.baseUrl - API base URL (default: https://pdf.siteforge.build)
|
|
19
|
+
* @param {number} options.timeout - Request timeout in ms (default: 60000)
|
|
20
|
+
*/
|
|
21
|
+
constructor(apiKey, options = {}) {
|
|
22
|
+
if (!apiKey) {
|
|
23
|
+
throw new Error('API key is required. Get one at https://pdf.siteforge.build');
|
|
24
|
+
}
|
|
25
|
+
if (!apiKey.startsWith('sf_pdf_')) {
|
|
26
|
+
throw new Error('Invalid API key format. Keys start with sf_pdf_');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.apiKey = apiKey;
|
|
30
|
+
this.baseUrl = options.baseUrl || DEFAULT_BASE_URL;
|
|
31
|
+
this.timeout = options.timeout || 60000;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Make an API request
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
_request(method, path, body = null, expectBinary = false) {
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
const url = new URL(path, this.baseUrl);
|
|
41
|
+
const isHttps = url.protocol === 'https:';
|
|
42
|
+
const client = isHttps ? https : http;
|
|
43
|
+
|
|
44
|
+
const options = {
|
|
45
|
+
hostname: url.hostname,
|
|
46
|
+
port: url.port || (isHttps ? 443 : 80),
|
|
47
|
+
path: url.pathname + url.search,
|
|
48
|
+
method,
|
|
49
|
+
headers: {
|
|
50
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
51
|
+
'Content-Type': 'application/json',
|
|
52
|
+
'User-Agent': 'siteforge-pdf-node/1.0.0'
|
|
53
|
+
},
|
|
54
|
+
timeout: this.timeout
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const req = client.request(options, (res) => {
|
|
58
|
+
const chunks = [];
|
|
59
|
+
|
|
60
|
+
res.on('data', chunk => chunks.push(chunk));
|
|
61
|
+
res.on('end', () => {
|
|
62
|
+
const buffer = Buffer.concat(chunks);
|
|
63
|
+
|
|
64
|
+
if (res.statusCode >= 400) {
|
|
65
|
+
let error;
|
|
66
|
+
try {
|
|
67
|
+
const json = JSON.parse(buffer.toString());
|
|
68
|
+
error = new Error(json.error || `HTTP ${res.statusCode}`);
|
|
69
|
+
} catch {
|
|
70
|
+
error = new Error(`HTTP ${res.statusCode}: ${buffer.toString()}`);
|
|
71
|
+
}
|
|
72
|
+
error.statusCode = res.statusCode;
|
|
73
|
+
reject(error);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (expectBinary) {
|
|
78
|
+
resolve(buffer);
|
|
79
|
+
} else {
|
|
80
|
+
try {
|
|
81
|
+
resolve(JSON.parse(buffer.toString()));
|
|
82
|
+
} catch {
|
|
83
|
+
resolve(buffer.toString());
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
req.on('error', reject);
|
|
90
|
+
req.on('timeout', () => {
|
|
91
|
+
req.destroy();
|
|
92
|
+
reject(new Error('Request timed out'));
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
if (body) {
|
|
96
|
+
req.write(JSON.stringify(body));
|
|
97
|
+
}
|
|
98
|
+
req.end();
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Convert HTML to PDF
|
|
104
|
+
* @param {string} html - HTML content to convert
|
|
105
|
+
* @param {object} options - Conversion options
|
|
106
|
+
* @param {string} options.format - Page format: A4, Letter, Legal (default: A4)
|
|
107
|
+
* @param {boolean} options.landscape - Landscape orientation (default: false)
|
|
108
|
+
* @param {string} options.margin - Margin size: none, small, default, large
|
|
109
|
+
* @param {boolean} options.printBackground - Include background graphics (default: true)
|
|
110
|
+
* @returns {Promise<Buffer>} PDF as a Buffer
|
|
111
|
+
*/
|
|
112
|
+
async convert(html, options = {}) {
|
|
113
|
+
if (!html || typeof html !== 'string') {
|
|
114
|
+
throw new Error('HTML content is required');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const body = {
|
|
118
|
+
html,
|
|
119
|
+
...options
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
return this._request('POST', '/v1/convert', body, true);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Convert a URL to PDF
|
|
127
|
+
* @param {string} url - URL to convert
|
|
128
|
+
* @param {object} options - Conversion options
|
|
129
|
+
* @param {string} options.format - Page format: A4, Letter, Legal (default: A4)
|
|
130
|
+
* @param {boolean} options.landscape - Landscape orientation (default: false)
|
|
131
|
+
* @param {string} options.margin - Margin size: none, small, default, large
|
|
132
|
+
* @param {boolean} options.printBackground - Include background graphics (default: true)
|
|
133
|
+
* @param {number} options.waitMs - Wait time before capture in ms (default: 0)
|
|
134
|
+
* @returns {Promise<Buffer>} PDF as a Buffer
|
|
135
|
+
*/
|
|
136
|
+
async convertUrl(url, options = {}) {
|
|
137
|
+
if (!url || typeof url !== 'string') {
|
|
138
|
+
throw new Error('URL is required');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const body = {
|
|
142
|
+
url,
|
|
143
|
+
...options
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return this._request('POST', '/v1/convert', body, true);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Get usage statistics
|
|
151
|
+
* @returns {Promise<object>} Usage stats including conversions, limits, costs
|
|
152
|
+
*/
|
|
153
|
+
async usage() {
|
|
154
|
+
return this._request('GET', '/v1/usage');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Health check
|
|
159
|
+
* @returns {Promise<object>} Service status
|
|
160
|
+
*/
|
|
161
|
+
async health() {
|
|
162
|
+
return this._request('GET', '/health');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Create a SiteForge PDF client
|
|
168
|
+
* @param {string} apiKey - Your API key
|
|
169
|
+
* @param {object} options - Optional configuration
|
|
170
|
+
* @returns {SiteForgePDF}
|
|
171
|
+
*/
|
|
172
|
+
function createClient(apiKey, options) {
|
|
173
|
+
return new SiteForgePDF(apiKey, options);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Allow both: require('siteforge-pdf')('key') and require('siteforge-pdf').createClient('key')
|
|
177
|
+
module.exports = createClient;
|
|
178
|
+
module.exports.createClient = createClient;
|
|
179
|
+
module.exports.SiteForgePDF = SiteForgePDF;
|