Skip to content

feat: add standalone timestamp and validation data APIs#77

Merged
Mythie merged 3 commits into
mainfrom
feat/add-validation-data-to-api
Jun 12, 2026
Merged

feat: add standalone timestamp and validation data APIs#77
Mythie merged 3 commits into
mainfrom
feat/add-validation-data-to-api

Conversation

@Mythie

@Mythie Mythie commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Add PDF.addTimestamp(), addValidationData(), and addArchivalData()
for multi-signer PAdES flows: upgrade existing B-T signatures to
B-LT/B-LTA after the fact instead of only at signing time.

Refactor signature field lookup into prepareSignatureField() with
support for reusing pre-allocated fields, and switch field errors
to typed SignatureError codes.

Add PDF.addTimestamp(), addValidationData(), and addArchivalData()
for multi-signer PAdES flows: upgrade existing B-T signatures to
B-LT/B-LTA after the fact instead of only at signing time.

Refactor signature field lookup into prepareSignatureField() with
support for reusing pre-allocated fields, and switch field errors
to typed SignatureError codes.
@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
core Ready Ready Preview, Comment Jun 12, 2026 4:37am

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

Comparison

Load PDF

Benchmark Mean p99 RME Samples
libpdf 2.14ms 2.95ms ±1.4% 234
pdf-lib 39.21ms 41.48ms ±3.0% 13
@cantoo/pdf-lib 38.52ms 42.92ms ±2.5% 14

Create blank PDF

Benchmark Mean p99 RME Samples
libpdf 48μs 109μs ±1.4% 10512
pdf-lib 308μs 1.24ms ±2.5% 1624
@cantoo/pdf-lib 334μs 1.55ms ±2.9% 1498

Add 10 pages

Benchmark Mean p99 RME Samples
libpdf 105μs 191μs ±0.9% 4750
pdf-lib 428μs 1.82ms ±3.2% 1172
@cantoo/pdf-lib 384μs 2.19ms ±4.1% 1301

Draw 50 rectangles

Benchmark Mean p99 RME Samples
libpdf 324μs 795μs ±1.3% 1544
pdf-lib 1.27ms 4.51ms ±6.7% 395
@cantoo/pdf-lib 1.60ms 4.21ms ±5.2% 312

Load and save PDF

Benchmark Mean p99 RME Samples
libpdf 2.27ms 3.88ms ±2.1% 221
pdf-lib 76.45ms 86.19ms ±4.0% 10
@cantoo/pdf-lib 143.49ms 154.10ms ±2.2% 10

Load, modify, and save PDF

Benchmark Mean p99 RME Samples
libpdf 47.95ms 53.85ms ±5.9% 11
pdf-lib 73.17ms 79.31ms ±3.1% 10
@cantoo/pdf-lib 142.50ms 149.53ms ±1.8% 10

Extract single page from 100-page PDF

Benchmark Mean p99 RME Samples
libpdf 3.40ms 3.94ms ±0.7% 147
pdf-lib 8.74ms 12.77ms ±2.0% 58
@cantoo/pdf-lib 9.13ms 11.29ms ±1.7% 55

Split 100-page PDF into single-page PDFs

Benchmark Mean p99 RME Samples
libpdf 37.06ms 41.85ms ±3.3% 14
pdf-lib 70.02ms 75.63ms ±3.7% 8
@cantoo/pdf-lib 73.76ms 80.60ms ±5.2% 7

Split 2000-page PDF into single-page PDFs (0.9MB)

Benchmark Mean p99 RME Samples
libpdf 692.25ms 692.25ms ±0.0% 1
pdf-lib 1.31s 1.31s ±0.0% 1
@cantoo/pdf-lib 1.40s 1.40s ±0.0% 1

Copy 10 pages between documents

Benchmark Mean p99 RME Samples
libpdf 4.33ms 4.96ms ±0.9% 116
pdf-lib 11.43ms 13.38ms ±1.3% 44
@cantoo/pdf-lib 12.78ms 13.58ms ±1.0% 40

Merge 2 x 100-page PDFs

Benchmark Mean p99 RME Samples
libpdf 14.60ms 16.19ms ±1.2% 35
pdf-lib 51.15ms 52.11ms ±0.5% 10
@cantoo/pdf-lib 60.54ms 61.13ms ±0.7% 9

Fill FINTRAC form fields

Benchmark Mean p99 RME Samples
libpdf 20.62ms 33.98ms ±6.3% 25
pdf-lib 28.24ms 34.36ms ±3.9% 18
@cantoo/pdf-lib 29.56ms 34.58ms ±4.1% 17

Fill and flatten FINTRAC form

Benchmark Mean p99 RME Samples
libpdf 16.39ms 20.57ms ±3.0% 31
pdf-lib FAILED - - 0
@cantoo/pdf-lib 32.03ms 40.06ms ±4.7% 16
Copying

Copy pages between documents

Benchmark Mean p99 RME Samples
copy 1 page 991μs 1.91ms ±2.1% 505
copy 10 pages from 100-page PDF 4.38ms 5.64ms ±1.7% 115
copy all 100 pages 7.49ms 10.77ms ±1.7% 67

Duplicate pages within same document

Benchmark Mean p99 RME Samples
duplicate page 0 937μs 1.31ms ±0.8% 534
duplicate all pages (double the document) 930μs 1.26ms ±0.6% 538

Merge PDFs

Benchmark Mean p99 RME Samples
merge 2 small PDFs 1.46ms 2.24ms ±1.4% 343
merge 10 small PDFs 7.32ms 10.26ms ±1.5% 69
merge 2 x 100-page PDFs 14.07ms 19.03ms ±2.2% 36
Drawing

benchmarks/drawing.bench.ts

Benchmark Mean p99 RME Samples
draw 100 rectangles 643μs 1.68ms ±2.8% 778
draw 100 circles 884μs 1.76ms ±1.6% 567
draw 100 lines 545μs 1.10ms ±1.2% 919
draw 100 text lines (standard font) 1.57ms 2.57ms ±1.5% 319
create 10 pages with mixed content 1.39ms 2.26ms ±1.8% 360
Forms

benchmarks/forms.bench.ts

Benchmark Mean p99 RME Samples
get form fields 2.89ms 5.20ms ±2.9% 173
fill text fields 11.48ms 16.57ms ±3.9% 44
read field values 2.68ms 4.82ms ±2.3% 187
flatten form 7.67ms 9.50ms ±1.2% 66
Loading

benchmarks/loading.bench.ts

Benchmark Mean p99 RME Samples
load small PDF (888B) 51μs 119μs ±1.1% 9737
load medium PDF (19KB) 82μs 124μs ±0.5% 6119
load form PDF (116KB) 1.21ms 1.78ms ±1.0% 414
load heavy PDF (9.9MB) 2.10ms 2.94ms ±1.2% 238
Saving

benchmarks/saving.bench.ts

Benchmark Mean p99 RME Samples
save unmodified (19KB) 93μs 242μs ±1.0% 5397
save with modifications (19KB) 739μs 1.42ms ±1.6% 677
incremental save (19KB) 130μs 287μs ±0.9% 3856
save heavy PDF (9.9MB) 2.07ms 2.59ms ±0.8% 242
incremental save heavy PDF (9.9MB) 7.51ms 8.82ms ±3.3% 67
Splitting

Extract single page

Benchmark Mean p99 RME Samples
extractPages (1 page from small PDF) 1.03ms 2.60ms ±3.2% 487
extractPages (1 page from 100-page PDF) 3.23ms 3.83ms ±1.1% 155
extractPages (1 page from 2000-page PDF) 49.83ms 50.34ms ±0.6% 11

Split into single-page PDFs

Benchmark Mean p99 RME Samples
split 100-page PDF (0.1MB) 36.85ms 41.57ms ±2.8% 14
split 2000-page PDF (0.9MB) 659.91ms 659.91ms ±0.0% 1

Batch page extraction

Benchmark Mean p99 RME Samples
extract first 10 pages from 2000-page PDF 51.27ms 52.96ms ±0.9% 10
extract first 100 pages from 2000-page PDF 55.31ms 56.20ms ±0.9% 10
extract every 10th page from 2000-page PDF (200 pages) 60.05ms 62.38ms ±1.4% 9
Environment
  • Runner: Linux (X64)
  • Runtime: Bun 1.3.14

Results are machine-dependent.

Mythie added 2 commits June 12, 2026 14:34
Tagged PDFs reference widget annotations from the structure tree via
/OBJR entries and the /ParentTree. Flatten left these intact, keeping
the removed widgets reachable so full-save GC wrote all the orphaned
field objects back into the output.

Remove /OBJR kids and stale /ParentTree entries for flattened widgets
while preserving references to non-widget annotations.
@Mythie Mythie merged commit 18766b8 into main Jun 12, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant