pdfn 0.6.1 → 0.6.3
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 +30 -6
- package/dist/cli.js +2 -42
- package/dist/cli.js.map +1 -1
- package/package.json +4 -6
package/README.md
CHANGED
|
@@ -26,6 +26,19 @@ npx pdfn dev --open # Start and open browser
|
|
|
26
26
|
| `--open` | `false` | Open browser on start |
|
|
27
27
|
| `--no-open` | - | Don't open browser |
|
|
28
28
|
|
|
29
|
+
**Server API:**
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
POST /v1/generate # HTML → PDF
|
|
33
|
+
GET /health # Health check
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Use with `generate()` by setting `PDFN_HOST`:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
PDFN_HOST=http://localhost:3456 node your-app.js
|
|
40
|
+
```
|
|
41
|
+
|
|
29
42
|
### `pdfn add`
|
|
30
43
|
|
|
31
44
|
Add starter templates to your project.
|
|
@@ -45,11 +58,22 @@ npx pdfn add --list # Show all templates
|
|
|
45
58
|
| `poster` | Event poster (landscape) |
|
|
46
59
|
| `report` | Sales report with charts (requires recharts) |
|
|
47
60
|
|
|
48
|
-
##
|
|
61
|
+
## PDF Generation
|
|
49
62
|
|
|
50
|
-
For
|
|
63
|
+
For PDF generation, choose based on your infrastructure:
|
|
64
|
+
|
|
65
|
+
**Option 1: Local dev server**
|
|
66
|
+
|
|
67
|
+
Use `pdfn dev` for development with `generate()`:
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
import { generate } from '@pdfn/react';
|
|
71
|
+
|
|
72
|
+
// Set PDFN_HOST=http://localhost:3456
|
|
73
|
+
const pdf = await generate(<Invoice />);
|
|
74
|
+
```
|
|
51
75
|
|
|
52
|
-
**Option
|
|
76
|
+
**Option 2: Self-host with Puppeteer/Playwright**
|
|
53
77
|
|
|
54
78
|
Use `render()` to get print-ready HTML, then convert with your own browser:
|
|
55
79
|
|
|
@@ -69,20 +93,20 @@ await browser.close();
|
|
|
69
93
|
|
|
70
94
|
Works with Puppeteer, Playwright, Browserless, @sparticuz/chromium, or any Chromium setup.
|
|
71
95
|
|
|
72
|
-
**Option
|
|
96
|
+
**Option 3: pdfn Cloud**
|
|
73
97
|
|
|
74
98
|
Let pdfn manage the browser infrastructure:
|
|
75
99
|
|
|
76
100
|
```tsx
|
|
77
101
|
import { generate } from '@pdfn/react';
|
|
78
102
|
|
|
79
|
-
// Set PDFN_API_KEY
|
|
103
|
+
// Set PDFN_API_KEY=pdfn_live_...
|
|
80
104
|
const pdf = await generate(<Invoice />);
|
|
81
105
|
```
|
|
82
106
|
|
|
83
107
|
Get your API key at [console.pdfn.dev](https://console.pdfn.dev).
|
|
84
108
|
|
|
85
|
-
**
|
|
109
|
+
**All options produce identical PDFs** — same templates, same output.
|
|
86
110
|
|
|
87
111
|
## License
|
|
88
112
|
|
package/dist/cli.js
CHANGED
|
@@ -1463,7 +1463,6 @@ import chokidar from "chokidar";
|
|
|
1463
1463
|
import { createServer as createHttpServer } from "http";
|
|
1464
1464
|
import { spawn } from "child_process";
|
|
1465
1465
|
import puppeteer2 from "puppeteer";
|
|
1466
|
-
import multer from "multer";
|
|
1467
1466
|
|
|
1468
1467
|
// src/server/base.ts
|
|
1469
1468
|
import express from "express";
|
|
@@ -1826,7 +1825,7 @@ function createBaseServer(options = {}) {
|
|
|
1826
1825
|
res.on("finish", () => {
|
|
1827
1826
|
const duration = performance.now() - start;
|
|
1828
1827
|
let extra;
|
|
1829
|
-
if (req.path === "/generate" && res.statusCode === 200) {
|
|
1828
|
+
if (req.path === "/v1/generate" && res.statusCode === 200) {
|
|
1830
1829
|
const pages = res.getHeader("X-PDFN-Page-Count");
|
|
1831
1830
|
const size = Number(res.getHeader("X-PDFN-PDF-Size")) || 0;
|
|
1832
1831
|
const sizeKB = (size / 1024).toFixed(1);
|
|
@@ -1850,7 +1849,7 @@ function createBaseServer(options = {}) {
|
|
|
1850
1849
|
});
|
|
1851
1850
|
});
|
|
1852
1851
|
app.post(
|
|
1853
|
-
"/generate",
|
|
1852
|
+
"/v1/generate",
|
|
1854
1853
|
createGenerateHandler(browserManager, {
|
|
1855
1854
|
timeout,
|
|
1856
1855
|
onSuccess: options.onSuccess,
|
|
@@ -3257,45 +3256,6 @@ async function startDevServer(options) {
|
|
|
3257
3256
|
res.status(500).json({ error: `Error generating PDF: ${error}` });
|
|
3258
3257
|
}
|
|
3259
3258
|
});
|
|
3260
|
-
const upload = multer({ storage: multer.memoryStorage() });
|
|
3261
|
-
app.post(
|
|
3262
|
-
"/forms/chromium/convert/html",
|
|
3263
|
-
upload.any(),
|
|
3264
|
-
async (req, res) => {
|
|
3265
|
-
try {
|
|
3266
|
-
const files = req.files;
|
|
3267
|
-
const htmlFile = files?.find(
|
|
3268
|
-
(f) => f.originalname === "index.html" || f.fieldname === "files"
|
|
3269
|
-
);
|
|
3270
|
-
if (!htmlFile) {
|
|
3271
|
-
res.status(400).send("Missing index.html file");
|
|
3272
|
-
return;
|
|
3273
|
-
}
|
|
3274
|
-
const html = htmlFile.buffer.toString("utf-8");
|
|
3275
|
-
const result = await browserManager.withPage(async (page) => {
|
|
3276
|
-
return generatePdf(page, html, { timeout: 3e4 });
|
|
3277
|
-
});
|
|
3278
|
-
const { metrics } = result;
|
|
3279
|
-
console.log(
|
|
3280
|
-
chalk.green(" \u2713"),
|
|
3281
|
-
chalk.dim("API \u2192"),
|
|
3282
|
-
"PDF",
|
|
3283
|
-
chalk.dim("\u2022"),
|
|
3284
|
-
chalk.cyan(`${metrics.total}ms`),
|
|
3285
|
-
chalk.dim("\u2022"),
|
|
3286
|
-
formatBytes(metrics.pdfSize),
|
|
3287
|
-
chalk.dim(`\u2022 ${metrics.pageCount} page${metrics.pageCount > 1 ? "s" : ""}`)
|
|
3288
|
-
);
|
|
3289
|
-
res.setHeader("Content-Type", "application/pdf");
|
|
3290
|
-
res.send(result.buffer);
|
|
3291
|
-
} catch (error) {
|
|
3292
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3293
|
-
console.log(chalk.red(" \u2717"), chalk.dim("API \u2192"), chalk.red("PDF generation failed"));
|
|
3294
|
-
console.error(chalk.dim(" "), message);
|
|
3295
|
-
res.status(500).send(message);
|
|
3296
|
-
}
|
|
3297
|
-
}
|
|
3298
|
-
);
|
|
3299
3259
|
await new Promise((resolve3, reject) => {
|
|
3300
3260
|
server.on("error", (err) => {
|
|
3301
3261
|
if (err.code === "EADDRINUSE") {
|