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
pdfSerializerandpdfWriterare core-embedded. They are write-path (serializeObject,writeDocument) but are declared dependencies ofsrc/pdf.jsitself —pdf.write()is part of the core facade. They cannot be factored out without changingsrc/pdf.js, so they are not part of the composable inventory and the Read-family purity lock is stated against the six modules above.pdfFontEmbedis write-path but not shippable in a bundle. Its four declared dependencies (embedSubsetForPdf,embedFontDescriptor,embedCidSystemInfo,embedToUnicodeBuilder) come frompkg_require(@awacloud/fonts), which the generator's local registry (buildLocalRegistry(modules, extras)) does not see — including it makestopoLocalthrowUnknown 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 intools/generate-bundles.mjs, not insrc/main.js#bundle, soruntime.resolve('pdfRwBundle')is not a supported call. On an@awacloud/fwruntime, register the write modules from themodulesarray (or thedist/build/index.jsbarrel) directly. - Invocability. Every
dist/standaloneroot is invocable with no arguments, the layered ones included: the generator wraps each layered entry in the{ name, register }envelope thatpdf.use()requires, sopdfLargeBundled.factory()orpdfRwBundled.factory()returns a core with its extras registered (core.usedExtension(name)). Thedist/buildroots need an@awacloud/fwruntime to inject their declared dependencies. - Regeneration is idempotent:
bun run gen:bundlesre-emits byte-identical output (no build stamp; every bundle opens with the/*! … */licence banner at byte 0).