fullbleed 0.1.1 → 0.1.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 CHANGED
@@ -4,17 +4,24 @@ Generate PDFs from static HTML and CSS in Node.js. The package includes the
4
4
  Fullbleed Rust engine compiled to WebAssembly and four font faces, so installing
5
5
  it does not require Python, Rust, a browser, or system fonts. MIT licensed.
6
6
 
7
- This is an optional integration around the unchanged **Fullbleed 2.5.5** engine.
8
- The Node package has its own version, **0.1.1**.
7
+ This is an optional integration around the unchanged **Fullbleed 2.5.6** engine.
8
+ The Node package has its own version, **0.1.3**. Render promises now wait for their
9
+ worker to exit, including after errors, timeouts, and cancellation, so sequential
10
+ calls do not overlap worker lifetimes.
9
11
 
10
12
  ## Install and render
11
13
 
12
- Use Node.js 22 or newer. Install the versioned package from its GitHub release:
14
+ Use Node.js 22 or newer. Install the [npm package](https://www.npmjs.com/package/fullbleed):
13
15
 
14
16
  ```bash
15
- npm install https://github.com/fullbleed-engine/fullbleed-node/releases/download/v0.1.1/fullbleed-0.1.1.tgz
17
+ npm install fullbleed
16
18
  ```
17
19
 
20
+ For a version-pinned installation, use `npm install --save-exact fullbleed@0.1.3`.
21
+ The npm tarball is byte-identical to the verified
22
+ [GitHub release](https://github.com/fullbleed-engine/fullbleed-node/releases/tag/v0.1.3).
23
+ See the [installation verification records](https://github.com/fullbleed-engine/fullbleed-node/tree/main/verification).
24
+
18
25
  Save this as `invoice.mjs` and run `node invoice.mjs`:
19
26
 
20
27
  ```javascript
@@ -57,6 +64,14 @@ npm run example
57
64
  Open `output/invoice/invoice.pdf` and `page-1.png`. The [three-page report
58
65
  sources](examples/report.html) demonstrate pagination, tables, and vector artwork.
59
66
 
67
+ ## Use it in Next.js
68
+
69
+ For a web application, start with the [Next.js PDF download example](examples/nextjs).
70
+ It includes a designed invoice, an App Router handler, production build settings
71
+ for the worker and bundled assets, and a standalone-server verification script.
72
+ The route bounds rendering and returns private PDF attachments from fictional
73
+ data; connect your own authenticated record lookup when adapting it.
74
+
60
75
  ## Fonts and assets
61
76
 
62
77
  Supply file bytes explicitly. Additional fonts are registered alongside the
@@ -107,7 +122,12 @@ native engine.
107
122
  | `allowMissingGlyphs` | Default `false`: reject engine-reported missing glyphs. |
108
123
 
109
124
  Rendering runs in a dedicated worker. Concurrent calls use separate workers and
110
- document state. Bound concurrency in a server according to its available memory;
125
+ document state. The returned promise waits for that worker to exit on success,
126
+ render failure, timeout, or cancellation. Awaiting jobs in sequence therefore
127
+ does not overlap their worker lifetimes. A timeout or abort starts termination;
128
+ settlement includes the time needed to stop the worker.
129
+
130
+ Bound concurrency in a server according to its available memory;
111
131
  each worker's WebAssembly memory has a 512 MiB ceiling. HTML and CSS together are
112
132
  limited to 4,000,000 UTF-8 bytes; supplied fonts and assets together to 64 MiB.
113
133
  Preview images can use substantially more memory than PDF-only rendering.
@@ -143,8 +163,9 @@ arbitrary browser pages.
143
163
 
144
164
  ## Build and verify from source
145
165
 
146
- Contributors need Node.js 22+ and Rust 1.97.0 with the WASI target. Package users
147
- do not need a compiler. Dependencies are pinned in both lockfiles.
166
+ Contributors need Node.js 22+ and Rust 1.97.0 with the WASI target. The independent
167
+ PDF text check also uses Python with the test-only `pypdf==6.19.0` reader. Package
168
+ users do not need a compiler or Python. Dependencies are pinned in both lockfiles.
148
169
 
149
170
  ```bash
150
171
  rustup target add wasm32-wasip1
@@ -154,6 +175,8 @@ npm test
154
175
  npm run check:types
155
176
  npm run verify:native
156
177
  npm run verify:pack
178
+ python -m pip install pypdf==6.19.0
179
+ npm run verify:text
157
180
  ```
158
181
 
159
182
  The build records engine metadata, licenses, and artifact hashes in `dist/`.
@@ -1,4 +1,4 @@
1
- fullbleed 2.5.5 / LICENSE
1
+ fullbleed 2.5.6 / LICENSE
2
2
 
3
3
  MIT License
4
4
 
@@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
23
  SOFTWARE.
24
24
 
25
25
 
26
- fullbleed 2.5.5 / THIRD_PARTY_LICENSES.md
26
+ fullbleed 2.5.6 / THIRD_PARTY_LICENSES.md
27
27
 
28
28
  <!-- SPDX-License-Identifier: MIT -->
29
29
  # Third-Party Licenses
package/dist/build.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "packageVersion": "0.1.1",
3
- "engineVersion": "2.5.5",
4
- "engineSource": "https://crates.io/crates/fullbleed/2.5.5",
2
+ "packageVersion": "0.1.3",
3
+ "engineVersion": "2.5.6",
4
+ "engineSource": "https://crates.io/crates/fullbleed/2.5.6",
5
5
  "target": "wasm32-wasip1",
6
6
  "memoryMaximumBytes": 536870912,
7
7
  "fonts": [
@@ -13,7 +13,7 @@
13
13
  "dependencies": [
14
14
  {
15
15
  "name": "fullbleed",
16
- "version": "2.5.5",
16
+ "version": "2.5.6",
17
17
  "source": "registry+https://github.com/rust-lang/crates.io-index",
18
18
  "license": "MIT"
19
19
  },
@@ -44,12 +44,12 @@
44
44
  ],
45
45
  "files": {
46
46
  "dist/engine.wasm": {
47
- "bytes": 5047938,
48
- "sha256": "60f06871dcd0109f919581f21ba5dac716c2c160094f380d5dba58ec96f0d5ee"
47
+ "bytes": 5053312,
48
+ "sha256": "20bc142538c5acf826b162531ed57541d410b033e3666a827934b89ef2fc84cb"
49
49
  },
50
50
  "dist/THIRD_PARTY_NOTICES.txt": {
51
51
  "bytes": 57660,
52
- "sha256": "f369b7da5c0d54fb0be0917475e5964cfa276cfe3c7c830f7853213592d41ab8"
52
+ "sha256": "4a945a683c5f4be6a4c74b59f45aa1f5e6627022a80addddb6eaf68ed3916d9f"
53
53
  },
54
54
  "assets/fonts/BebasNeue-OFL.txt": {
55
55
  "bytes": 4337,
package/dist/engine.wasm CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fullbleed",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Generate PDFs from HTML and CSS in Node.js with the Fullbleed Rust engine, bundled fonts, and optional PNG previews.",
5
5
  "type": "module",
6
6
  "main": "./src/index.cjs",
@@ -34,7 +34,8 @@
34
34
  "check:types": "tsc -p tsconfig.json",
35
35
  "verify:native": "node tools/verify-native.mjs",
36
36
  "example": "node examples/invoice.mjs",
37
- "verify:pack": "node tools/verify-pack.mjs"
37
+ "verify:pack": "node tools/verify-pack.mjs",
38
+ "verify:text": "python tools/verify-installed-text.py"
38
39
  },
39
40
  "dependencies": {
40
41
  "@bjorn3/browser_wasi_shim": "0.4.2"
@@ -62,7 +63,7 @@
62
63
  "access": "public"
63
64
  },
64
65
  "fullbleed": {
65
- "engineVersion": "2.5.5"
66
+ "engineVersion": "2.5.6"
66
67
  },
67
68
  "devDependencies": {
68
69
  "@types/node": "22.20.5",
package/src/index.cjs CHANGED
@@ -87,13 +87,20 @@ async function renderPdf(options) {
87
87
  if (remaining <= 0) throw new FullbleedError('TIMEOUT', `PDF rendering exceeded ${job.timeoutMs} ms.`);
88
88
  return new Promise((resolve, reject) => {
89
89
  let worker, timer, settled = false;
90
- const finish = (error, result) => {
90
+ const finish = async (error, result) => {
91
91
  if (settled) return;
92
92
  settled = true;
93
93
  clearTimeout(timer);
94
94
  job.signal?.removeEventListener('abort', abort);
95
- const termination = worker?.terminate();
96
- if (termination) termination.catch(() => {});
95
+ // A process 'worker' listener can abort synchronously inside the Worker
96
+ // constructor. Let that constructor assign its handle before cleanup.
97
+ await Promise.resolve();
98
+ try {
99
+ await worker?.terminate();
100
+ } catch (cause) {
101
+ reject(new FullbleedError('WORKER_FAILED', 'Could not stop the rendering worker.', { cause }));
102
+ return;
103
+ }
97
104
  if (error) reject(error); else resolve(result);
98
105
  };
99
106
  const abort = () => finish(aborted());