Two bundle families — Read and Read+Write — across the four size segments.

This page is a reference page for the committed dist/ build, not a module page: no descriptor is named dist-matrix.

Generated by packages/front/office/pdf/tools/generate-bundles.mjs | Surfaces dist/build/ (fw-mode) + dist/standalone/ (framework-free) | Since 2026-08-04

The committed build is a matrix of two independent axes:

  • size segmentation (frozen): pdf (bare core), pdf-large, pdf-full, pdf-legacy — the extras layered on top of the core;
  • capability family (this page): Read and Read+Write.

Both axes cross with the two path-discriminated surfaces (dist/build/ and dist/standalone/), so every cell ships a .js / .min.js / .meta.json triplet: 8 roots × 2 surfaces × 3 files = 48 files, plus the single dist/build/index.js fw-mode barrel.

Naming scheme

The discriminator is a trailing -rw segment on the root name; the absence of a discriminator marks the Read family. The four historical root names are frozen — renaming them to pdf-read.js etc. would have removed a published name, which the additive doctrine forbids.

Family Root names Path
Read pdf, pdf-large, pdf-full, pdf-legacy @awacloud/pdf/{build,standalone}/<root>.js
Read+Write pdf-rw, pdf-large-rw, pdf-full-rw, pdf-legacy-rw @awacloud/pdf/{build,standalone}/<root>.js

Generated export names follow the surface suffix already in force: pdfRwBundled / pdfRwPackage, pdfLargeRwBundled / pdfLargeRwPackage, and so on.

The matrix

Module counts are the meta.json modules closure (identical on both surfaces); byte sizes are the standalone / build dev sizes.

Segment Read root modules Read+Write root modules Δ
bare core pdf 21 pdf-rw 35 +14
large pdf-large 43 pdf-large-rw 57 +14
full pdf-full 49 pdf-full-rw 63 +14
legacy pdf-legacy 54 pdf-legacy-rw 68 +14

The composition is strictly additive: every Read root is a subset of its Read+Write twin, and adding the Read+Write family left the four Read roots unchanged.

Write inventory

The Read+Write delta is the write inventory — the write-path modules that are separable from the pdf orchestrator core — plus the verification surface:

Module Surface In every -rw root
pdfBuilder builder() yes
pdfIncrementalWriter appendIncremental() yes
pdfXrefStreamWriter writeXrefStreamDocument() yes (required in every -rw root)
pdfEncryptedWriter writeEncryptedDocument() yes
pdfSign sign() yes
pdfDssBuilder buildDss() yes (transitive via pdfSign)

Their closure also pulls in pdfFlate, pdfAesGcm, pdfStandardV4/V5/V6, pdfSigOids, pdfByteRange, pdfSha1 — all classified shared (each exposes both directions, e.g. encode/decode, encryptStream/ decryptStream).

Two documented exclusions

  • pdfSerializer and pdfWriter are core-embedded. They are write-path (serializeObject, writeDocument) but are declared dependencies of src/pdf.js itself — pdf.write() is part of the core facade. They cannot be factored out without changing src/pdf.js, so they are not part of the composable inventory and the Read-family purity lock is stated against the six modules above.
  • pdfFontEmbed is write-path but not shippable in a bundle. Its four declared dependencies (embedSubsetForPdf, embedFontDescriptor, embedCidSystemInfo, embedToUnicodeBuilder) come from pkg_require (@awacloud/fonts), which the generator's local registry (buildLocalRegistry(modules, extras)) does not see — including it makes topoLocal throw Unknown module : embedSubsetForPdf. Font embedding therefore stays an fw-runtime-only capability.

Verification surface

A bundle that can sign() can also verify: every -rw root ships the read-path signature verifier beside the signer.

Module Surface In every -rw root In a Read root
pdfSignature verifySignature(), verifyAllSignatures() yes no

pdfSignature is a read module, not part of the write inventory; the generator lists it separately (VERIFY_SURFACE in tools/generate-bundles.mjs) so the inventory above stays exactly the set of separable write modules.

It rides the Read+Write family, not the Read family, because the four Read roots are byte-frozen: adding it left them, their .meta.json and the dist/build/index.js barrel byte-identical. Its crypto closure already ships through pdfSign, so it adds no @awacloud/fw dependency and no other module — only pdfSignature itself joins each -rw closure. Measured cost per -rw root: +21.8 KB minified (for example build/pdf-rw.min.js 121,323 → 143,156 bytes, +18.0 %; standalone/pdf-legacy-rw.min.js 336,801 → 358,735 bytes, +6.5 %) and +6.4 KB after gzip -9.

An invoked -rw factory exposes the verifier on the returned core:

import { pdfRwBundled } from '@awacloud/pdf/standalone/pdf-rw.js';

const core = pdfRwBundled.factory();
core.usedExtension('pdfSignature');          // → true
const { signatures, timestamps } = core.pdfSignature.verifyAllSignatures(bytes);

Module classification

All 95 src/main.js#modules factories were classified from their resolved API (a fresh ModuleRuntime per module — the shared pdf singleton order-poisons Object.keys):

Class Count Rule
read 68 the returned API only parses, types, walks or verifies existing bytes
write 9 the returned API emits or assembles PDF output
shared 18 the returned API works both directions, or is a pure table/primitive

The per-module table is the composition's contract; it is kept in the source monorepo and is not published. The write and verification modules it selects are listed above.

Notes

  • The Read+Write family is a dist/ composition only. Its four bundle plan entries live in tools/generate-bundles.mjs, not in src/main.js#bundle, so runtime.resolve('pdfRwBundle') is not a supported call. On an @awacloud/fw runtime, register the write modules from the modules array (or the dist/build/index.js barrel) directly.
  • Invocability. Every dist/standalone root is invocable with no arguments, the layered ones included: the generator wraps each layered entry in the { name, register } envelope that pdf.use() requires, so pdfLargeBundled.factory() or pdfRwBundled.factory() returns a core with its extras registered (core.usedExtension(name)). The dist/build roots need an @awacloud/fw runtime to inject their declared dependencies.
  • Regeneration is idempotent: bun run gen:bundles re-emits byte-identical output (no build stamp; every bundle opens with the /*! … */ licence banner at byte 0).

See also