@embedpdf/plugin-stamp 3.0.0-next.0 → 3.0.0-next.10

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/dist/index.cjs CHANGED
@@ -125,7 +125,7 @@ function createStampCapability(ctx, config = {}) {
125
125
  const doc = await openAssetDocument(new Uint8Array(resolved.bytes));
126
126
  let imported;
127
127
  try {
128
- if (!doc.pieceInfo || !doc.pages.extract) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.NotImplemented, "[stamp] canonical PDF libraries need an asset engine with pieceInfo and pages.extract");
128
+ if (!doc.pieceInfo) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.NotImplemented, "[stamp] canonical PDF libraries need an asset engine with pieceInfo");
129
129
  const snapshot = await doc.pages.list();
130
130
  if (snapshot.pageCount === 0) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, "[stamp] a canonical stamp library PDF must contain at least one page");
131
131
  const pages = snapshot.pages.map((layout) => {
@@ -246,7 +246,6 @@ function createStampCapability(ctx, config = {}) {
246
246
  const doc = await openAssetDocument(canonicalBytes);
247
247
  let appended;
248
248
  try {
249
- if (!doc.pages.insert || !doc.pages.extract) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.NotImplemented, "[stamp] appending to a canonical library needs pages.insert and pages.extract");
250
249
  const result = await doc.pages.insert(new Uint8Array(resolved.bytes));
251
250
  if (result.insertedPageObjectNumbers.length !== 1) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, "[stamp] a canonical library asset must be a single-page PDF");
252
251
  const pageObjectNumber = result.insertedPageObjectNumbers[0];
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["EngineError","EngineErrorCode","AnnotationToken"],"sources":["../src/capability.ts","../src/reducer.ts","../src/types.ts","../src/stamp.plugin.ts"],"sourcesContent":["import {\n EngineError,\n EngineErrorCode,\n resolveBinarySource,\n sniffBinaryMetadata,\n type BinarySource,\n type DocumentHandle,\n type Engine,\n type PageImageHandle,\n type PieceInfoEntry,\n type PieceInfoPatch,\n} from '@embedpdf/engine-core/runtime';\nimport { type PluginContext } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation';\nimport { createFormScriptingController, type FormCommitResult } from '@embedpdf/plugin-form';\n\nimport type {\n AddAssetInput,\n ImportLibraryOptions,\n StampAction,\n StampAsset,\n StampAssetPreview,\n StampCapability,\n StampConfig,\n StampLibrary,\n StampAssetKind,\n StampState,\n} from './types';\n\nconst DEFAULT_PREVIEW_WIDTH = 256;\nconst LIBRARY_PIECEINFO_APP = 'EMBD_StampLibrary';\nconst STAMP_PIECEINFO_APP = 'EMBD_Stamp';\nconst STAMP_SCHEMA_VERSION = 1;\n\n/** Session-unique ids. Assets are session-scoped for now (no persistence),\n * so a timestamp + counter is enough — durable ids come with the store port. */\nlet seq = 0;\nconst uid = (prefix: string): string =>\n `${prefix}-${Date.now().toString(36)}-${(seq++).toString(36)}`;\n\nconst entryString = (entries: Record<string, PieceInfoEntry>, key: string): string | undefined => {\n const entry = entries[key];\n return entry?.type === 'string' && entry.value.length > 0 ? entry.value : undefined;\n};\n\nconst entryName = (entries: Record<string, PieceInfoEntry>, key: string): string | undefined => {\n const entry = entries[key];\n return entry?.type === 'name' && entry.value.length > 0 ? entry.value : undefined;\n};\n\nconst entryStringArray = (\n entries: Record<string, PieceInfoEntry>,\n key: string,\n): string[] | undefined => {\n const entry = entries[key];\n return entry?.type === 'string-array' ? [...entry.value] : undefined;\n};\n\nconst kindToPdfName = (kind: StampAssetKind): string =>\n kind === 'signature' ? 'Signature' : kind === 'initials' ? 'Initials' : 'Stamp';\n\nconst kindFromPdfName = (name: string | undefined): StampAssetKind | undefined => {\n switch (name?.toLowerCase()) {\n case 'stamp':\n return 'stamp';\n case 'signature':\n return 'signature';\n case 'initials':\n return 'initials';\n default:\n return undefined;\n }\n};\n\nconst metadataPatch = (\n id: string,\n name: string,\n kind: StampAssetKind,\n subject?: string,\n categories?: readonly string[],\n): PieceInfoPatch => ({\n Version: STAMP_SCHEMA_VERSION,\n Id: id,\n Name: name,\n Kind: { name: kindToPdfName(kind) },\n Subject: subject ?? null,\n Categories: categories ?? null,\n});\n\nconst libraryMetadataPatch = (\n id: string,\n name: string,\n categories?: readonly string[],\n): PieceInfoPatch => ({\n Version: STAMP_SCHEMA_VERSION,\n Id: id,\n Name: name,\n Kind: { name: 'StampLibrary' },\n Categories: categories ?? null,\n});\n\nexport function createStampCapability(\n ctx: PluginContext<StampState, StampAction>,\n config: StampConfig = {},\n): StampCapability {\n /** Binary sidecar of the serializable store: asset bytes + cached preview,\n * keyed by asset id. The reducer never sees these (kernel rule 1). */\n const binaries = new Map<string, { bytes: Uint8Array; preview: StampAssetPreview | null }>();\n /** The durable source of truth for a canonical library. Asset PDFs above\n * are derived page extractions; this map owns the rewritten whole PDF. */\n const libraryBinaries = new Map<string, Uint8Array>();\n /** Whole-PDF rewrites must be serialized per library or two concurrent\n * appends could both start from the same bytes and lose one page. */\n const libraryMutationTails = new Map<string, Promise<void>>();\n\n const mutateLibrary = <T>(libraryId: string, mutation: () => Promise<T>): Promise<T> => {\n const previous = libraryMutationTails.get(libraryId) ?? Promise.resolve();\n const result = previous.then(mutation);\n const tail = result.then(\n () => undefined,\n () => undefined,\n );\n libraryMutationTails.set(libraryId, tail);\n return result.finally(() => {\n if (libraryMutationTails.get(libraryId) === tail) libraryMutationTails.delete(libraryId);\n });\n };\n\n // The ASSET ENGINE port. A configured factory is called (and memoized) on\n // the first import, not at viewer start; a configured instance is used\n // as-is; nothing configured falls back to the kernel's engine — correct for\n // local deployments, and rejected with an actionable error by cloud engines\n // at the first `open({ kind: 'bytes' })`.\n let assetEngineRef: Engine | Promise<Engine> | null = null;\n const assetEngine = (): Engine | Promise<Engine> => {\n if (!assetEngineRef) {\n const cfg = config.assetEngine;\n assetEngineRef = !cfg ? ctx.engine : typeof cfg === 'function' ? cfg() : cfg;\n }\n return assetEngineRef;\n };\n\n const openAssetDocument = async (\n bytes: Uint8Array,\n identity?: DocumentHandle['security']['identity'],\n ): Promise<DocumentHandle> => {\n try {\n return await (\n await assetEngine()\n ).open(\n { kind: 'bytes', id: uid('stamp-import'), bytes },\n { scope: ['*'], ...(identity ? { identity } : {}) },\n );\n } catch (err) {\n // A cloud kernel engine rejects 'bytes' with InvalidArg — turn the\n // generic contract error into the configuration fix.\n if (!config.assetEngine && EngineError.is(err, EngineErrorCode.InvalidArg)) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n \"[stamp] importing a library PDF needs an engine that can open local bytes, and this viewer's engine cannot (cloud). Pass stampPlugin({ assetEngine: () => import('@embedpdf/engine').then((m) => m.createLocalEngine()) }) — it loads lazily, on first import.\",\n );\n }\n throw err;\n }\n };\n\n /** Import-time preview render → bytes. The asset engine is local by\n * definition, so the image source is always inline bytes. */\n const imageToPreview = (image: PageImageHandle): StampAssetPreview => {\n if (image.source.kind !== 'bytes') {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] asset engine returned a URL-sourced render; asset engines must be local',\n );\n }\n return { bytes: image.source.bytes, mimeType: image.contentType };\n };\n\n const allocateId = (\n preferred: string | undefined,\n prefix: string,\n taken: Set<string>,\n ): string => {\n let id = preferred;\n if (!id || taken.has(id)) {\n do id = uid(prefix);\n while (taken.has(id));\n }\n taken.add(id);\n return id;\n };\n\n const createLooseLibrary = (name: string): string => {\n const id = uid('stamp-lib');\n ctx.dispatch({\n type: 'LIBRARY_ADDED',\n library: { id, name, storage: 'loose', assetIds: [] },\n });\n return id;\n };\n\n const importLibraryPdf = async (\n source: BinarySource,\n opts?: ImportLibraryOptions,\n ): Promise<string> => {\n const resolved = await resolveBinarySource(source);\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (meta?.mimeType !== 'application/pdf') {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] importLibraryPdf needs PDF bytes (use addAsset for a raster image)',\n );\n }\n const doc = await openAssetDocument(new Uint8Array(resolved.bytes));\n let imported:\n | {\n library: StampLibrary;\n canonicalBytes: Uint8Array;\n assets: Array<{\n asset: StampAsset;\n bytes: Uint8Array;\n preview: StampAssetPreview;\n }>;\n }\n | undefined;\n try {\n if (!doc.pieceInfo || !doc.pages.extract) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] canonical PDF libraries need an asset engine with pieceInfo and pages.extract',\n );\n }\n const snapshot = await doc.pages.list();\n if (snapshot.pageCount === 0) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] a canonical stamp library PDF must contain at least one page',\n );\n }\n\n // Discover and validate every required service before the first write.\n const pages = snapshot.pages.map((layout) => {\n const handle = doc.page(layout.pageObjectNumber);\n if (!handle.pieceInfo) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] canonical PDF libraries need page pieceInfo support',\n );\n }\n return {\n layout,\n handle,\n metadata: null as Awaited<ReturnType<typeof handle.pieceInfo.read>>,\n };\n });\n\n const catalogMetadata = await doc.pieceInfo.read(LIBRARY_PIECEINFO_APP);\n for (const page of pages) {\n page.metadata = await page.handle.pieceInfo!.read(STAMP_PIECEINFO_APP);\n }\n\n const state = ctx.getState();\n const takenLibraryIds = new Set(Object.keys(state.libraries));\n const takenAssetIds = new Set(Object.keys(state.assets));\n const catalogEntries = catalogMetadata?.entries ?? {};\n const libraryId = allocateId(entryString(catalogEntries, 'Id'), 'stamp-lib', takenLibraryIds);\n const libraryName = opts?.name ?? entryString(catalogEntries, 'Name') ?? 'Stamps';\n const libraryCategories = opts?.categories ?? entryStringArray(catalogEntries, 'Categories');\n\n const descriptors = pages.map(({ layout, handle, metadata: pageMetadata }) => {\n const entries = pageMetadata?.entries ?? {};\n const id = allocateId(entryString(entries, 'Id'), 'stamp', takenAssetIds);\n const kind = opts?.kind ?? kindFromPdfName(entryName(entries, 'Kind')) ?? 'stamp';\n return {\n handle,\n asset: {\n id,\n libraryId,\n kind,\n name:\n opts?.assetName?.(layout.index) ??\n entryString(entries, 'Name') ??\n `Stamp ${layout.index + 1}`,\n size: { width: layout.size.width, height: layout.size.height },\n format: 'pdf' as const,\n pageObjectNumber: layout.pageObjectNumber,\n subject: entryString(entries, 'Subject'),\n categories: entryStringArray(entries, 'Categories'),\n },\n };\n });\n\n await doc.pieceInfo.update(\n LIBRARY_PIECEINFO_APP,\n libraryMetadataPatch(libraryId, libraryName, libraryCategories),\n );\n\n const assets: NonNullable<typeof imported>['assets'] = [];\n for (const descriptor of descriptors) {\n const { asset, handle } = descriptor;\n await handle.pieceInfo!.update(\n STAMP_PIECEINFO_APP,\n metadataPatch(asset.id, asset.name, asset.kind, asset.subject, asset.categories),\n );\n // One canonical page → one derived placement PDF plus a transparent\n // preview. Extract after metadata so the cache carries the same id.\n const bytes = await doc.pages.extract([asset.pageObjectNumber!]);\n const image = await handle.render.image({\n viewport: { kind: 'width', width: config.previewWidth ?? DEFAULT_PREVIEW_WIDTH },\n background: 'transparent',\n includeAnnotations: true,\n format: 'png',\n });\n assets.push({ asset, bytes, preview: imageToPreview(image) });\n }\n\n imported = {\n library: {\n id: libraryId,\n name: libraryName,\n storage: 'canonical-pdf',\n categories: libraryCategories,\n assetIds: [],\n },\n canonicalBytes: await doc.download(),\n assets,\n };\n } finally {\n await doc.close();\n }\n\n libraryBinaries.set(imported.library.id, imported.canonicalBytes);\n ctx.dispatch({ type: 'LIBRARY_ADDED', library: imported.library });\n for (const { asset, bytes, preview } of imported.assets) {\n binaries.set(asset.id, { bytes, preview });\n ctx.dispatch({ type: 'ASSET_ADDED', asset });\n }\n return imported.library.id;\n };\n\n const addAsset = async (input: AddAssetInput): Promise<string> => {\n const targetLibrary = input.libraryId\n ? (ctx.getState().libraries[input.libraryId] ?? null)\n : null;\n if (input.libraryId && !targetLibrary) {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] unknown library '${input.libraryId}'`,\n );\n }\n const resolved = await resolveBinarySource(input.source);\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (!meta) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] asset source must be PNG, JPEG, or single-page PDF bytes',\n );\n }\n const isPdf = meta.mimeType === 'application/pdf';\n\n let suppliedPreview: StampAssetPreview | null = null;\n if (input.preview) {\n const preview = await resolveBinarySource(input.preview);\n suppliedPreview = {\n bytes: new Uint8Array(preview.bytes),\n mimeType: preview.mimeType ?? 'image/png',\n };\n }\n\n if (targetLibrary?.storage === 'canonical-pdf') {\n if (!isPdf) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] raster assets cannot be appended to a canonical PDF library',\n );\n }\n return mutateLibrary(targetLibrary.id, async () => {\n const liveLibrary = ctx.getState().libraries[targetLibrary.id];\n if (liveLibrary?.storage !== 'canonical-pdf') {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] canonical library '${targetLibrary.id}' no longer exists`,\n );\n }\n const canonicalBytes = libraryBinaries.get(liveLibrary.id);\n if (!canonicalBytes) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] canonical bytes are missing for library '${liveLibrary.id}'`,\n );\n }\n\n const assetId = uid('stamp');\n const doc = await openAssetDocument(canonicalBytes);\n let appended:\n | {\n asset: StampAsset;\n bytes: Uint8Array;\n preview: StampAssetPreview;\n canonical: Uint8Array;\n }\n | undefined;\n try {\n if (!doc.pages.insert || !doc.pages.extract) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] appending to a canonical library needs pages.insert and pages.extract',\n );\n }\n const result = await doc.pages.insert(new Uint8Array(resolved.bytes));\n if (result.insertedPageObjectNumbers.length !== 1) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] a canonical library asset must be a single-page PDF',\n );\n }\n const pageObjectNumber = result.insertedPageObjectNumbers[0];\n const layout = result.layout.pages.find(\n (candidate) => candidate.pageObjectNumber === pageObjectNumber,\n );\n const page = doc.page(pageObjectNumber);\n if (!layout || !page.pieceInfo) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] canonical PDF libraries need page layout and pieceInfo support',\n );\n }\n const asset: StampAsset = {\n id: assetId,\n libraryId: liveLibrary.id,\n kind: input.kind ?? 'stamp',\n name: input.name,\n size: { width: layout.size.width, height: layout.size.height },\n format: 'pdf',\n pageObjectNumber,\n subject: input.subject,\n categories: input.categories,\n };\n await page.pieceInfo.update(\n STAMP_PIECEINFO_APP,\n metadataPatch(asset.id, asset.name, asset.kind, asset.subject, asset.categories),\n );\n const bytes = await doc.pages.extract([pageObjectNumber]);\n let preview = suppliedPreview;\n if (!preview) {\n preview = imageToPreview(\n await page.render.image({\n viewport: { kind: 'width', width: config.previewWidth ?? DEFAULT_PREVIEW_WIDTH },\n background: 'transparent',\n includeAnnotations: true,\n format: 'png',\n }),\n );\n }\n appended = { asset, bytes, preview, canonical: await doc.download() };\n } finally {\n await doc.close();\n }\n\n libraryBinaries.set(liveLibrary.id, appended.canonical);\n binaries.set(appended.asset.id, { bytes: appended.bytes, preview: appended.preview });\n ctx.dispatch({ type: 'ASSET_ADDED', asset: appended.asset });\n return appended.asset.id;\n });\n }\n\n const size =\n input.size ?? ('width' in meta ? { width: meta.width, height: meta.height } : null);\n if (!size) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] a PDF asset needs `size` (its page size in points) — PDF bytes carry no sniffable dimensions',\n );\n }\n let preview = suppliedPreview;\n if (!preview && !isPdf) {\n preview = { bytes: new Uint8Array(resolved.bytes), mimeType: meta.mimeType };\n }\n const commitLooseAsset = (libraryId: string): string => {\n const asset: StampAsset = {\n id: uid('stamp'),\n libraryId,\n kind: input.kind ?? 'stamp',\n name: input.name,\n size,\n format: isPdf ? 'pdf' : meta.mimeType === 'image/png' ? 'png' : 'jpeg',\n subject: input.subject,\n categories: input.categories,\n };\n binaries.set(asset.id, { bytes: new Uint8Array(resolved.bytes), preview });\n ctx.dispatch({ type: 'ASSET_ADDED', asset });\n return asset.id;\n };\n if (!targetLibrary) return commitLooseAsset(createLooseLibrary(input.name));\n return mutateLibrary(targetLibrary.id, async () => {\n const liveLibrary = ctx.getState().libraries[targetLibrary.id];\n if (liveLibrary?.storage !== 'loose') {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] loose library '${targetLibrary.id}' no longer exists`,\n );\n }\n return commitLooseAsset(liveLibrary.id);\n });\n };\n\n const dropLibrary = (id: string): void => {\n const library = ctx.getState().libraries[id];\n if (library) for (const assetId of library.assetIds) binaries.delete(assetId);\n libraryBinaries.delete(id);\n ctx.dispatch({ type: 'LIBRARY_REMOVED', libraryId: id });\n };\n\n const removeAsset = async (id: string): Promise<void> => {\n const initialAsset = ctx.getState().assets[id];\n if (!initialAsset) return;\n return mutateLibrary(initialAsset.libraryId, async () => {\n const asset = ctx.getState().assets[id];\n if (!asset) return;\n const library = ctx.getState().libraries[asset.libraryId];\n if (library?.storage === 'canonical-pdf') {\n if (library.assetIds.length === 1) {\n dropLibrary(library.id);\n return;\n }\n if (asset.pageObjectNumber === undefined) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] canonical asset '${id}' has no page object number`,\n );\n }\n const canonicalBytes = libraryBinaries.get(library.id);\n if (!canonicalBytes) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] canonical bytes are missing for library '${library.id}'`,\n );\n }\n const doc = await openAssetDocument(canonicalBytes);\n let rewritten: Uint8Array | undefined;\n try {\n await doc.pages.delete([asset.pageObjectNumber]);\n rewritten = await doc.download();\n } finally {\n await doc.close();\n }\n libraryBinaries.set(library.id, rewritten);\n }\n binaries.delete(id);\n ctx.dispatch({ type: 'ASSET_REMOVED', assetId: id });\n });\n };\n\n const removeLibrary = (id: string): Promise<void> =>\n mutateLibrary(id, async () => dropLibrary(id));\n\n const surfaceScriptingResult = (result: FormCommitResult): void => {\n try {\n for (const effect of result.uiEffects) config.scripting?.onUiEffect?.(effect);\n for (const diagnostic of result.diagnostics) {\n config.scripting?.onDiagnostic?.(diagnostic);\n }\n if (result.error) config.scripting?.onError?.(result.error);\n } catch (error) {\n globalThis.console?.error('[stamp] scripting observer failed:', error);\n }\n };\n\n /**\n * Form-backed stamps are executable templates only until placement. Work\n * on an isolated copy so neither the canonical library nor its reusable\n * per-page extraction becomes target/user/time specific.\n */\n const materializeForPlacement = async (\n documentId: string,\n asset: StampAsset,\n bin: { bytes: Uint8Array; preview: StampAssetPreview | null },\n ): Promise<{ bytes: Uint8Array; preview: StampAssetPreview | null }> => {\n if (asset.format !== 'pdf' || !config.scripting?.enabled) return bin;\n\n const targetDoc = ctx.documentHandle(documentId);\n const targetMeta = ctx.core().documents[documentId] ?? null;\n if (!targetDoc || !targetMeta) {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] target document '${documentId}' is not open`,\n );\n }\n\n // A page extraction intentionally does not retain catalog-owned AcroForm\n // and action structures. Canonical assets therefore evaluate from the\n // whole library PDF, then extract only their selected page after flatten.\n const canonicalBytes = libraryBinaries.get(asset.libraryId);\n const sourceBytes = canonicalBytes ?? bin.bytes;\n const doc = await openAssetDocument(new Uint8Array(sourceBytes), targetDoc.security.identity);\n let scripting: ReturnType<typeof createFormScriptingController> | null = null;\n try {\n const layout = await doc.pages.list();\n const selectedPage =\n asset.pageObjectNumber === undefined\n ? layout.pageCount === 1\n ? layout.pages[0]\n : undefined\n : layout.pages.find(\n ({ pageObjectNumber }) => pageObjectNumber === asset.pageObjectNumber,\n );\n if (!selectedPage) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n canonicalBytes\n ? `[stamp] canonical page ${asset.pageObjectNumber ?? 'unknown'} no longer exists`\n : '[stamp] a loose dynamic stamp asset must contain exactly one page',\n );\n }\n const snapshot = await doc.forms.list();\n const hasSelectedPageField = snapshot.fields.some((field) =>\n field.widgets.some(\n ({ pageObjectNumber }) => pageObjectNumber === selectedPage.pageObjectNumber,\n ),\n );\n if (!hasSelectedPageField) return bin;\n if (!doc.pages.flatten || !doc.pages.extract) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] dynamic PDF stamps need an asset engine with pages.flatten and pages.extract',\n );\n }\n\n const scriptingConfig = config.scripting;\n scripting = createFormScriptingController({\n doc,\n document: () => targetMeta,\n config: scriptingConfig,\n sandboxFactory:\n scriptingConfig.sandboxFactory ??\n (() =>\n import('@embedpdf/core-js-sandbox').then(({ createQuickJsSandbox }) =>\n createQuickJsSandbox(),\n )),\n });\n const result = await scripting.recalculate(snapshot);\n surfaceScriptingResult(result);\n if (result.status === 'failed') {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] dynamic stamp scripting failed: ${result.error?.message ?? 'native form effect failed'}`,\n );\n }\n\n const pageObjectNumber = selectedPage.pageObjectNumber;\n const flattened = await doc.pages.flatten([pageObjectNumber], 'display');\n const failed = flattened.results.find(\n ({ status }) => status === 'failed' || status === 'skipped',\n );\n if (failed) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] dynamic stamp flatten failed for page ${failed.pageObjectNumber}`,\n );\n }\n\n const bytes = await doc.pages.extract([pageObjectNumber]);\n const image = await doc.page(pageObjectNumber).render.image({\n viewport: { kind: 'width', width: config.previewWidth ?? DEFAULT_PREVIEW_WIDTH },\n background: 'transparent',\n includeAnnotations: false,\n format: 'png',\n });\n return { bytes, preview: imageToPreview(image) };\n } finally {\n scripting?.dispose();\n await doc.close();\n }\n };\n\n const armAsset = async (\n documentId: string,\n assetId: string,\n opts?: { targetWidth?: number },\n ): Promise<void> => {\n const asset = ctx.getState().assets[assetId];\n const bin = binaries.get(assetId);\n if (!asset || !bin) {\n throw new EngineError(EngineErrorCode.NotFound, `[stamp] unknown asset '${assetId}'`);\n }\n const placement = await materializeForPlacement(documentId, asset, bin);\n // The placement itself remains one armStamp call. Dynamic evaluation,\n // when enabled and applicable, has already produced an ephemeral static\n // page and matching preview at this boundary.\n const annotation = ctx.forDocument(AnnotationToken, documentId);\n await annotation.armStamp({\n source: placement.bytes,\n preview: placement.preview\n ? { data: placement.preview.bytes, mimeType: placement.preview.mimeType }\n : undefined,\n intrinsicSize: asset.size,\n targetWidth: opts?.targetWidth,\n });\n };\n\n ctx.cleanup(() => {\n binaries.clear();\n libraryBinaries.clear();\n libraryMutationTails.clear();\n const ownedAssetEngine = typeof config.assetEngine === 'function' ? assetEngineRef : null;\n assetEngineRef = null;\n if (ownedAssetEngine) {\n void Promise.resolve(ownedAssetEngine)\n .then((engine) => engine.destroy())\n .catch(() => {});\n }\n });\n\n return {\n libraries: () => {\n const s = ctx.getState();\n return s.libraryOrder.map((id) => s.libraries[id]).filter((l) => l != null);\n },\n library: (id) => ctx.getState().libraries[id] ?? null,\n assets: (libraryId) => {\n const s = ctx.getState();\n if (libraryId) {\n const library = s.libraries[libraryId];\n return library ? library.assetIds.map((id) => s.assets[id]).filter((a) => a != null) : [];\n }\n return s.libraryOrder.flatMap((lid) =>\n (s.libraries[lid]?.assetIds ?? []).map((id) => s.assets[id]).filter((a) => a != null),\n );\n },\n asset: (id) => ctx.getState().assets[id] ?? null,\n assetPreview: (id) => binaries.get(id)?.preview ?? null,\n assetBytes: (id) => binaries.get(id)?.bytes ?? null,\n libraryBytes: (id) => libraryBinaries.get(id) ?? null,\n importLibraryPdf,\n addAsset,\n removeAsset,\n removeLibrary,\n armAsset,\n disarm: (documentId) => ctx.forDocument(AnnotationToken, documentId).disarmStamp(),\n };\n}\n","import type { StampAction, StampState } from './types';\n\nexport const initialStampState = (): StampState => ({\n libraries: {},\n libraryOrder: [],\n assets: {},\n});\n\n/** Pure and serializable (kernel rule 1) — descriptors only; the bytes and\n * previews live in the capability and never enter the store. */\nexport const stampReducer = (state: StampState, action: StampAction): StampState => {\n switch (action.type) {\n case 'LIBRARY_ADDED':\n return {\n ...state,\n libraries: { ...state.libraries, [action.library.id]: action.library },\n libraryOrder: [...state.libraryOrder, action.library.id],\n };\n case 'LIBRARY_REMOVED': {\n const library = state.libraries[action.libraryId];\n if (!library) return state;\n const libraries = { ...state.libraries };\n delete libraries[action.libraryId];\n const assets = { ...state.assets };\n for (const id of library.assetIds) delete assets[id];\n return {\n ...state,\n libraries,\n libraryOrder: state.libraryOrder.filter((id) => id !== action.libraryId),\n assets,\n };\n }\n case 'ASSET_ADDED': {\n const library = state.libraries[action.asset.libraryId];\n if (!library) return state;\n return {\n ...state,\n assets: { ...state.assets, [action.asset.id]: action.asset },\n libraries: {\n ...state.libraries,\n [library.id]: { ...library, assetIds: [...library.assetIds, action.asset.id] },\n },\n };\n }\n case 'ASSET_REMOVED': {\n const asset = state.assets[action.assetId];\n if (!asset) return state;\n const assets = { ...state.assets };\n delete assets[action.assetId];\n const library = state.libraries[asset.libraryId];\n return {\n ...state,\n assets,\n libraries: library\n ? {\n ...state.libraries,\n [library.id]: {\n ...library,\n assetIds: library.assetIds.filter((id) => id !== action.assetId),\n },\n }\n : state.libraries,\n };\n }\n default:\n return state;\n }\n};\n","import type { BinarySource, Engine } from '@embedpdf/engine-core/runtime';\nimport { createCapabilityToken } from '@embedpdf/core';\nimport type { FormScriptingOptions } from '@embedpdf/plugin-form';\n\n/**\n * The stamp plugin: a workspace-scoped ASSET substrate.\n *\n * The design law (\"documents have a home; assets ride the wire\"): imported\n * PDF libraries retain one canonical PDF whose catalog/page `/PieceInfo`\n * carries their metadata. Per-asset PDFs and previews are derived caches used\n * for placement. Standalone PNG/JPEG assets remain loose because the engine\n * intentionally has no raster-to-PDF-page authoring primitive.\n */\n\nexport type StampAssetKind = 'stamp' | 'signature' | 'initials';\n\n/**\n * One asset's SERIALIZABLE descriptor. The bytes and the cached preview are\n * deliberately NOT here — the reducer state stays pure/serializable (kernel\n * rule 1); binary lives in the capability and crosses only as call\n * arguments/returns, mirroring the engine's own BinarySource rule.\n */\nexport interface StampAsset {\n id: string;\n libraryId: string;\n kind: StampAssetKind;\n name: string;\n /** Intrinsic size in PDF points (the source page's crop box / image pixels 1:1). */\n size: { width: number; height: number };\n /** What the asset bytes are: a single-page vector PDF, or a raster image. */\n format: 'pdf' | 'png' | 'jpeg';\n /** Canonical library page identity; present for PDF-backed libraries. */\n pageObjectNumber?: number;\n subject?: string;\n categories?: string[];\n}\n\n/** A named group of assets — one imported PDF becomes one library. */\nexport interface StampLibrary {\n id: string;\n name: string;\n /** PDF-backed libraries own canonical bytes; loose libraries are raster/pre-sliced conveniences. */\n storage: 'canonical-pdf' | 'loose';\n categories?: string[];\n /** Asset ids in display order. */\n assetIds: string[];\n}\n\nexport interface StampState {\n libraries: Record<string, StampLibrary>;\n /** Library display order (insertion order). */\n libraryOrder: string[];\n assets: Record<string, StampAsset>;\n}\n\nexport type StampAction =\n | { type: 'LIBRARY_ADDED'; library: StampLibrary }\n | { type: 'LIBRARY_REMOVED'; libraryId: string }\n | { type: 'ASSET_ADDED'; asset: StampAsset }\n | { type: 'ASSET_REMOVED'; assetId: string };\n\nexport interface StampConfig {\n /**\n * The ASSET ENGINE port: any `Engine` that can open `{ kind: 'bytes' }` —\n * used only to slice an imported library PDF into per-page assets and\n * render their previews.\n *\n * Omitted → the kernel's own engine is used, which is exactly right for a\n * local deployment (same WASM instance, zero extra cost). In a CLOUD\n * deployment the kernel engine cannot open local bytes, so pass a factory —\n * it is called (and memoized) on the first import, never at viewer boot:\n *\n * ```ts\n * stampPlugin({\n * assetEngine: () => import('@embedpdf/engine').then((m) => m.createLocalEngine()),\n * })\n * ```\n */\n assetEngine?: Engine | (() => Engine | Promise<Engine>);\n /** Cached preview width in device px (import-time render). Default 256. */\n previewWidth?: number;\n /**\n * Opt-in Acrobat JavaScript evaluation for form-backed PDF stamp assets.\n * On arm, the plugin recalculates a temporary copy using the target\n * document's identity/name/clock, flattens it, and arms the resulting\n * static page. Canonical library and derived base bytes stay unchanged.\n */\n scripting?: FormScriptingOptions;\n}\n\nexport interface ImportLibraryOptions {\n /** Library display name. Default `'Stamps'`. */\n name?: string;\n /** Library categories written to catalog `/PieceInfo`. */\n categories?: string[];\n /** Kind stamped onto every imported asset. Default `'stamp'`. */\n kind?: StampAssetKind;\n /** Per-page asset names; default `Stamp <n>`. */\n assetName?: (pageIndex: number) => string;\n}\n\nexport interface AddAssetInput {\n /** Target library; omitted → a new single-asset library named after the asset. */\n libraryId?: string;\n name: string;\n kind?: StampAssetKind;\n subject?: string;\n categories?: string[];\n /** Single-page PDF (vector) or PNG/JPEG bytes. */\n source: BinarySource;\n /**\n * Paintable preview for pickers + the hover ghost. Loose PDF assets cannot\n * derive one without opening the PDF; canonical libraries render it after\n * insertion. Raster sources default to their own bytes.\n */\n preview?: BinarySource;\n /** Intrinsic size in PDF points. Required for PDF sources; rasters are sniffed. */\n size?: { width: number; height: number };\n}\n\n/** A cached, browser-paintable render of an asset (PNG from import; raster assets as-is). */\nexport interface StampAssetPreview {\n bytes: Uint8Array;\n mimeType: string;\n}\n\nexport interface StampCapability {\n // ── selectors (pure reads over serializable state) ──\n libraries(): StampLibrary[];\n library(id: string): StampLibrary | null;\n /** Assets of one library, in library order — or every asset when omitted. */\n assets(libraryId?: string): StampAsset[];\n asset(id: string): StampAsset | null;\n // ── binary reads (capability-held, never store state) ──\n /** The asset's paintable preview, or null while none is cached. */\n assetPreview(id: string): StampAssetPreview | null;\n /** Placement bytes; derived from the canonical page for PDF-backed libraries. */\n assetBytes(id: string): Uint8Array | null;\n /** Canonical library PDF bytes, or null for a loose library/unknown id. */\n libraryBytes(id: string): Uint8Array | null;\n // ── library intents ──\n /**\n * Import a PDF as a stamp library: every page becomes one vector asset\n * (single-page PDF bytes + a cached preview render). Uses the asset\n * engine; in a cloud deployment without one configured this rejects with\n * an actionable error. Resolves to the new library id.\n */\n importLibraryPdf(source: BinarySource, opts?: ImportLibraryOptions): Promise<string>;\n /**\n * Add a single asset. A PDF added to a canonical library is inserted as a\n * page and receives `/PieceInfo`; loose assets keep their bytes directly.\n * Raster input cannot be appended to a canonical PDF library.\n */\n addAsset(input: AddAssetInput): Promise<string>;\n /** Remove an asset, deleting its canonical page before state changes when PDF-backed. */\n removeAsset(id: string): Promise<void>;\n /** Remove a library and every asset in it, ordered with in-flight library mutations. */\n removeLibrary(id: string): Promise<void>;\n // ── placement (delegates to the annotation plugin of the named document) ──\n /**\n * Arm an asset on a document: the next click on that document's pages\n * places it (and the hover ghost previews the exact placement). With\n * scripting enabled, form-backed PDFs are evaluated against that target\n * document and flattened first. Rides `annotation.armStamp` — bytes,\n * preview, and intrinsic size all travel along, so vector stamps keep\n * their true aspect.\n */\n armAsset(documentId: string, assetId: string, opts?: { targetWidth?: number }): Promise<void>;\n /** Disarm the stamp tool on a document. */\n disarm(documentId: string): void;\n}\n\nexport const StampToken = createCapabilityToken<StampCapability>('stamp');\n","import { definePlugin } from '@embedpdf/core';\nimport { createStampCapability } from './capability';\nimport { initialStampState, stampReducer } from './reducer';\nimport { StampToken } from './types';\nimport type { StampAction, StampCapability, StampConfig, StampState } from './types';\n\n/**\n * The stamp plugin. WORKSPACE-scoped: libraries are shared across every open\n * document; placement names its document explicitly (`armAsset(documentId, …)`)\n * and delegates to that document's annotation plugin — no hard `requires`,\n * because the annotation token is document-scoped and resolved lazily per\n * placement (a viewer without the annotation plugin fails at the arm call,\n * with the kernel's own missing-capability error).\n */\nexport const stampPlugin = (config: StampConfig = {}) =>\n definePlugin<StampState, StampAction, StampCapability>({\n id: 'stamp',\n token: StampToken,\n scope: 'workspace',\n initialState: initialStampState,\n reduce: stampReducer,\n capability: (ctx) => createStampCapability(ctx, config),\n });\n"],"mappings":";;;;;;AA6BA,MAAM,wBAAwB;AAC9B,MAAM,wBAAwB;AAC9B,MAAM,sBAAsB;AAC5B,MAAM,uBAAuB;;;AAI7B,IAAI,MAAM;AACV,MAAM,OAAO,WACX,GAAG,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,IAAI,MAAA,CAAO,SAAS,EAAE;AAE7D,MAAM,eAAe,SAAyC,QAAoC;CAChG,MAAM,QAAQ,QAAQ;CACtB,OAAO,OAAO,SAAS,YAAY,MAAM,MAAM,SAAS,IAAI,MAAM,QAAQ,KAAA;AAC5E;AAEA,MAAM,aAAa,SAAyC,QAAoC;CAC9F,MAAM,QAAQ,QAAQ;CACtB,OAAO,OAAO,SAAS,UAAU,MAAM,MAAM,SAAS,IAAI,MAAM,QAAQ,KAAA;AAC1E;AAEA,MAAM,oBACJ,SACA,QACyB;CACzB,MAAM,QAAQ,QAAQ;CACtB,OAAO,OAAO,SAAS,iBAAiB,CAAC,GAAG,MAAM,KAAK,IAAI,KAAA;AAC7D;AAEA,MAAM,iBAAiB,SACrB,SAAS,cAAc,cAAc,SAAS,aAAa,aAAa;AAE1E,MAAM,mBAAmB,SAAyD;CAChF,QAAQ,MAAM,YAAY,GAA1B;EACE,KAAK,SACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,YACH,OAAO;EACT,SACE;CACJ;AACF;AAEA,MAAM,iBACJ,IACA,MACA,MACA,SACA,gBACoB;CACpB,SAAS;CACT,IAAI;CACJ,MAAM;CACN,MAAM,EAAE,MAAM,cAAc,IAAI,EAAE;CAClC,SAAS,WAAW;CACpB,YAAY,cAAc;AAC5B;AAEA,MAAM,wBACJ,IACA,MACA,gBACoB;CACpB,SAAS;CACT,IAAI;CACJ,MAAM;CACN,MAAM,EAAE,MAAM,eAAe;CAC7B,YAAY,cAAc;AAC5B;AAEA,SAAgB,sBACd,KACA,SAAsB,CAAC,GACN;;;CAGjB,MAAM,2BAAW,IAAI,IAAsE;;;CAG3F,MAAM,kCAAkB,IAAI,IAAwB;;;CAGpD,MAAM,uCAAuB,IAAI,IAA2B;CAE5D,MAAM,iBAAoB,WAAmB,aAA2C;EAEtF,MAAM,UADW,qBAAqB,IAAI,SAAS,KAAK,QAAQ,QAAQ,EAAA,CAChD,KAAK,QAAQ;EACrC,MAAM,OAAO,OAAO,WACZ,KAAA,SACA,KAAA,CACR;EACA,qBAAqB,IAAI,WAAW,IAAI;EACxC,OAAO,OAAO,cAAc;GAC1B,IAAI,qBAAqB,IAAI,SAAS,MAAM,MAAM,qBAAqB,OAAO,SAAS;EACzF,CAAC;CACH;CAOA,IAAI,iBAAkD;CACtD,MAAM,oBAA8C;EAClD,IAAI,CAAC,gBAAgB;GACnB,MAAM,MAAM,OAAO;GACnB,iBAAiB,CAAC,MAAM,IAAI,SAAS,OAAO,QAAQ,aAAa,IAAI,IAAI;EAC3E;EACA,OAAO;CACT;CAEA,MAAM,oBAAoB,OACxB,OACA,aAC4B;EAC5B,IAAI;GACF,OAAO,OACL,MAAM,YAAY,EAAA,CAClB,KACA;IAAE,MAAM;IAAS,IAAI,IAAI,cAAc;IAAG;GAAM,GAChD;IAAE,OAAO,CAAC,GAAG;IAAG,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;GAAG,CACpD;EACF,SAAS,KAAK;GAGZ,IAAI,CAAC,OAAO,eAAeA,8BAAAA,YAAY,GAAG,KAAKC,8BAAAA,gBAAgB,UAAU,GACvE,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,gBAChB,gQACF;GAEF,MAAM;EACR;CACF;;;CAIA,MAAM,kBAAkB,UAA8C;EACpE,IAAI,MAAM,OAAO,SAAS,SACxB,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,gBAChB,iFACF;EAEF,OAAO;GAAE,OAAO,MAAM,OAAO;GAAO,UAAU,MAAM;EAAY;CAClE;CAEA,MAAM,cACJ,WACA,QACA,UACW;EACX,IAAI,KAAK;EACT,IAAI,CAAC,MAAM,MAAM,IAAI,EAAE,GACrB;GAAG,KAAK,IAAI,MAAM;SACX,MAAM,IAAI,EAAE;EAErB,MAAM,IAAI,EAAE;EACZ,OAAO;CACT;CAEA,MAAM,sBAAsB,SAAyB;EACnD,MAAM,KAAK,IAAI,WAAW;EAC1B,IAAI,SAAS;GACX,MAAM;GACN,SAAS;IAAE;IAAI;IAAM,SAAS;IAAS,UAAU,CAAC;GAAE;EACtD,CAAC;EACD,OAAO;CACT;CAEA,MAAM,mBAAmB,OACvB,QACA,SACoB;EACpB,MAAM,WAAW,OAAA,GAAA,8BAAA,oBAAA,CAA0B,MAAM;EAEjD,KAAA,GAAA,8BAAA,oBAAA,CADiC,SAAS,KACnC,CAAC,EAAE,aAAa,mBACrB,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,YAChB,4EACF;EAEF,MAAM,MAAM,MAAM,kBAAkB,IAAI,WAAW,SAAS,KAAK,CAAC;EAClE,IAAI;EAWJ,IAAI;GACF,IAAI,CAAC,IAAI,aAAa,CAAC,IAAI,MAAM,SAC/B,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,gBAChB,uFACF;GAEF,MAAM,WAAW,MAAM,IAAI,MAAM,KAAK;GACtC,IAAI,SAAS,cAAc,GACzB,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,YAChB,sEACF;GAIF,MAAM,QAAQ,SAAS,MAAM,KAAK,WAAW;IAC3C,MAAM,SAAS,IAAI,KAAK,OAAO,gBAAgB;IAC/C,IAAI,CAAC,OAAO,WACV,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,gBAChB,6DACF;IAEF,OAAO;KACL;KACA;KACA,UAAU;IACZ;GACF,CAAC;GAED,MAAM,kBAAkB,MAAM,IAAI,UAAU,KAAK,qBAAqB;GACtE,KAAK,MAAM,QAAQ,OACjB,KAAK,WAAW,MAAM,KAAK,OAAO,UAAW,KAAK,mBAAmB;GAGvE,MAAM,QAAQ,IAAI,SAAS;GAC3B,MAAM,kBAAkB,IAAI,IAAI,OAAO,KAAK,MAAM,SAAS,CAAC;GAC5D,MAAM,gBAAgB,IAAI,IAAI,OAAO,KAAK,MAAM,MAAM,CAAC;GACvD,MAAM,iBAAiB,iBAAiB,WAAW,CAAC;GACpD,MAAM,YAAY,WAAW,YAAY,gBAAgB,IAAI,GAAG,aAAa,eAAe;GAC5F,MAAM,cAAc,MAAM,QAAQ,YAAY,gBAAgB,MAAM,KAAK;GACzE,MAAM,oBAAoB,MAAM,cAAc,iBAAiB,gBAAgB,YAAY;GAE3F,MAAM,cAAc,MAAM,KAAK,EAAE,QAAQ,QAAQ,UAAU,mBAAmB;IAC5E,MAAM,UAAU,cAAc,WAAW,CAAC;IAC1C,MAAM,KAAK,WAAW,YAAY,SAAS,IAAI,GAAG,SAAS,aAAa;IACxE,MAAM,OAAO,MAAM,QAAQ,gBAAgB,UAAU,SAAS,MAAM,CAAC,KAAK;IAC1E,OAAO;KACL;KACA,OAAO;MACL;MACA;MACA;MACA,MACE,MAAM,YAAY,OAAO,KAAK,KAC9B,YAAY,SAAS,MAAM,KAC3B,SAAS,OAAO,QAAQ;MAC1B,MAAM;OAAE,OAAO,OAAO,KAAK;OAAO,QAAQ,OAAO,KAAK;MAAO;MAC7D,QAAQ;MACR,kBAAkB,OAAO;MACzB,SAAS,YAAY,SAAS,SAAS;MACvC,YAAY,iBAAiB,SAAS,YAAY;KACpD;IACF;GACF,CAAC;GAED,MAAM,IAAI,UAAU,OAClB,uBACA,qBAAqB,WAAW,aAAa,iBAAiB,CAChE;GAEA,MAAM,SAAiD,CAAC;GACxD,KAAK,MAAM,cAAc,aAAa;IACpC,MAAM,EAAE,OAAO,WAAW;IAC1B,MAAM,OAAO,UAAW,OACtB,qBACA,cAAc,MAAM,IAAI,MAAM,MAAM,MAAM,MAAM,MAAM,SAAS,MAAM,UAAU,CACjF;IAGA,MAAM,QAAQ,MAAM,IAAI,MAAM,QAAQ,CAAC,MAAM,gBAAiB,CAAC;IAC/D,MAAM,QAAQ,MAAM,OAAO,OAAO,MAAM;KACtC,UAAU;MAAE,MAAM;MAAS,OAAO,OAAO,gBAAgB;KAAsB;KAC/E,YAAY;KACZ,oBAAoB;KACpB,QAAQ;IACV,CAAC;IACD,OAAO,KAAK;KAAE;KAAO;KAAO,SAAS,eAAe,KAAK;IAAE,CAAC;GAC9D;GAEA,WAAW;IACT,SAAS;KACP,IAAI;KACJ,MAAM;KACN,SAAS;KACT,YAAY;KACZ,UAAU,CAAC;IACb;IACA,gBAAgB,MAAM,IAAI,SAAS;IACnC;GACF;EACF,UAAU;GACR,MAAM,IAAI,MAAM;EAClB;EAEA,gBAAgB,IAAI,SAAS,QAAQ,IAAI,SAAS,cAAc;EAChE,IAAI,SAAS;GAAE,MAAM;GAAiB,SAAS,SAAS;EAAQ,CAAC;EACjE,KAAK,MAAM,EAAE,OAAO,OAAO,aAAa,SAAS,QAAQ;GACvD,SAAS,IAAI,MAAM,IAAI;IAAE;IAAO;GAAQ,CAAC;GACzC,IAAI,SAAS;IAAE,MAAM;IAAe;GAAM,CAAC;EAC7C;EACA,OAAO,SAAS,QAAQ;CAC1B;CAEA,MAAM,WAAW,OAAO,UAA0C;EAChE,MAAM,gBAAgB,MAAM,YACvB,IAAI,SAAS,CAAC,CAAC,UAAU,MAAM,cAAc,OAC9C;EACJ,IAAI,MAAM,aAAa,CAAC,eACtB,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,UAChB,4BAA4B,MAAM,UAAU,EAC9C;EAEF,MAAM,WAAW,OAAA,GAAA,8BAAA,oBAAA,CAA0B,MAAM,MAAM;EACvD,MAAM,QAAA,GAAA,8BAAA,oBAAA,CAA2B,SAAS,KAAK;EAC/C,IAAI,CAAC,MACH,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,YAChB,kEACF;EAEF,MAAM,QAAQ,KAAK,aAAa;EAEhC,IAAI,kBAA4C;EAChD,IAAI,MAAM,SAAS;GACjB,MAAM,UAAU,OAAA,GAAA,8BAAA,oBAAA,CAA0B,MAAM,OAAO;GACvD,kBAAkB;IAChB,OAAO,IAAI,WAAW,QAAQ,KAAK;IACnC,UAAU,QAAQ,YAAY;GAChC;EACF;EAEA,IAAI,eAAe,YAAY,iBAAiB;GAC9C,IAAI,CAAC,OACH,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,YAChB,qEACF;GAEF,OAAO,cAAc,cAAc,IAAI,YAAY;IACjD,MAAM,cAAc,IAAI,SAAS,CAAC,CAAC,UAAU,cAAc;IAC3D,IAAI,aAAa,YAAY,iBAC3B,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,UAChB,8BAA8B,cAAc,GAAG,mBACjD;IAEF,MAAM,iBAAiB,gBAAgB,IAAI,YAAY,EAAE;IACzD,IAAI,CAAC,gBACH,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,SAChB,oDAAoD,YAAY,GAAG,EACrE;IAGF,MAAM,UAAU,IAAI,OAAO;IAC3B,MAAM,MAAM,MAAM,kBAAkB,cAAc;IAClD,IAAI;IAQJ,IAAI;KACF,IAAI,CAAC,IAAI,MAAM,UAAU,CAAC,IAAI,MAAM,SAClC,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,gBAChB,+EACF;KAEF,MAAM,SAAS,MAAM,IAAI,MAAM,OAAO,IAAI,WAAW,SAAS,KAAK,CAAC;KACpE,IAAI,OAAO,0BAA0B,WAAW,GAC9C,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,YAChB,6DACF;KAEF,MAAM,mBAAmB,OAAO,0BAA0B;KAC1D,MAAM,SAAS,OAAO,OAAO,MAAM,MAChC,cAAc,UAAU,qBAAqB,gBAChD;KACA,MAAM,OAAO,IAAI,KAAK,gBAAgB;KACtC,IAAI,CAAC,UAAU,CAAC,KAAK,WACnB,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,gBAChB,wEACF;KAEF,MAAM,QAAoB;MACxB,IAAI;MACJ,WAAW,YAAY;MACvB,MAAM,MAAM,QAAQ;MACpB,MAAM,MAAM;MACZ,MAAM;OAAE,OAAO,OAAO,KAAK;OAAO,QAAQ,OAAO,KAAK;MAAO;MAC7D,QAAQ;MACR;MACA,SAAS,MAAM;MACf,YAAY,MAAM;KACpB;KACA,MAAM,KAAK,UAAU,OACnB,qBACA,cAAc,MAAM,IAAI,MAAM,MAAM,MAAM,MAAM,MAAM,SAAS,MAAM,UAAU,CACjF;KACA,MAAM,QAAQ,MAAM,IAAI,MAAM,QAAQ,CAAC,gBAAgB,CAAC;KACxD,IAAI,UAAU;KACd,IAAI,CAAC,SACH,UAAU,eACR,MAAM,KAAK,OAAO,MAAM;MACtB,UAAU;OAAE,MAAM;OAAS,OAAO,OAAO,gBAAgB;MAAsB;MAC/E,YAAY;MACZ,oBAAoB;MACpB,QAAQ;KACV,CAAC,CACH;KAEF,WAAW;MAAE;MAAO;MAAO;MAAS,WAAW,MAAM,IAAI,SAAS;KAAE;IACtE,UAAU;KACR,MAAM,IAAI,MAAM;IAClB;IAEA,gBAAgB,IAAI,YAAY,IAAI,SAAS,SAAS;IACtD,SAAS,IAAI,SAAS,MAAM,IAAI;KAAE,OAAO,SAAS;KAAO,SAAS,SAAS;IAAQ,CAAC;IACpF,IAAI,SAAS;KAAE,MAAM;KAAe,OAAO,SAAS;IAAM,CAAC;IAC3D,OAAO,SAAS,MAAM;GACxB,CAAC;EACH;EAEA,MAAM,OACJ,MAAM,SAAS,WAAW,OAAO;GAAE,OAAO,KAAK;GAAO,QAAQ,KAAK;EAAO,IAAI;EAChF,IAAI,CAAC,MACH,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,YAChB,sGACF;EAEF,IAAI,UAAU;EACd,IAAI,CAAC,WAAW,CAAC,OACf,UAAU;GAAE,OAAO,IAAI,WAAW,SAAS,KAAK;GAAG,UAAU,KAAK;EAAS;EAE7E,MAAM,oBAAoB,cAA8B;GACtD,MAAM,QAAoB;IACxB,IAAI,IAAI,OAAO;IACf;IACA,MAAM,MAAM,QAAQ;IACpB,MAAM,MAAM;IACZ;IACA,QAAQ,QAAQ,QAAQ,KAAK,aAAa,cAAc,QAAQ;IAChE,SAAS,MAAM;IACf,YAAY,MAAM;GACpB;GACA,SAAS,IAAI,MAAM,IAAI;IAAE,OAAO,IAAI,WAAW,SAAS,KAAK;IAAG;GAAQ,CAAC;GACzE,IAAI,SAAS;IAAE,MAAM;IAAe;GAAM,CAAC;GAC3C,OAAO,MAAM;EACf;EACA,IAAI,CAAC,eAAe,OAAO,iBAAiB,mBAAmB,MAAM,IAAI,CAAC;EAC1E,OAAO,cAAc,cAAc,IAAI,YAAY;GACjD,MAAM,cAAc,IAAI,SAAS,CAAC,CAAC,UAAU,cAAc;GAC3D,IAAI,aAAa,YAAY,SAC3B,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,UAChB,0BAA0B,cAAc,GAAG,mBAC7C;GAEF,OAAO,iBAAiB,YAAY,EAAE;EACxC,CAAC;CACH;CAEA,MAAM,eAAe,OAAqB;EACxC,MAAM,UAAU,IAAI,SAAS,CAAC,CAAC,UAAU;EACzC,IAAI,SAAS,KAAK,MAAM,WAAW,QAAQ,UAAU,SAAS,OAAO,OAAO;EAC5E,gBAAgB,OAAO,EAAE;EACzB,IAAI,SAAS;GAAE,MAAM;GAAmB,WAAW;EAAG,CAAC;CACzD;CAEA,MAAM,cAAc,OAAO,OAA8B;EACvD,MAAM,eAAe,IAAI,SAAS,CAAC,CAAC,OAAO;EAC3C,IAAI,CAAC,cAAc;EACnB,OAAO,cAAc,aAAa,WAAW,YAAY;GACvD,MAAM,QAAQ,IAAI,SAAS,CAAC,CAAC,OAAO;GACpC,IAAI,CAAC,OAAO;GACZ,MAAM,UAAU,IAAI,SAAS,CAAC,CAAC,UAAU,MAAM;GAC/C,IAAI,SAAS,YAAY,iBAAiB;IACxC,IAAI,QAAQ,SAAS,WAAW,GAAG;KACjC,YAAY,QAAQ,EAAE;KACtB;IACF;IACA,IAAI,MAAM,qBAAqB,KAAA,GAC7B,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,SAChB,4BAA4B,GAAG,4BACjC;IAEF,MAAM,iBAAiB,gBAAgB,IAAI,QAAQ,EAAE;IACrD,IAAI,CAAC,gBACH,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,SAChB,oDAAoD,QAAQ,GAAG,EACjE;IAEF,MAAM,MAAM,MAAM,kBAAkB,cAAc;IAClD,IAAI;IACJ,IAAI;KACF,MAAM,IAAI,MAAM,OAAO,CAAC,MAAM,gBAAgB,CAAC;KAC/C,YAAY,MAAM,IAAI,SAAS;IACjC,UAAU;KACR,MAAM,IAAI,MAAM;IAClB;IACA,gBAAgB,IAAI,QAAQ,IAAI,SAAS;GAC3C;GACA,SAAS,OAAO,EAAE;GAClB,IAAI,SAAS;IAAE,MAAM;IAAiB,SAAS;GAAG,CAAC;EACrD,CAAC;CACH;CAEA,MAAM,iBAAiB,OACrB,cAAc,IAAI,YAAY,YAAY,EAAE,CAAC;CAE/C,MAAM,0BAA0B,WAAmC;EACjE,IAAI;GACF,KAAK,MAAM,UAAU,OAAO,WAAW,OAAO,WAAW,aAAa,MAAM;GAC5E,KAAK,MAAM,cAAc,OAAO,aAC9B,OAAO,WAAW,eAAe,UAAU;GAE7C,IAAI,OAAO,OAAO,OAAO,WAAW,UAAU,OAAO,KAAK;EAC5D,SAAS,OAAO;GACd,WAAW,SAAS,MAAM,sCAAsC,KAAK;EACvE;CACF;;;;;;CAOA,MAAM,0BAA0B,OAC9B,YACA,OACA,QACsE;EACtE,IAAI,MAAM,WAAW,SAAS,CAAC,OAAO,WAAW,SAAS,OAAO;EAEjE,MAAM,YAAY,IAAI,eAAe,UAAU;EAC/C,MAAM,aAAa,IAAI,KAAK,CAAC,CAAC,UAAU,eAAe;EACvD,IAAI,CAAC,aAAa,CAAC,YACjB,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,UAChB,4BAA4B,WAAW,cACzC;EAMF,MAAM,iBAAiB,gBAAgB,IAAI,MAAM,SAAS;EAC1D,MAAM,cAAc,kBAAkB,IAAI;EAC1C,MAAM,MAAM,MAAM,kBAAkB,IAAI,WAAW,WAAW,GAAG,UAAU,SAAS,QAAQ;EAC5F,IAAI,YAAqE;EACzE,IAAI;GACF,MAAM,SAAS,MAAM,IAAI,MAAM,KAAK;GACpC,MAAM,eACJ,MAAM,qBAAqB,KAAA,IACvB,OAAO,cAAc,IACnB,OAAO,MAAM,KACb,KAAA,IACF,OAAO,MAAM,MACV,EAAE,uBAAuB,qBAAqB,MAAM,gBACvD;GACN,IAAI,CAAC,cACH,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,YAChB,iBACI,0BAA0B,MAAM,oBAAoB,UAAU,qBAC9D,mEACN;GAEF,MAAM,WAAW,MAAM,IAAI,MAAM,KAAK;GAMtC,IAAI,CALyB,SAAS,OAAO,MAAM,UACjD,MAAM,QAAQ,MACX,EAAE,uBAAuB,qBAAqB,aAAa,gBAC9D,CAEsB,GAAG,OAAO;GAClC,IAAI,CAAC,IAAI,MAAM,WAAW,CAAC,IAAI,MAAM,SACnC,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,gBAChB,sFACF;GAGF,MAAM,kBAAkB,OAAO;GAC/B,aAAA,GAAA,sBAAA,8BAAA,CAA0C;IACxC;IACA,gBAAgB;IAChB,QAAQ;IACR,gBACE,gBAAgB,yBAEd,OAAO,4BAA4B,CAAC,MAAM,EAAE,2BAC1C,qBAAqB,CACvB;GACN,CAAC;GACD,MAAM,SAAS,MAAM,UAAU,YAAY,QAAQ;GACnD,uBAAuB,MAAM;GAC7B,IAAI,OAAO,WAAW,UACpB,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,SAChB,2CAA2C,OAAO,OAAO,WAAW,6BACtE;GAGF,MAAM,mBAAmB,aAAa;GAEtC,MAAM,UAAS,MADS,IAAI,MAAM,QAAQ,CAAC,gBAAgB,GAAG,SAAS,EAAA,CAC9C,QAAQ,MAC9B,EAAE,aAAa,WAAW,YAAY,WAAW,SACpD;GACA,IAAI,QACF,MAAM,IAAID,8BAAAA,YACRC,8BAAAA,gBAAgB,SAChB,iDAAiD,OAAO,kBAC1D;GAGF,MAAM,QAAQ,MAAM,IAAI,MAAM,QAAQ,CAAC,gBAAgB,CAAC;GACxD,MAAM,QAAQ,MAAM,IAAI,KAAK,gBAAgB,CAAC,CAAC,OAAO,MAAM;IAC1D,UAAU;KAAE,MAAM;KAAS,OAAO,OAAO,gBAAgB;IAAsB;IAC/E,YAAY;IACZ,oBAAoB;IACpB,QAAQ;GACV,CAAC;GACD,OAAO;IAAE;IAAO,SAAS,eAAe,KAAK;GAAE;EACjD,UAAU;GACR,WAAW,QAAQ;GACnB,MAAM,IAAI,MAAM;EAClB;CACF;CAEA,MAAM,WAAW,OACf,YACA,SACA,SACkB;EAClB,MAAM,QAAQ,IAAI,SAAS,CAAC,CAAC,OAAO;EACpC,MAAM,MAAM,SAAS,IAAI,OAAO;EAChC,IAAI,CAAC,SAAS,CAAC,KACb,MAAM,IAAID,8BAAAA,YAAYC,8BAAAA,gBAAgB,UAAU,0BAA0B,QAAQ,EAAE;EAEtF,MAAM,YAAY,MAAM,wBAAwB,YAAY,OAAO,GAAG;EAKtE,MADmB,IAAI,YAAYC,4BAAAA,iBAAiB,UACrC,CAAC,CAAC,SAAS;GACxB,QAAQ,UAAU;GAClB,SAAS,UAAU,UACf;IAAE,MAAM,UAAU,QAAQ;IAAO,UAAU,UAAU,QAAQ;GAAS,IACtE,KAAA;GACJ,eAAe,MAAM;GACrB,aAAa,MAAM;EACrB,CAAC;CACH;CAEA,IAAI,cAAc;EAChB,SAAS,MAAM;EACf,gBAAgB,MAAM;EACtB,qBAAqB,MAAM;EAC3B,MAAM,mBAAmB,OAAO,OAAO,gBAAgB,aAAa,iBAAiB;EACrF,iBAAiB;EACjB,IAAI,kBACF,QAAa,QAAQ,gBAAgB,CAAC,CACnC,MAAM,WAAW,OAAO,QAAQ,CAAC,CAAC,CAClC,YAAY,CAAC,CAAC;CAErB,CAAC;CAED,OAAO;EACL,iBAAiB;GACf,MAAM,IAAI,IAAI,SAAS;GACvB,OAAO,EAAE,aAAa,KAAK,OAAO,EAAE,UAAU,GAAG,CAAC,CAAC,QAAQ,MAAM,KAAK,IAAI;EAC5E;EACA,UAAU,OAAO,IAAI,SAAS,CAAC,CAAC,UAAU,OAAO;EACjD,SAAS,cAAc;GACrB,MAAM,IAAI,IAAI,SAAS;GACvB,IAAI,WAAW;IACb,MAAM,UAAU,EAAE,UAAU;IAC5B,OAAO,UAAU,QAAQ,SAAS,KAAK,OAAO,EAAE,OAAO,GAAG,CAAC,CAAC,QAAQ,MAAM,KAAK,IAAI,IAAI,CAAC;GAC1F;GACA,OAAO,EAAE,aAAa,SAAS,SAC5B,EAAE,UAAU,IAAI,EAAE,YAAY,CAAC,EAAA,CAAG,KAAK,OAAO,EAAE,OAAO,GAAG,CAAC,CAAC,QAAQ,MAAM,KAAK,IAAI,CACtF;EACF;EACA,QAAQ,OAAO,IAAI,SAAS,CAAC,CAAC,OAAO,OAAO;EAC5C,eAAe,OAAO,SAAS,IAAI,EAAE,CAAC,EAAE,WAAW;EACnD,aAAa,OAAO,SAAS,IAAI,EAAE,CAAC,EAAE,SAAS;EAC/C,eAAe,OAAO,gBAAgB,IAAI,EAAE,KAAK;EACjD;EACA;EACA;EACA;EACA;EACA,SAAS,eAAe,IAAI,YAAYA,4BAAAA,iBAAiB,UAAU,CAAC,CAAC,YAAY;CACnF;AACF;;;ACluBA,MAAa,2BAAuC;CAClD,WAAW,CAAC;CACZ,cAAc,CAAC;CACf,QAAQ,CAAC;AACX;;;AAIA,MAAa,gBAAgB,OAAmB,WAAoC;CAClF,QAAQ,OAAO,MAAf;EACE,KAAK,iBACH,OAAO;GACL,GAAG;GACH,WAAW;IAAE,GAAG,MAAM;KAAY,OAAO,QAAQ,KAAK,OAAO;GAAQ;GACrE,cAAc,CAAC,GAAG,MAAM,cAAc,OAAO,QAAQ,EAAE;EACzD;EACF,KAAK,mBAAmB;GACtB,MAAM,UAAU,MAAM,UAAU,OAAO;GACvC,IAAI,CAAC,SAAS,OAAO;GACrB,MAAM,YAAY,EAAE,GAAG,MAAM,UAAU;GACvC,OAAO,UAAU,OAAO;GACxB,MAAM,SAAS,EAAE,GAAG,MAAM,OAAO;GACjC,KAAK,MAAM,MAAM,QAAQ,UAAU,OAAO,OAAO;GACjD,OAAO;IACL,GAAG;IACH;IACA,cAAc,MAAM,aAAa,QAAQ,OAAO,OAAO,OAAO,SAAS;IACvE;GACF;EACF;EACA,KAAK,eAAe;GAClB,MAAM,UAAU,MAAM,UAAU,OAAO,MAAM;GAC7C,IAAI,CAAC,SAAS,OAAO;GACrB,OAAO;IACL,GAAG;IACH,QAAQ;KAAE,GAAG,MAAM;MAAS,OAAO,MAAM,KAAK,OAAO;IAAM;IAC3D,WAAW;KACT,GAAG,MAAM;MACR,QAAQ,KAAK;MAAE,GAAG;MAAS,UAAU,CAAC,GAAG,QAAQ,UAAU,OAAO,MAAM,EAAE;KAAE;IAC/E;GACF;EACF;EACA,KAAK,iBAAiB;GACpB,MAAM,QAAQ,MAAM,OAAO,OAAO;GAClC,IAAI,CAAC,OAAO,OAAO;GACnB,MAAM,SAAS,EAAE,GAAG,MAAM,OAAO;GACjC,OAAO,OAAO,OAAO;GACrB,MAAM,UAAU,MAAM,UAAU,MAAM;GACtC,OAAO;IACL,GAAG;IACH;IACA,WAAW,UACP;KACE,GAAG,MAAM;MACR,QAAQ,KAAK;MACZ,GAAG;MACH,UAAU,QAAQ,SAAS,QAAQ,OAAO,OAAO,OAAO,OAAO;KACjE;IACF,IACA,MAAM;GACZ;EACF;EACA,SACE,OAAO;CACX;AACF;;;ACyGA,MAAa,cAAA,GAAA,eAAA,sBAAA,CAAoD,OAAO;;;;;;;;;;;AC9JxE,MAAa,eAAe,SAAsB,CAAC,OAAA,GAAA,eAAA,aAAA,CACM;CACrD,IAAI;CACJ,OAAO;CACP,OAAO;CACP,cAAc;CACd,QAAQ;CACR,aAAa,QAAQ,sBAAsB,KAAK,MAAM;AACxD,CAAC"}
1
+ {"version":3,"file":"index.cjs","names":["EngineError","EngineErrorCode","AnnotationToken"],"sources":["../src/capability.ts","../src/reducer.ts","../src/types.ts","../src/stamp.plugin.ts"],"sourcesContent":["import {\n EngineError,\n EngineErrorCode,\n resolveBinarySource,\n sniffBinaryMetadata,\n type BinarySource,\n type DocumentHandle,\n type Engine,\n type PageImageHandle,\n type PieceInfoEntry,\n type PieceInfoPatch,\n} from '@embedpdf/engine-core/runtime';\nimport { type PluginContext } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation';\nimport { createFormScriptingController, type FormCommitResult } from '@embedpdf/plugin-form';\n\nimport type {\n AddAssetInput,\n ImportLibraryOptions,\n StampAction,\n StampAsset,\n StampAssetPreview,\n StampCapability,\n StampConfig,\n StampLibrary,\n StampAssetKind,\n StampState,\n} from './types';\n\nconst DEFAULT_PREVIEW_WIDTH = 256;\nconst LIBRARY_PIECEINFO_APP = 'EMBD_StampLibrary';\nconst STAMP_PIECEINFO_APP = 'EMBD_Stamp';\nconst STAMP_SCHEMA_VERSION = 1;\n\n/** Session-unique ids. Assets are session-scoped for now (no persistence),\n * so a timestamp + counter is enough — durable ids come with the store port. */\nlet seq = 0;\nconst uid = (prefix: string): string =>\n `${prefix}-${Date.now().toString(36)}-${(seq++).toString(36)}`;\n\nconst entryString = (entries: Record<string, PieceInfoEntry>, key: string): string | undefined => {\n const entry = entries[key];\n return entry?.type === 'string' && entry.value.length > 0 ? entry.value : undefined;\n};\n\nconst entryName = (entries: Record<string, PieceInfoEntry>, key: string): string | undefined => {\n const entry = entries[key];\n return entry?.type === 'name' && entry.value.length > 0 ? entry.value : undefined;\n};\n\nconst entryStringArray = (\n entries: Record<string, PieceInfoEntry>,\n key: string,\n): string[] | undefined => {\n const entry = entries[key];\n return entry?.type === 'string-array' ? [...entry.value] : undefined;\n};\n\nconst kindToPdfName = (kind: StampAssetKind): string =>\n kind === 'signature' ? 'Signature' : kind === 'initials' ? 'Initials' : 'Stamp';\n\nconst kindFromPdfName = (name: string | undefined): StampAssetKind | undefined => {\n switch (name?.toLowerCase()) {\n case 'stamp':\n return 'stamp';\n case 'signature':\n return 'signature';\n case 'initials':\n return 'initials';\n default:\n return undefined;\n }\n};\n\nconst metadataPatch = (\n id: string,\n name: string,\n kind: StampAssetKind,\n subject?: string,\n categories?: readonly string[],\n): PieceInfoPatch => ({\n Version: STAMP_SCHEMA_VERSION,\n Id: id,\n Name: name,\n Kind: { name: kindToPdfName(kind) },\n Subject: subject ?? null,\n Categories: categories ?? null,\n});\n\nconst libraryMetadataPatch = (\n id: string,\n name: string,\n categories?: readonly string[],\n): PieceInfoPatch => ({\n Version: STAMP_SCHEMA_VERSION,\n Id: id,\n Name: name,\n Kind: { name: 'StampLibrary' },\n Categories: categories ?? null,\n});\n\nexport function createStampCapability(\n ctx: PluginContext<StampState, StampAction>,\n config: StampConfig = {},\n): StampCapability {\n /** Binary sidecar of the serializable store: asset bytes + cached preview,\n * keyed by asset id. The reducer never sees these (kernel rule 1). */\n const binaries = new Map<string, { bytes: Uint8Array; preview: StampAssetPreview | null }>();\n /** The durable source of truth for a canonical library. Asset PDFs above\n * are derived page extractions; this map owns the rewritten whole PDF. */\n const libraryBinaries = new Map<string, Uint8Array>();\n /** Whole-PDF rewrites must be serialized per library or two concurrent\n * appends could both start from the same bytes and lose one page. */\n const libraryMutationTails = new Map<string, Promise<void>>();\n\n const mutateLibrary = <T>(libraryId: string, mutation: () => Promise<T>): Promise<T> => {\n const previous = libraryMutationTails.get(libraryId) ?? Promise.resolve();\n const result = previous.then(mutation);\n const tail = result.then(\n () => undefined,\n () => undefined,\n );\n libraryMutationTails.set(libraryId, tail);\n return result.finally(() => {\n if (libraryMutationTails.get(libraryId) === tail) libraryMutationTails.delete(libraryId);\n });\n };\n\n // The ASSET ENGINE port. A configured factory is called (and memoized) on\n // the first import, not at viewer start; a configured instance is used\n // as-is; nothing configured falls back to the kernel's engine — correct for\n // local deployments, and rejected with an actionable error by cloud engines\n // at the first `open({ kind: 'bytes' })`.\n let assetEngineRef: Engine | Promise<Engine> | null = null;\n const assetEngine = (): Engine | Promise<Engine> => {\n if (!assetEngineRef) {\n const cfg = config.assetEngine;\n assetEngineRef = !cfg ? ctx.engine : typeof cfg === 'function' ? cfg() : cfg;\n }\n return assetEngineRef;\n };\n\n const openAssetDocument = async (\n bytes: Uint8Array,\n identity?: DocumentHandle['security']['identity'],\n ): Promise<DocumentHandle> => {\n try {\n return await (\n await assetEngine()\n ).open(\n { kind: 'bytes', id: uid('stamp-import'), bytes },\n { scope: ['*'], ...(identity ? { identity } : {}) },\n );\n } catch (err) {\n // A cloud kernel engine rejects 'bytes' with InvalidArg — turn the\n // generic contract error into the configuration fix.\n if (!config.assetEngine && EngineError.is(err, EngineErrorCode.InvalidArg)) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n \"[stamp] importing a library PDF needs an engine that can open local bytes, and this viewer's engine cannot (cloud). Pass stampPlugin({ assetEngine: () => import('@embedpdf/engine').then((m) => m.createLocalEngine()) }) — it loads lazily, on first import.\",\n );\n }\n throw err;\n }\n };\n\n /** Import-time preview render → bytes. The asset engine is local by\n * definition, so the image source is always inline bytes. */\n const imageToPreview = (image: PageImageHandle): StampAssetPreview => {\n if (image.source.kind !== 'bytes') {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] asset engine returned a URL-sourced render; asset engines must be local',\n );\n }\n return { bytes: image.source.bytes, mimeType: image.contentType };\n };\n\n const allocateId = (\n preferred: string | undefined,\n prefix: string,\n taken: Set<string>,\n ): string => {\n let id = preferred;\n if (!id || taken.has(id)) {\n do id = uid(prefix);\n while (taken.has(id));\n }\n taken.add(id);\n return id;\n };\n\n const createLooseLibrary = (name: string): string => {\n const id = uid('stamp-lib');\n ctx.dispatch({\n type: 'LIBRARY_ADDED',\n library: { id, name, storage: 'loose', assetIds: [] },\n });\n return id;\n };\n\n const importLibraryPdf = async (\n source: BinarySource,\n opts?: ImportLibraryOptions,\n ): Promise<string> => {\n const resolved = await resolveBinarySource(source);\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (meta?.mimeType !== 'application/pdf') {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] importLibraryPdf needs PDF bytes (use addAsset for a raster image)',\n );\n }\n const doc = await openAssetDocument(new Uint8Array(resolved.bytes));\n let imported:\n | {\n library: StampLibrary;\n canonicalBytes: Uint8Array;\n assets: Array<{\n asset: StampAsset;\n bytes: Uint8Array;\n preview: StampAssetPreview;\n }>;\n }\n | undefined;\n try {\n if (!doc.pieceInfo) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] canonical PDF libraries need an asset engine with pieceInfo',\n );\n }\n const snapshot = await doc.pages.list();\n if (snapshot.pageCount === 0) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] a canonical stamp library PDF must contain at least one page',\n );\n }\n\n // Discover and validate every required service before the first write.\n const pages = snapshot.pages.map((layout) => {\n const handle = doc.page(layout.pageObjectNumber);\n if (!handle.pieceInfo) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] canonical PDF libraries need page pieceInfo support',\n );\n }\n return {\n layout,\n handle,\n metadata: null as Awaited<ReturnType<typeof handle.pieceInfo.read>>,\n };\n });\n\n const catalogMetadata = await doc.pieceInfo.read(LIBRARY_PIECEINFO_APP);\n for (const page of pages) {\n page.metadata = await page.handle.pieceInfo!.read(STAMP_PIECEINFO_APP);\n }\n\n const state = ctx.getState();\n const takenLibraryIds = new Set(Object.keys(state.libraries));\n const takenAssetIds = new Set(Object.keys(state.assets));\n const catalogEntries = catalogMetadata?.entries ?? {};\n const libraryId = allocateId(entryString(catalogEntries, 'Id'), 'stamp-lib', takenLibraryIds);\n const libraryName = opts?.name ?? entryString(catalogEntries, 'Name') ?? 'Stamps';\n const libraryCategories = opts?.categories ?? entryStringArray(catalogEntries, 'Categories');\n\n const descriptors = pages.map(({ layout, handle, metadata: pageMetadata }) => {\n const entries = pageMetadata?.entries ?? {};\n const id = allocateId(entryString(entries, 'Id'), 'stamp', takenAssetIds);\n const kind = opts?.kind ?? kindFromPdfName(entryName(entries, 'Kind')) ?? 'stamp';\n return {\n handle,\n asset: {\n id,\n libraryId,\n kind,\n name:\n opts?.assetName?.(layout.index) ??\n entryString(entries, 'Name') ??\n `Stamp ${layout.index + 1}`,\n size: { width: layout.size.width, height: layout.size.height },\n format: 'pdf' as const,\n pageObjectNumber: layout.pageObjectNumber,\n subject: entryString(entries, 'Subject'),\n categories: entryStringArray(entries, 'Categories'),\n },\n };\n });\n\n await doc.pieceInfo.update(\n LIBRARY_PIECEINFO_APP,\n libraryMetadataPatch(libraryId, libraryName, libraryCategories),\n );\n\n const assets: NonNullable<typeof imported>['assets'] = [];\n for (const descriptor of descriptors) {\n const { asset, handle } = descriptor;\n await handle.pieceInfo!.update(\n STAMP_PIECEINFO_APP,\n metadataPatch(asset.id, asset.name, asset.kind, asset.subject, asset.categories),\n );\n // One canonical page → one derived placement PDF plus a transparent\n // preview. Extract after metadata so the cache carries the same id.\n const bytes = await doc.pages.extract([asset.pageObjectNumber!]);\n const image = await handle.render.image({\n viewport: { kind: 'width', width: config.previewWidth ?? DEFAULT_PREVIEW_WIDTH },\n background: 'transparent',\n includeAnnotations: true,\n format: 'png',\n });\n assets.push({ asset, bytes, preview: imageToPreview(image) });\n }\n\n imported = {\n library: {\n id: libraryId,\n name: libraryName,\n storage: 'canonical-pdf',\n categories: libraryCategories,\n assetIds: [],\n },\n canonicalBytes: await doc.download(),\n assets,\n };\n } finally {\n await doc.close();\n }\n\n libraryBinaries.set(imported.library.id, imported.canonicalBytes);\n ctx.dispatch({ type: 'LIBRARY_ADDED', library: imported.library });\n for (const { asset, bytes, preview } of imported.assets) {\n binaries.set(asset.id, { bytes, preview });\n ctx.dispatch({ type: 'ASSET_ADDED', asset });\n }\n return imported.library.id;\n };\n\n const addAsset = async (input: AddAssetInput): Promise<string> => {\n const targetLibrary = input.libraryId\n ? (ctx.getState().libraries[input.libraryId] ?? null)\n : null;\n if (input.libraryId && !targetLibrary) {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] unknown library '${input.libraryId}'`,\n );\n }\n const resolved = await resolveBinarySource(input.source);\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (!meta) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] asset source must be PNG, JPEG, or single-page PDF bytes',\n );\n }\n const isPdf = meta.mimeType === 'application/pdf';\n\n let suppliedPreview: StampAssetPreview | null = null;\n if (input.preview) {\n const preview = await resolveBinarySource(input.preview);\n suppliedPreview = {\n bytes: new Uint8Array(preview.bytes),\n mimeType: preview.mimeType ?? 'image/png',\n };\n }\n\n if (targetLibrary?.storage === 'canonical-pdf') {\n if (!isPdf) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] raster assets cannot be appended to a canonical PDF library',\n );\n }\n return mutateLibrary(targetLibrary.id, async () => {\n const liveLibrary = ctx.getState().libraries[targetLibrary.id];\n if (liveLibrary?.storage !== 'canonical-pdf') {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] canonical library '${targetLibrary.id}' no longer exists`,\n );\n }\n const canonicalBytes = libraryBinaries.get(liveLibrary.id);\n if (!canonicalBytes) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] canonical bytes are missing for library '${liveLibrary.id}'`,\n );\n }\n\n const assetId = uid('stamp');\n const doc = await openAssetDocument(canonicalBytes);\n let appended:\n | {\n asset: StampAsset;\n bytes: Uint8Array;\n preview: StampAssetPreview;\n canonical: Uint8Array;\n }\n | undefined;\n try {\n const result = await doc.pages.insert(new Uint8Array(resolved.bytes));\n if (result.insertedPageObjectNumbers.length !== 1) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] a canonical library asset must be a single-page PDF',\n );\n }\n const pageObjectNumber = result.insertedPageObjectNumbers[0];\n const layout = result.layout.pages.find(\n (candidate) => candidate.pageObjectNumber === pageObjectNumber,\n );\n const page = doc.page(pageObjectNumber);\n if (!layout || !page.pieceInfo) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] canonical PDF libraries need page layout and pieceInfo support',\n );\n }\n const asset: StampAsset = {\n id: assetId,\n libraryId: liveLibrary.id,\n kind: input.kind ?? 'stamp',\n name: input.name,\n size: { width: layout.size.width, height: layout.size.height },\n format: 'pdf',\n pageObjectNumber,\n subject: input.subject,\n categories: input.categories,\n };\n await page.pieceInfo.update(\n STAMP_PIECEINFO_APP,\n metadataPatch(asset.id, asset.name, asset.kind, asset.subject, asset.categories),\n );\n const bytes = await doc.pages.extract([pageObjectNumber]);\n let preview = suppliedPreview;\n if (!preview) {\n preview = imageToPreview(\n await page.render.image({\n viewport: { kind: 'width', width: config.previewWidth ?? DEFAULT_PREVIEW_WIDTH },\n background: 'transparent',\n includeAnnotations: true,\n format: 'png',\n }),\n );\n }\n appended = { asset, bytes, preview, canonical: await doc.download() };\n } finally {\n await doc.close();\n }\n\n libraryBinaries.set(liveLibrary.id, appended.canonical);\n binaries.set(appended.asset.id, { bytes: appended.bytes, preview: appended.preview });\n ctx.dispatch({ type: 'ASSET_ADDED', asset: appended.asset });\n return appended.asset.id;\n });\n }\n\n const size =\n input.size ?? ('width' in meta ? { width: meta.width, height: meta.height } : null);\n if (!size) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] a PDF asset needs `size` (its page size in points) — PDF bytes carry no sniffable dimensions',\n );\n }\n let preview = suppliedPreview;\n if (!preview && !isPdf) {\n preview = { bytes: new Uint8Array(resolved.bytes), mimeType: meta.mimeType };\n }\n const commitLooseAsset = (libraryId: string): string => {\n const asset: StampAsset = {\n id: uid('stamp'),\n libraryId,\n kind: input.kind ?? 'stamp',\n name: input.name,\n size,\n format: isPdf ? 'pdf' : meta.mimeType === 'image/png' ? 'png' : 'jpeg',\n subject: input.subject,\n categories: input.categories,\n };\n binaries.set(asset.id, { bytes: new Uint8Array(resolved.bytes), preview });\n ctx.dispatch({ type: 'ASSET_ADDED', asset });\n return asset.id;\n };\n if (!targetLibrary) return commitLooseAsset(createLooseLibrary(input.name));\n return mutateLibrary(targetLibrary.id, async () => {\n const liveLibrary = ctx.getState().libraries[targetLibrary.id];\n if (liveLibrary?.storage !== 'loose') {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] loose library '${targetLibrary.id}' no longer exists`,\n );\n }\n return commitLooseAsset(liveLibrary.id);\n });\n };\n\n const dropLibrary = (id: string): void => {\n const library = ctx.getState().libraries[id];\n if (library) for (const assetId of library.assetIds) binaries.delete(assetId);\n libraryBinaries.delete(id);\n ctx.dispatch({ type: 'LIBRARY_REMOVED', libraryId: id });\n };\n\n const removeAsset = async (id: string): Promise<void> => {\n const initialAsset = ctx.getState().assets[id];\n if (!initialAsset) return;\n return mutateLibrary(initialAsset.libraryId, async () => {\n const asset = ctx.getState().assets[id];\n if (!asset) return;\n const library = ctx.getState().libraries[asset.libraryId];\n if (library?.storage === 'canonical-pdf') {\n if (library.assetIds.length === 1) {\n dropLibrary(library.id);\n return;\n }\n if (asset.pageObjectNumber === undefined) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] canonical asset '${id}' has no page object number`,\n );\n }\n const canonicalBytes = libraryBinaries.get(library.id);\n if (!canonicalBytes) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] canonical bytes are missing for library '${library.id}'`,\n );\n }\n const doc = await openAssetDocument(canonicalBytes);\n let rewritten: Uint8Array | undefined;\n try {\n await doc.pages.delete([asset.pageObjectNumber]);\n rewritten = await doc.download();\n } finally {\n await doc.close();\n }\n libraryBinaries.set(library.id, rewritten);\n }\n binaries.delete(id);\n ctx.dispatch({ type: 'ASSET_REMOVED', assetId: id });\n });\n };\n\n const removeLibrary = (id: string): Promise<void> =>\n mutateLibrary(id, async () => dropLibrary(id));\n\n const surfaceScriptingResult = (result: FormCommitResult): void => {\n try {\n for (const effect of result.uiEffects) config.scripting?.onUiEffect?.(effect);\n for (const diagnostic of result.diagnostics) {\n config.scripting?.onDiagnostic?.(diagnostic);\n }\n if (result.error) config.scripting?.onError?.(result.error);\n } catch (error) {\n globalThis.console?.error('[stamp] scripting observer failed:', error);\n }\n };\n\n /**\n * Form-backed stamps are executable templates only until placement. Work\n * on an isolated copy so neither the canonical library nor its reusable\n * per-page extraction becomes target/user/time specific.\n */\n const materializeForPlacement = async (\n documentId: string,\n asset: StampAsset,\n bin: { bytes: Uint8Array; preview: StampAssetPreview | null },\n ): Promise<{ bytes: Uint8Array; preview: StampAssetPreview | null }> => {\n if (asset.format !== 'pdf' || !config.scripting?.enabled) return bin;\n\n const targetDoc = ctx.documentHandle(documentId);\n const targetMeta = ctx.core().documents[documentId] ?? null;\n if (!targetDoc || !targetMeta) {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] target document '${documentId}' is not open`,\n );\n }\n\n // A page extraction intentionally does not retain catalog-owned AcroForm\n // and action structures. Canonical assets therefore evaluate from the\n // whole library PDF, then extract only their selected page after flatten.\n const canonicalBytes = libraryBinaries.get(asset.libraryId);\n const sourceBytes = canonicalBytes ?? bin.bytes;\n const doc = await openAssetDocument(new Uint8Array(sourceBytes), targetDoc.security.identity);\n let scripting: ReturnType<typeof createFormScriptingController> | null = null;\n try {\n const layout = await doc.pages.list();\n const selectedPage =\n asset.pageObjectNumber === undefined\n ? layout.pageCount === 1\n ? layout.pages[0]\n : undefined\n : layout.pages.find(\n ({ pageObjectNumber }) => pageObjectNumber === asset.pageObjectNumber,\n );\n if (!selectedPage) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n canonicalBytes\n ? `[stamp] canonical page ${asset.pageObjectNumber ?? 'unknown'} no longer exists`\n : '[stamp] a loose dynamic stamp asset must contain exactly one page',\n );\n }\n const snapshot = await doc.forms.list();\n const hasSelectedPageField = snapshot.fields.some((field) =>\n field.widgets.some(\n ({ pageObjectNumber }) => pageObjectNumber === selectedPage.pageObjectNumber,\n ),\n );\n if (!hasSelectedPageField) return bin;\n if (!doc.pages.flatten || !doc.pages.extract) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] dynamic PDF stamps need an asset engine with pages.flatten and pages.extract',\n );\n }\n\n const scriptingConfig = config.scripting;\n scripting = createFormScriptingController({\n doc,\n document: () => targetMeta,\n config: scriptingConfig,\n sandboxFactory:\n scriptingConfig.sandboxFactory ??\n (() =>\n import('@embedpdf/core-js-sandbox').then(({ createQuickJsSandbox }) =>\n createQuickJsSandbox(),\n )),\n });\n const result = await scripting.recalculate(snapshot);\n surfaceScriptingResult(result);\n if (result.status === 'failed') {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] dynamic stamp scripting failed: ${result.error?.message ?? 'native form effect failed'}`,\n );\n }\n\n const pageObjectNumber = selectedPage.pageObjectNumber;\n const flattened = await doc.pages.flatten([pageObjectNumber], 'display');\n const failed = flattened.results.find(\n ({ status }) => status === 'failed' || status === 'skipped',\n );\n if (failed) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] dynamic stamp flatten failed for page ${failed.pageObjectNumber}`,\n );\n }\n\n const bytes = await doc.pages.extract([pageObjectNumber]);\n const image = await doc.page(pageObjectNumber).render.image({\n viewport: { kind: 'width', width: config.previewWidth ?? DEFAULT_PREVIEW_WIDTH },\n background: 'transparent',\n includeAnnotations: false,\n format: 'png',\n });\n return { bytes, preview: imageToPreview(image) };\n } finally {\n scripting?.dispose();\n await doc.close();\n }\n };\n\n const armAsset = async (\n documentId: string,\n assetId: string,\n opts?: { targetWidth?: number },\n ): Promise<void> => {\n const asset = ctx.getState().assets[assetId];\n const bin = binaries.get(assetId);\n if (!asset || !bin) {\n throw new EngineError(EngineErrorCode.NotFound, `[stamp] unknown asset '${assetId}'`);\n }\n const placement = await materializeForPlacement(documentId, asset, bin);\n // The placement itself remains one armStamp call. Dynamic evaluation,\n // when enabled and applicable, has already produced an ephemeral static\n // page and matching preview at this boundary.\n const annotation = ctx.forDocument(AnnotationToken, documentId);\n await annotation.armStamp({\n source: placement.bytes,\n preview: placement.preview\n ? { data: placement.preview.bytes, mimeType: placement.preview.mimeType }\n : undefined,\n intrinsicSize: asset.size,\n targetWidth: opts?.targetWidth,\n });\n };\n\n ctx.cleanup(() => {\n binaries.clear();\n libraryBinaries.clear();\n libraryMutationTails.clear();\n const ownedAssetEngine = typeof config.assetEngine === 'function' ? assetEngineRef : null;\n assetEngineRef = null;\n if (ownedAssetEngine) {\n void Promise.resolve(ownedAssetEngine)\n .then((engine) => engine.destroy())\n .catch(() => {});\n }\n });\n\n return {\n libraries: () => {\n const s = ctx.getState();\n return s.libraryOrder.map((id) => s.libraries[id]).filter((l) => l != null);\n },\n library: (id) => ctx.getState().libraries[id] ?? null,\n assets: (libraryId) => {\n const s = ctx.getState();\n if (libraryId) {\n const library = s.libraries[libraryId];\n return library ? library.assetIds.map((id) => s.assets[id]).filter((a) => a != null) : [];\n }\n return s.libraryOrder.flatMap((lid) =>\n (s.libraries[lid]?.assetIds ?? []).map((id) => s.assets[id]).filter((a) => a != null),\n );\n },\n asset: (id) => ctx.getState().assets[id] ?? null,\n assetPreview: (id) => binaries.get(id)?.preview ?? null,\n assetBytes: (id) => binaries.get(id)?.bytes ?? null,\n libraryBytes: (id) => libraryBinaries.get(id) ?? null,\n importLibraryPdf,\n addAsset,\n removeAsset,\n removeLibrary,\n armAsset,\n disarm: (documentId) => ctx.forDocument(AnnotationToken, documentId).disarmStamp(),\n };\n}\n","import type { StampAction, StampState } from './types';\n\nexport const initialStampState = (): StampState => ({\n libraries: {},\n libraryOrder: [],\n assets: {},\n});\n\n/** Pure and serializable (kernel rule 1) — descriptors only; the bytes and\n * previews live in the capability and never enter the store. */\nexport const stampReducer = (state: StampState, action: StampAction): StampState => {\n switch (action.type) {\n case 'LIBRARY_ADDED':\n return {\n ...state,\n libraries: { ...state.libraries, [action.library.id]: action.library },\n libraryOrder: [...state.libraryOrder, action.library.id],\n };\n case 'LIBRARY_REMOVED': {\n const library = state.libraries[action.libraryId];\n if (!library) return state;\n const libraries = { ...state.libraries };\n delete libraries[action.libraryId];\n const assets = { ...state.assets };\n for (const id of library.assetIds) delete assets[id];\n return {\n ...state,\n libraries,\n libraryOrder: state.libraryOrder.filter((id) => id !== action.libraryId),\n assets,\n };\n }\n case 'ASSET_ADDED': {\n const library = state.libraries[action.asset.libraryId];\n if (!library) return state;\n return {\n ...state,\n assets: { ...state.assets, [action.asset.id]: action.asset },\n libraries: {\n ...state.libraries,\n [library.id]: { ...library, assetIds: [...library.assetIds, action.asset.id] },\n },\n };\n }\n case 'ASSET_REMOVED': {\n const asset = state.assets[action.assetId];\n if (!asset) return state;\n const assets = { ...state.assets };\n delete assets[action.assetId];\n const library = state.libraries[asset.libraryId];\n return {\n ...state,\n assets,\n libraries: library\n ? {\n ...state.libraries,\n [library.id]: {\n ...library,\n assetIds: library.assetIds.filter((id) => id !== action.assetId),\n },\n }\n : state.libraries,\n };\n }\n default:\n return state;\n }\n};\n","import type { BinarySource, Engine } from '@embedpdf/engine-core/runtime';\nimport { createCapabilityToken } from '@embedpdf/core';\nimport type { FormScriptingOptions } from '@embedpdf/plugin-form';\n\n/**\n * The stamp plugin: a workspace-scoped ASSET substrate.\n *\n * The design law (\"documents have a home; assets ride the wire\"): imported\n * PDF libraries retain one canonical PDF whose catalog/page `/PieceInfo`\n * carries their metadata. Per-asset PDFs and previews are derived caches used\n * for placement. Standalone PNG/JPEG assets remain loose because the engine\n * intentionally has no raster-to-PDF-page authoring primitive.\n */\n\nexport type StampAssetKind = 'stamp' | 'signature' | 'initials';\n\n/**\n * One asset's SERIALIZABLE descriptor. The bytes and the cached preview are\n * deliberately NOT here — the reducer state stays pure/serializable (kernel\n * rule 1); binary lives in the capability and crosses only as call\n * arguments/returns, mirroring the engine's own BinarySource rule.\n */\nexport interface StampAsset {\n id: string;\n libraryId: string;\n kind: StampAssetKind;\n name: string;\n /** Intrinsic size in PDF points (the source page's crop box / image pixels 1:1). */\n size: { width: number; height: number };\n /** What the asset bytes are: a single-page vector PDF, or a raster image. */\n format: 'pdf' | 'png' | 'jpeg';\n /** Canonical library page identity; present for PDF-backed libraries. */\n pageObjectNumber?: number;\n subject?: string;\n categories?: string[];\n}\n\n/** A named group of assets — one imported PDF becomes one library. */\nexport interface StampLibrary {\n id: string;\n name: string;\n /** PDF-backed libraries own canonical bytes; loose libraries are raster/pre-sliced conveniences. */\n storage: 'canonical-pdf' | 'loose';\n categories?: string[];\n /** Asset ids in display order. */\n assetIds: string[];\n}\n\nexport interface StampState {\n libraries: Record<string, StampLibrary>;\n /** Library display order (insertion order). */\n libraryOrder: string[];\n assets: Record<string, StampAsset>;\n}\n\nexport type StampAction =\n | { type: 'LIBRARY_ADDED'; library: StampLibrary }\n | { type: 'LIBRARY_REMOVED'; libraryId: string }\n | { type: 'ASSET_ADDED'; asset: StampAsset }\n | { type: 'ASSET_REMOVED'; assetId: string };\n\nexport interface StampConfig {\n /**\n * The ASSET ENGINE port: any `Engine` that can open `{ kind: 'bytes' }` —\n * used only to slice an imported library PDF into per-page assets and\n * render their previews.\n *\n * Omitted → the kernel's own engine is used, which is exactly right for a\n * local deployment (same WASM instance, zero extra cost). In a CLOUD\n * deployment the kernel engine cannot open local bytes, so pass a factory —\n * it is called (and memoized) on the first import, never at viewer boot:\n *\n * ```ts\n * stampPlugin({\n * assetEngine: () => import('@embedpdf/engine').then((m) => m.createLocalEngine()),\n * })\n * ```\n */\n assetEngine?: Engine | (() => Engine | Promise<Engine>);\n /** Cached preview width in device px (import-time render). Default 256. */\n previewWidth?: number;\n /**\n * Opt-in Acrobat JavaScript evaluation for form-backed PDF stamp assets.\n * On arm, the plugin recalculates a temporary copy using the target\n * document's identity/name/clock, flattens it, and arms the resulting\n * static page. Canonical library and derived base bytes stay unchanged.\n */\n scripting?: FormScriptingOptions;\n}\n\nexport interface ImportLibraryOptions {\n /** Library display name. Default `'Stamps'`. */\n name?: string;\n /** Library categories written to catalog `/PieceInfo`. */\n categories?: string[];\n /** Kind stamped onto every imported asset. Default `'stamp'`. */\n kind?: StampAssetKind;\n /** Per-page asset names; default `Stamp <n>`. */\n assetName?: (pageIndex: number) => string;\n}\n\nexport interface AddAssetInput {\n /** Target library; omitted → a new single-asset library named after the asset. */\n libraryId?: string;\n name: string;\n kind?: StampAssetKind;\n subject?: string;\n categories?: string[];\n /** Single-page PDF (vector) or PNG/JPEG bytes. */\n source: BinarySource;\n /**\n * Paintable preview for pickers + the hover ghost. Loose PDF assets cannot\n * derive one without opening the PDF; canonical libraries render it after\n * insertion. Raster sources default to their own bytes.\n */\n preview?: BinarySource;\n /** Intrinsic size in PDF points. Required for PDF sources; rasters are sniffed. */\n size?: { width: number; height: number };\n}\n\n/** A cached, browser-paintable render of an asset (PNG from import; raster assets as-is). */\nexport interface StampAssetPreview {\n bytes: Uint8Array;\n mimeType: string;\n}\n\nexport interface StampCapability {\n // ── selectors (pure reads over serializable state) ──\n libraries(): StampLibrary[];\n library(id: string): StampLibrary | null;\n /** Assets of one library, in library order — or every asset when omitted. */\n assets(libraryId?: string): StampAsset[];\n asset(id: string): StampAsset | null;\n // ── binary reads (capability-held, never store state) ──\n /** The asset's paintable preview, or null while none is cached. */\n assetPreview(id: string): StampAssetPreview | null;\n /** Placement bytes; derived from the canonical page for PDF-backed libraries. */\n assetBytes(id: string): Uint8Array | null;\n /** Canonical library PDF bytes, or null for a loose library/unknown id. */\n libraryBytes(id: string): Uint8Array | null;\n // ── library intents ──\n /**\n * Import a PDF as a stamp library: every page becomes one vector asset\n * (single-page PDF bytes + a cached preview render). Uses the asset\n * engine; in a cloud deployment without one configured this rejects with\n * an actionable error. Resolves to the new library id.\n */\n importLibraryPdf(source: BinarySource, opts?: ImportLibraryOptions): Promise<string>;\n /**\n * Add a single asset. A PDF added to a canonical library is inserted as a\n * page and receives `/PieceInfo`; loose assets keep their bytes directly.\n * Raster input cannot be appended to a canonical PDF library.\n */\n addAsset(input: AddAssetInput): Promise<string>;\n /** Remove an asset, deleting its canonical page before state changes when PDF-backed. */\n removeAsset(id: string): Promise<void>;\n /** Remove a library and every asset in it, ordered with in-flight library mutations. */\n removeLibrary(id: string): Promise<void>;\n // ── placement (delegates to the annotation plugin of the named document) ──\n /**\n * Arm an asset on a document: the next click on that document's pages\n * places it (and the hover ghost previews the exact placement). With\n * scripting enabled, form-backed PDFs are evaluated against that target\n * document and flattened first. Rides `annotation.armStamp` — bytes,\n * preview, and intrinsic size all travel along, so vector stamps keep\n * their true aspect.\n */\n armAsset(documentId: string, assetId: string, opts?: { targetWidth?: number }): Promise<void>;\n /** Disarm the stamp tool on a document. */\n disarm(documentId: string): void;\n}\n\nexport const StampToken = createCapabilityToken<StampCapability>('stamp');\n","import { definePlugin } from '@embedpdf/core';\nimport { createStampCapability } from './capability';\nimport { initialStampState, stampReducer } from './reducer';\nimport { StampToken } from './types';\nimport type { StampAction, StampCapability, StampConfig, StampState } from './types';\n\n/**\n * The stamp plugin. WORKSPACE-scoped: libraries are shared across every open\n * document; placement names its document explicitly (`armAsset(documentId, …)`)\n * and delegates to that document's annotation plugin — no hard `requires`,\n * because the annotation token is document-scoped and resolved lazily per\n * placement (a viewer without the annotation plugin fails at the arm call,\n * with the kernel's own missing-capability error).\n */\nexport const stampPlugin = (config: StampConfig = {}) =>\n definePlugin<StampState, StampAction, StampCapability>({\n id: 'stamp',\n token: StampToken,\n scope: 'workspace',\n initialState: initialStampState,\n reduce: stampReducer,\n capability: (ctx) => createStampCapability(ctx, config),\n });\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -124,7 +124,7 @@ function createStampCapability(ctx, config = {}) {
124
124
  const doc = await openAssetDocument(new Uint8Array(resolved.bytes));
125
125
  let imported;
126
126
  try {
127
- if (!doc.pieceInfo || !doc.pages.extract) throw new EngineError(EngineErrorCode.NotImplemented, "[stamp] canonical PDF libraries need an asset engine with pieceInfo and pages.extract");
127
+ if (!doc.pieceInfo) throw new EngineError(EngineErrorCode.NotImplemented, "[stamp] canonical PDF libraries need an asset engine with pieceInfo");
128
128
  const snapshot = await doc.pages.list();
129
129
  if (snapshot.pageCount === 0) throw new EngineError(EngineErrorCode.InvalidArg, "[stamp] a canonical stamp library PDF must contain at least one page");
130
130
  const pages = snapshot.pages.map((layout) => {
@@ -245,7 +245,6 @@ function createStampCapability(ctx, config = {}) {
245
245
  const doc = await openAssetDocument(canonicalBytes);
246
246
  let appended;
247
247
  try {
248
- if (!doc.pages.insert || !doc.pages.extract) throw new EngineError(EngineErrorCode.NotImplemented, "[stamp] appending to a canonical library needs pages.insert and pages.extract");
249
248
  const result = await doc.pages.insert(new Uint8Array(resolved.bytes));
250
249
  if (result.insertedPageObjectNumbers.length !== 1) throw new EngineError(EngineErrorCode.InvalidArg, "[stamp] a canonical library asset must be a single-page PDF");
251
250
  const pageObjectNumber = result.insertedPageObjectNumbers[0];
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/capability.ts","../src/reducer.ts","../src/types.ts","../src/stamp.plugin.ts"],"sourcesContent":["import {\n EngineError,\n EngineErrorCode,\n resolveBinarySource,\n sniffBinaryMetadata,\n type BinarySource,\n type DocumentHandle,\n type Engine,\n type PageImageHandle,\n type PieceInfoEntry,\n type PieceInfoPatch,\n} from '@embedpdf/engine-core/runtime';\nimport { type PluginContext } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation';\nimport { createFormScriptingController, type FormCommitResult } from '@embedpdf/plugin-form';\n\nimport type {\n AddAssetInput,\n ImportLibraryOptions,\n StampAction,\n StampAsset,\n StampAssetPreview,\n StampCapability,\n StampConfig,\n StampLibrary,\n StampAssetKind,\n StampState,\n} from './types';\n\nconst DEFAULT_PREVIEW_WIDTH = 256;\nconst LIBRARY_PIECEINFO_APP = 'EMBD_StampLibrary';\nconst STAMP_PIECEINFO_APP = 'EMBD_Stamp';\nconst STAMP_SCHEMA_VERSION = 1;\n\n/** Session-unique ids. Assets are session-scoped for now (no persistence),\n * so a timestamp + counter is enough — durable ids come with the store port. */\nlet seq = 0;\nconst uid = (prefix: string): string =>\n `${prefix}-${Date.now().toString(36)}-${(seq++).toString(36)}`;\n\nconst entryString = (entries: Record<string, PieceInfoEntry>, key: string): string | undefined => {\n const entry = entries[key];\n return entry?.type === 'string' && entry.value.length > 0 ? entry.value : undefined;\n};\n\nconst entryName = (entries: Record<string, PieceInfoEntry>, key: string): string | undefined => {\n const entry = entries[key];\n return entry?.type === 'name' && entry.value.length > 0 ? entry.value : undefined;\n};\n\nconst entryStringArray = (\n entries: Record<string, PieceInfoEntry>,\n key: string,\n): string[] | undefined => {\n const entry = entries[key];\n return entry?.type === 'string-array' ? [...entry.value] : undefined;\n};\n\nconst kindToPdfName = (kind: StampAssetKind): string =>\n kind === 'signature' ? 'Signature' : kind === 'initials' ? 'Initials' : 'Stamp';\n\nconst kindFromPdfName = (name: string | undefined): StampAssetKind | undefined => {\n switch (name?.toLowerCase()) {\n case 'stamp':\n return 'stamp';\n case 'signature':\n return 'signature';\n case 'initials':\n return 'initials';\n default:\n return undefined;\n }\n};\n\nconst metadataPatch = (\n id: string,\n name: string,\n kind: StampAssetKind,\n subject?: string,\n categories?: readonly string[],\n): PieceInfoPatch => ({\n Version: STAMP_SCHEMA_VERSION,\n Id: id,\n Name: name,\n Kind: { name: kindToPdfName(kind) },\n Subject: subject ?? null,\n Categories: categories ?? null,\n});\n\nconst libraryMetadataPatch = (\n id: string,\n name: string,\n categories?: readonly string[],\n): PieceInfoPatch => ({\n Version: STAMP_SCHEMA_VERSION,\n Id: id,\n Name: name,\n Kind: { name: 'StampLibrary' },\n Categories: categories ?? null,\n});\n\nexport function createStampCapability(\n ctx: PluginContext<StampState, StampAction>,\n config: StampConfig = {},\n): StampCapability {\n /** Binary sidecar of the serializable store: asset bytes + cached preview,\n * keyed by asset id. The reducer never sees these (kernel rule 1). */\n const binaries = new Map<string, { bytes: Uint8Array; preview: StampAssetPreview | null }>();\n /** The durable source of truth for a canonical library. Asset PDFs above\n * are derived page extractions; this map owns the rewritten whole PDF. */\n const libraryBinaries = new Map<string, Uint8Array>();\n /** Whole-PDF rewrites must be serialized per library or two concurrent\n * appends could both start from the same bytes and lose one page. */\n const libraryMutationTails = new Map<string, Promise<void>>();\n\n const mutateLibrary = <T>(libraryId: string, mutation: () => Promise<T>): Promise<T> => {\n const previous = libraryMutationTails.get(libraryId) ?? Promise.resolve();\n const result = previous.then(mutation);\n const tail = result.then(\n () => undefined,\n () => undefined,\n );\n libraryMutationTails.set(libraryId, tail);\n return result.finally(() => {\n if (libraryMutationTails.get(libraryId) === tail) libraryMutationTails.delete(libraryId);\n });\n };\n\n // The ASSET ENGINE port. A configured factory is called (and memoized) on\n // the first import, not at viewer start; a configured instance is used\n // as-is; nothing configured falls back to the kernel's engine — correct for\n // local deployments, and rejected with an actionable error by cloud engines\n // at the first `open({ kind: 'bytes' })`.\n let assetEngineRef: Engine | Promise<Engine> | null = null;\n const assetEngine = (): Engine | Promise<Engine> => {\n if (!assetEngineRef) {\n const cfg = config.assetEngine;\n assetEngineRef = !cfg ? ctx.engine : typeof cfg === 'function' ? cfg() : cfg;\n }\n return assetEngineRef;\n };\n\n const openAssetDocument = async (\n bytes: Uint8Array,\n identity?: DocumentHandle['security']['identity'],\n ): Promise<DocumentHandle> => {\n try {\n return await (\n await assetEngine()\n ).open(\n { kind: 'bytes', id: uid('stamp-import'), bytes },\n { scope: ['*'], ...(identity ? { identity } : {}) },\n );\n } catch (err) {\n // A cloud kernel engine rejects 'bytes' with InvalidArg — turn the\n // generic contract error into the configuration fix.\n if (!config.assetEngine && EngineError.is(err, EngineErrorCode.InvalidArg)) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n \"[stamp] importing a library PDF needs an engine that can open local bytes, and this viewer's engine cannot (cloud). Pass stampPlugin({ assetEngine: () => import('@embedpdf/engine').then((m) => m.createLocalEngine()) }) — it loads lazily, on first import.\",\n );\n }\n throw err;\n }\n };\n\n /** Import-time preview render → bytes. The asset engine is local by\n * definition, so the image source is always inline bytes. */\n const imageToPreview = (image: PageImageHandle): StampAssetPreview => {\n if (image.source.kind !== 'bytes') {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] asset engine returned a URL-sourced render; asset engines must be local',\n );\n }\n return { bytes: image.source.bytes, mimeType: image.contentType };\n };\n\n const allocateId = (\n preferred: string | undefined,\n prefix: string,\n taken: Set<string>,\n ): string => {\n let id = preferred;\n if (!id || taken.has(id)) {\n do id = uid(prefix);\n while (taken.has(id));\n }\n taken.add(id);\n return id;\n };\n\n const createLooseLibrary = (name: string): string => {\n const id = uid('stamp-lib');\n ctx.dispatch({\n type: 'LIBRARY_ADDED',\n library: { id, name, storage: 'loose', assetIds: [] },\n });\n return id;\n };\n\n const importLibraryPdf = async (\n source: BinarySource,\n opts?: ImportLibraryOptions,\n ): Promise<string> => {\n const resolved = await resolveBinarySource(source);\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (meta?.mimeType !== 'application/pdf') {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] importLibraryPdf needs PDF bytes (use addAsset for a raster image)',\n );\n }\n const doc = await openAssetDocument(new Uint8Array(resolved.bytes));\n let imported:\n | {\n library: StampLibrary;\n canonicalBytes: Uint8Array;\n assets: Array<{\n asset: StampAsset;\n bytes: Uint8Array;\n preview: StampAssetPreview;\n }>;\n }\n | undefined;\n try {\n if (!doc.pieceInfo || !doc.pages.extract) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] canonical PDF libraries need an asset engine with pieceInfo and pages.extract',\n );\n }\n const snapshot = await doc.pages.list();\n if (snapshot.pageCount === 0) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] a canonical stamp library PDF must contain at least one page',\n );\n }\n\n // Discover and validate every required service before the first write.\n const pages = snapshot.pages.map((layout) => {\n const handle = doc.page(layout.pageObjectNumber);\n if (!handle.pieceInfo) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] canonical PDF libraries need page pieceInfo support',\n );\n }\n return {\n layout,\n handle,\n metadata: null as Awaited<ReturnType<typeof handle.pieceInfo.read>>,\n };\n });\n\n const catalogMetadata = await doc.pieceInfo.read(LIBRARY_PIECEINFO_APP);\n for (const page of pages) {\n page.metadata = await page.handle.pieceInfo!.read(STAMP_PIECEINFO_APP);\n }\n\n const state = ctx.getState();\n const takenLibraryIds = new Set(Object.keys(state.libraries));\n const takenAssetIds = new Set(Object.keys(state.assets));\n const catalogEntries = catalogMetadata?.entries ?? {};\n const libraryId = allocateId(entryString(catalogEntries, 'Id'), 'stamp-lib', takenLibraryIds);\n const libraryName = opts?.name ?? entryString(catalogEntries, 'Name') ?? 'Stamps';\n const libraryCategories = opts?.categories ?? entryStringArray(catalogEntries, 'Categories');\n\n const descriptors = pages.map(({ layout, handle, metadata: pageMetadata }) => {\n const entries = pageMetadata?.entries ?? {};\n const id = allocateId(entryString(entries, 'Id'), 'stamp', takenAssetIds);\n const kind = opts?.kind ?? kindFromPdfName(entryName(entries, 'Kind')) ?? 'stamp';\n return {\n handle,\n asset: {\n id,\n libraryId,\n kind,\n name:\n opts?.assetName?.(layout.index) ??\n entryString(entries, 'Name') ??\n `Stamp ${layout.index + 1}`,\n size: { width: layout.size.width, height: layout.size.height },\n format: 'pdf' as const,\n pageObjectNumber: layout.pageObjectNumber,\n subject: entryString(entries, 'Subject'),\n categories: entryStringArray(entries, 'Categories'),\n },\n };\n });\n\n await doc.pieceInfo.update(\n LIBRARY_PIECEINFO_APP,\n libraryMetadataPatch(libraryId, libraryName, libraryCategories),\n );\n\n const assets: NonNullable<typeof imported>['assets'] = [];\n for (const descriptor of descriptors) {\n const { asset, handle } = descriptor;\n await handle.pieceInfo!.update(\n STAMP_PIECEINFO_APP,\n metadataPatch(asset.id, asset.name, asset.kind, asset.subject, asset.categories),\n );\n // One canonical page → one derived placement PDF plus a transparent\n // preview. Extract after metadata so the cache carries the same id.\n const bytes = await doc.pages.extract([asset.pageObjectNumber!]);\n const image = await handle.render.image({\n viewport: { kind: 'width', width: config.previewWidth ?? DEFAULT_PREVIEW_WIDTH },\n background: 'transparent',\n includeAnnotations: true,\n format: 'png',\n });\n assets.push({ asset, bytes, preview: imageToPreview(image) });\n }\n\n imported = {\n library: {\n id: libraryId,\n name: libraryName,\n storage: 'canonical-pdf',\n categories: libraryCategories,\n assetIds: [],\n },\n canonicalBytes: await doc.download(),\n assets,\n };\n } finally {\n await doc.close();\n }\n\n libraryBinaries.set(imported.library.id, imported.canonicalBytes);\n ctx.dispatch({ type: 'LIBRARY_ADDED', library: imported.library });\n for (const { asset, bytes, preview } of imported.assets) {\n binaries.set(asset.id, { bytes, preview });\n ctx.dispatch({ type: 'ASSET_ADDED', asset });\n }\n return imported.library.id;\n };\n\n const addAsset = async (input: AddAssetInput): Promise<string> => {\n const targetLibrary = input.libraryId\n ? (ctx.getState().libraries[input.libraryId] ?? null)\n : null;\n if (input.libraryId && !targetLibrary) {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] unknown library '${input.libraryId}'`,\n );\n }\n const resolved = await resolveBinarySource(input.source);\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (!meta) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] asset source must be PNG, JPEG, or single-page PDF bytes',\n );\n }\n const isPdf = meta.mimeType === 'application/pdf';\n\n let suppliedPreview: StampAssetPreview | null = null;\n if (input.preview) {\n const preview = await resolveBinarySource(input.preview);\n suppliedPreview = {\n bytes: new Uint8Array(preview.bytes),\n mimeType: preview.mimeType ?? 'image/png',\n };\n }\n\n if (targetLibrary?.storage === 'canonical-pdf') {\n if (!isPdf) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] raster assets cannot be appended to a canonical PDF library',\n );\n }\n return mutateLibrary(targetLibrary.id, async () => {\n const liveLibrary = ctx.getState().libraries[targetLibrary.id];\n if (liveLibrary?.storage !== 'canonical-pdf') {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] canonical library '${targetLibrary.id}' no longer exists`,\n );\n }\n const canonicalBytes = libraryBinaries.get(liveLibrary.id);\n if (!canonicalBytes) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] canonical bytes are missing for library '${liveLibrary.id}'`,\n );\n }\n\n const assetId = uid('stamp');\n const doc = await openAssetDocument(canonicalBytes);\n let appended:\n | {\n asset: StampAsset;\n bytes: Uint8Array;\n preview: StampAssetPreview;\n canonical: Uint8Array;\n }\n | undefined;\n try {\n if (!doc.pages.insert || !doc.pages.extract) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] appending to a canonical library needs pages.insert and pages.extract',\n );\n }\n const result = await doc.pages.insert(new Uint8Array(resolved.bytes));\n if (result.insertedPageObjectNumbers.length !== 1) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] a canonical library asset must be a single-page PDF',\n );\n }\n const pageObjectNumber = result.insertedPageObjectNumbers[0];\n const layout = result.layout.pages.find(\n (candidate) => candidate.pageObjectNumber === pageObjectNumber,\n );\n const page = doc.page(pageObjectNumber);\n if (!layout || !page.pieceInfo) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] canonical PDF libraries need page layout and pieceInfo support',\n );\n }\n const asset: StampAsset = {\n id: assetId,\n libraryId: liveLibrary.id,\n kind: input.kind ?? 'stamp',\n name: input.name,\n size: { width: layout.size.width, height: layout.size.height },\n format: 'pdf',\n pageObjectNumber,\n subject: input.subject,\n categories: input.categories,\n };\n await page.pieceInfo.update(\n STAMP_PIECEINFO_APP,\n metadataPatch(asset.id, asset.name, asset.kind, asset.subject, asset.categories),\n );\n const bytes = await doc.pages.extract([pageObjectNumber]);\n let preview = suppliedPreview;\n if (!preview) {\n preview = imageToPreview(\n await page.render.image({\n viewport: { kind: 'width', width: config.previewWidth ?? DEFAULT_PREVIEW_WIDTH },\n background: 'transparent',\n includeAnnotations: true,\n format: 'png',\n }),\n );\n }\n appended = { asset, bytes, preview, canonical: await doc.download() };\n } finally {\n await doc.close();\n }\n\n libraryBinaries.set(liveLibrary.id, appended.canonical);\n binaries.set(appended.asset.id, { bytes: appended.bytes, preview: appended.preview });\n ctx.dispatch({ type: 'ASSET_ADDED', asset: appended.asset });\n return appended.asset.id;\n });\n }\n\n const size =\n input.size ?? ('width' in meta ? { width: meta.width, height: meta.height } : null);\n if (!size) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] a PDF asset needs `size` (its page size in points) — PDF bytes carry no sniffable dimensions',\n );\n }\n let preview = suppliedPreview;\n if (!preview && !isPdf) {\n preview = { bytes: new Uint8Array(resolved.bytes), mimeType: meta.mimeType };\n }\n const commitLooseAsset = (libraryId: string): string => {\n const asset: StampAsset = {\n id: uid('stamp'),\n libraryId,\n kind: input.kind ?? 'stamp',\n name: input.name,\n size,\n format: isPdf ? 'pdf' : meta.mimeType === 'image/png' ? 'png' : 'jpeg',\n subject: input.subject,\n categories: input.categories,\n };\n binaries.set(asset.id, { bytes: new Uint8Array(resolved.bytes), preview });\n ctx.dispatch({ type: 'ASSET_ADDED', asset });\n return asset.id;\n };\n if (!targetLibrary) return commitLooseAsset(createLooseLibrary(input.name));\n return mutateLibrary(targetLibrary.id, async () => {\n const liveLibrary = ctx.getState().libraries[targetLibrary.id];\n if (liveLibrary?.storage !== 'loose') {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] loose library '${targetLibrary.id}' no longer exists`,\n );\n }\n return commitLooseAsset(liveLibrary.id);\n });\n };\n\n const dropLibrary = (id: string): void => {\n const library = ctx.getState().libraries[id];\n if (library) for (const assetId of library.assetIds) binaries.delete(assetId);\n libraryBinaries.delete(id);\n ctx.dispatch({ type: 'LIBRARY_REMOVED', libraryId: id });\n };\n\n const removeAsset = async (id: string): Promise<void> => {\n const initialAsset = ctx.getState().assets[id];\n if (!initialAsset) return;\n return mutateLibrary(initialAsset.libraryId, async () => {\n const asset = ctx.getState().assets[id];\n if (!asset) return;\n const library = ctx.getState().libraries[asset.libraryId];\n if (library?.storage === 'canonical-pdf') {\n if (library.assetIds.length === 1) {\n dropLibrary(library.id);\n return;\n }\n if (asset.pageObjectNumber === undefined) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] canonical asset '${id}' has no page object number`,\n );\n }\n const canonicalBytes = libraryBinaries.get(library.id);\n if (!canonicalBytes) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] canonical bytes are missing for library '${library.id}'`,\n );\n }\n const doc = await openAssetDocument(canonicalBytes);\n let rewritten: Uint8Array | undefined;\n try {\n await doc.pages.delete([asset.pageObjectNumber]);\n rewritten = await doc.download();\n } finally {\n await doc.close();\n }\n libraryBinaries.set(library.id, rewritten);\n }\n binaries.delete(id);\n ctx.dispatch({ type: 'ASSET_REMOVED', assetId: id });\n });\n };\n\n const removeLibrary = (id: string): Promise<void> =>\n mutateLibrary(id, async () => dropLibrary(id));\n\n const surfaceScriptingResult = (result: FormCommitResult): void => {\n try {\n for (const effect of result.uiEffects) config.scripting?.onUiEffect?.(effect);\n for (const diagnostic of result.diagnostics) {\n config.scripting?.onDiagnostic?.(diagnostic);\n }\n if (result.error) config.scripting?.onError?.(result.error);\n } catch (error) {\n globalThis.console?.error('[stamp] scripting observer failed:', error);\n }\n };\n\n /**\n * Form-backed stamps are executable templates only until placement. Work\n * on an isolated copy so neither the canonical library nor its reusable\n * per-page extraction becomes target/user/time specific.\n */\n const materializeForPlacement = async (\n documentId: string,\n asset: StampAsset,\n bin: { bytes: Uint8Array; preview: StampAssetPreview | null },\n ): Promise<{ bytes: Uint8Array; preview: StampAssetPreview | null }> => {\n if (asset.format !== 'pdf' || !config.scripting?.enabled) return bin;\n\n const targetDoc = ctx.documentHandle(documentId);\n const targetMeta = ctx.core().documents[documentId] ?? null;\n if (!targetDoc || !targetMeta) {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] target document '${documentId}' is not open`,\n );\n }\n\n // A page extraction intentionally does not retain catalog-owned AcroForm\n // and action structures. Canonical assets therefore evaluate from the\n // whole library PDF, then extract only their selected page after flatten.\n const canonicalBytes = libraryBinaries.get(asset.libraryId);\n const sourceBytes = canonicalBytes ?? bin.bytes;\n const doc = await openAssetDocument(new Uint8Array(sourceBytes), targetDoc.security.identity);\n let scripting: ReturnType<typeof createFormScriptingController> | null = null;\n try {\n const layout = await doc.pages.list();\n const selectedPage =\n asset.pageObjectNumber === undefined\n ? layout.pageCount === 1\n ? layout.pages[0]\n : undefined\n : layout.pages.find(\n ({ pageObjectNumber }) => pageObjectNumber === asset.pageObjectNumber,\n );\n if (!selectedPage) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n canonicalBytes\n ? `[stamp] canonical page ${asset.pageObjectNumber ?? 'unknown'} no longer exists`\n : '[stamp] a loose dynamic stamp asset must contain exactly one page',\n );\n }\n const snapshot = await doc.forms.list();\n const hasSelectedPageField = snapshot.fields.some((field) =>\n field.widgets.some(\n ({ pageObjectNumber }) => pageObjectNumber === selectedPage.pageObjectNumber,\n ),\n );\n if (!hasSelectedPageField) return bin;\n if (!doc.pages.flatten || !doc.pages.extract) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] dynamic PDF stamps need an asset engine with pages.flatten and pages.extract',\n );\n }\n\n const scriptingConfig = config.scripting;\n scripting = createFormScriptingController({\n doc,\n document: () => targetMeta,\n config: scriptingConfig,\n sandboxFactory:\n scriptingConfig.sandboxFactory ??\n (() =>\n import('@embedpdf/core-js-sandbox').then(({ createQuickJsSandbox }) =>\n createQuickJsSandbox(),\n )),\n });\n const result = await scripting.recalculate(snapshot);\n surfaceScriptingResult(result);\n if (result.status === 'failed') {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] dynamic stamp scripting failed: ${result.error?.message ?? 'native form effect failed'}`,\n );\n }\n\n const pageObjectNumber = selectedPage.pageObjectNumber;\n const flattened = await doc.pages.flatten([pageObjectNumber], 'display');\n const failed = flattened.results.find(\n ({ status }) => status === 'failed' || status === 'skipped',\n );\n if (failed) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] dynamic stamp flatten failed for page ${failed.pageObjectNumber}`,\n );\n }\n\n const bytes = await doc.pages.extract([pageObjectNumber]);\n const image = await doc.page(pageObjectNumber).render.image({\n viewport: { kind: 'width', width: config.previewWidth ?? DEFAULT_PREVIEW_WIDTH },\n background: 'transparent',\n includeAnnotations: false,\n format: 'png',\n });\n return { bytes, preview: imageToPreview(image) };\n } finally {\n scripting?.dispose();\n await doc.close();\n }\n };\n\n const armAsset = async (\n documentId: string,\n assetId: string,\n opts?: { targetWidth?: number },\n ): Promise<void> => {\n const asset = ctx.getState().assets[assetId];\n const bin = binaries.get(assetId);\n if (!asset || !bin) {\n throw new EngineError(EngineErrorCode.NotFound, `[stamp] unknown asset '${assetId}'`);\n }\n const placement = await materializeForPlacement(documentId, asset, bin);\n // The placement itself remains one armStamp call. Dynamic evaluation,\n // when enabled and applicable, has already produced an ephemeral static\n // page and matching preview at this boundary.\n const annotation = ctx.forDocument(AnnotationToken, documentId);\n await annotation.armStamp({\n source: placement.bytes,\n preview: placement.preview\n ? { data: placement.preview.bytes, mimeType: placement.preview.mimeType }\n : undefined,\n intrinsicSize: asset.size,\n targetWidth: opts?.targetWidth,\n });\n };\n\n ctx.cleanup(() => {\n binaries.clear();\n libraryBinaries.clear();\n libraryMutationTails.clear();\n const ownedAssetEngine = typeof config.assetEngine === 'function' ? assetEngineRef : null;\n assetEngineRef = null;\n if (ownedAssetEngine) {\n void Promise.resolve(ownedAssetEngine)\n .then((engine) => engine.destroy())\n .catch(() => {});\n }\n });\n\n return {\n libraries: () => {\n const s = ctx.getState();\n return s.libraryOrder.map((id) => s.libraries[id]).filter((l) => l != null);\n },\n library: (id) => ctx.getState().libraries[id] ?? null,\n assets: (libraryId) => {\n const s = ctx.getState();\n if (libraryId) {\n const library = s.libraries[libraryId];\n return library ? library.assetIds.map((id) => s.assets[id]).filter((a) => a != null) : [];\n }\n return s.libraryOrder.flatMap((lid) =>\n (s.libraries[lid]?.assetIds ?? []).map((id) => s.assets[id]).filter((a) => a != null),\n );\n },\n asset: (id) => ctx.getState().assets[id] ?? null,\n assetPreview: (id) => binaries.get(id)?.preview ?? null,\n assetBytes: (id) => binaries.get(id)?.bytes ?? null,\n libraryBytes: (id) => libraryBinaries.get(id) ?? null,\n importLibraryPdf,\n addAsset,\n removeAsset,\n removeLibrary,\n armAsset,\n disarm: (documentId) => ctx.forDocument(AnnotationToken, documentId).disarmStamp(),\n };\n}\n","import type { StampAction, StampState } from './types';\n\nexport const initialStampState = (): StampState => ({\n libraries: {},\n libraryOrder: [],\n assets: {},\n});\n\n/** Pure and serializable (kernel rule 1) — descriptors only; the bytes and\n * previews live in the capability and never enter the store. */\nexport const stampReducer = (state: StampState, action: StampAction): StampState => {\n switch (action.type) {\n case 'LIBRARY_ADDED':\n return {\n ...state,\n libraries: { ...state.libraries, [action.library.id]: action.library },\n libraryOrder: [...state.libraryOrder, action.library.id],\n };\n case 'LIBRARY_REMOVED': {\n const library = state.libraries[action.libraryId];\n if (!library) return state;\n const libraries = { ...state.libraries };\n delete libraries[action.libraryId];\n const assets = { ...state.assets };\n for (const id of library.assetIds) delete assets[id];\n return {\n ...state,\n libraries,\n libraryOrder: state.libraryOrder.filter((id) => id !== action.libraryId),\n assets,\n };\n }\n case 'ASSET_ADDED': {\n const library = state.libraries[action.asset.libraryId];\n if (!library) return state;\n return {\n ...state,\n assets: { ...state.assets, [action.asset.id]: action.asset },\n libraries: {\n ...state.libraries,\n [library.id]: { ...library, assetIds: [...library.assetIds, action.asset.id] },\n },\n };\n }\n case 'ASSET_REMOVED': {\n const asset = state.assets[action.assetId];\n if (!asset) return state;\n const assets = { ...state.assets };\n delete assets[action.assetId];\n const library = state.libraries[asset.libraryId];\n return {\n ...state,\n assets,\n libraries: library\n ? {\n ...state.libraries,\n [library.id]: {\n ...library,\n assetIds: library.assetIds.filter((id) => id !== action.assetId),\n },\n }\n : state.libraries,\n };\n }\n default:\n return state;\n }\n};\n","import type { BinarySource, Engine } from '@embedpdf/engine-core/runtime';\nimport { createCapabilityToken } from '@embedpdf/core';\nimport type { FormScriptingOptions } from '@embedpdf/plugin-form';\n\n/**\n * The stamp plugin: a workspace-scoped ASSET substrate.\n *\n * The design law (\"documents have a home; assets ride the wire\"): imported\n * PDF libraries retain one canonical PDF whose catalog/page `/PieceInfo`\n * carries their metadata. Per-asset PDFs and previews are derived caches used\n * for placement. Standalone PNG/JPEG assets remain loose because the engine\n * intentionally has no raster-to-PDF-page authoring primitive.\n */\n\nexport type StampAssetKind = 'stamp' | 'signature' | 'initials';\n\n/**\n * One asset's SERIALIZABLE descriptor. The bytes and the cached preview are\n * deliberately NOT here — the reducer state stays pure/serializable (kernel\n * rule 1); binary lives in the capability and crosses only as call\n * arguments/returns, mirroring the engine's own BinarySource rule.\n */\nexport interface StampAsset {\n id: string;\n libraryId: string;\n kind: StampAssetKind;\n name: string;\n /** Intrinsic size in PDF points (the source page's crop box / image pixels 1:1). */\n size: { width: number; height: number };\n /** What the asset bytes are: a single-page vector PDF, or a raster image. */\n format: 'pdf' | 'png' | 'jpeg';\n /** Canonical library page identity; present for PDF-backed libraries. */\n pageObjectNumber?: number;\n subject?: string;\n categories?: string[];\n}\n\n/** A named group of assets — one imported PDF becomes one library. */\nexport interface StampLibrary {\n id: string;\n name: string;\n /** PDF-backed libraries own canonical bytes; loose libraries are raster/pre-sliced conveniences. */\n storage: 'canonical-pdf' | 'loose';\n categories?: string[];\n /** Asset ids in display order. */\n assetIds: string[];\n}\n\nexport interface StampState {\n libraries: Record<string, StampLibrary>;\n /** Library display order (insertion order). */\n libraryOrder: string[];\n assets: Record<string, StampAsset>;\n}\n\nexport type StampAction =\n | { type: 'LIBRARY_ADDED'; library: StampLibrary }\n | { type: 'LIBRARY_REMOVED'; libraryId: string }\n | { type: 'ASSET_ADDED'; asset: StampAsset }\n | { type: 'ASSET_REMOVED'; assetId: string };\n\nexport interface StampConfig {\n /**\n * The ASSET ENGINE port: any `Engine` that can open `{ kind: 'bytes' }` —\n * used only to slice an imported library PDF into per-page assets and\n * render their previews.\n *\n * Omitted → the kernel's own engine is used, which is exactly right for a\n * local deployment (same WASM instance, zero extra cost). In a CLOUD\n * deployment the kernel engine cannot open local bytes, so pass a factory —\n * it is called (and memoized) on the first import, never at viewer boot:\n *\n * ```ts\n * stampPlugin({\n * assetEngine: () => import('@embedpdf/engine').then((m) => m.createLocalEngine()),\n * })\n * ```\n */\n assetEngine?: Engine | (() => Engine | Promise<Engine>);\n /** Cached preview width in device px (import-time render). Default 256. */\n previewWidth?: number;\n /**\n * Opt-in Acrobat JavaScript evaluation for form-backed PDF stamp assets.\n * On arm, the plugin recalculates a temporary copy using the target\n * document's identity/name/clock, flattens it, and arms the resulting\n * static page. Canonical library and derived base bytes stay unchanged.\n */\n scripting?: FormScriptingOptions;\n}\n\nexport interface ImportLibraryOptions {\n /** Library display name. Default `'Stamps'`. */\n name?: string;\n /** Library categories written to catalog `/PieceInfo`. */\n categories?: string[];\n /** Kind stamped onto every imported asset. Default `'stamp'`. */\n kind?: StampAssetKind;\n /** Per-page asset names; default `Stamp <n>`. */\n assetName?: (pageIndex: number) => string;\n}\n\nexport interface AddAssetInput {\n /** Target library; omitted → a new single-asset library named after the asset. */\n libraryId?: string;\n name: string;\n kind?: StampAssetKind;\n subject?: string;\n categories?: string[];\n /** Single-page PDF (vector) or PNG/JPEG bytes. */\n source: BinarySource;\n /**\n * Paintable preview for pickers + the hover ghost. Loose PDF assets cannot\n * derive one without opening the PDF; canonical libraries render it after\n * insertion. Raster sources default to their own bytes.\n */\n preview?: BinarySource;\n /** Intrinsic size in PDF points. Required for PDF sources; rasters are sniffed. */\n size?: { width: number; height: number };\n}\n\n/** A cached, browser-paintable render of an asset (PNG from import; raster assets as-is). */\nexport interface StampAssetPreview {\n bytes: Uint8Array;\n mimeType: string;\n}\n\nexport interface StampCapability {\n // ── selectors (pure reads over serializable state) ──\n libraries(): StampLibrary[];\n library(id: string): StampLibrary | null;\n /** Assets of one library, in library order — or every asset when omitted. */\n assets(libraryId?: string): StampAsset[];\n asset(id: string): StampAsset | null;\n // ── binary reads (capability-held, never store state) ──\n /** The asset's paintable preview, or null while none is cached. */\n assetPreview(id: string): StampAssetPreview | null;\n /** Placement bytes; derived from the canonical page for PDF-backed libraries. */\n assetBytes(id: string): Uint8Array | null;\n /** Canonical library PDF bytes, or null for a loose library/unknown id. */\n libraryBytes(id: string): Uint8Array | null;\n // ── library intents ──\n /**\n * Import a PDF as a stamp library: every page becomes one vector asset\n * (single-page PDF bytes + a cached preview render). Uses the asset\n * engine; in a cloud deployment without one configured this rejects with\n * an actionable error. Resolves to the new library id.\n */\n importLibraryPdf(source: BinarySource, opts?: ImportLibraryOptions): Promise<string>;\n /**\n * Add a single asset. A PDF added to a canonical library is inserted as a\n * page and receives `/PieceInfo`; loose assets keep their bytes directly.\n * Raster input cannot be appended to a canonical PDF library.\n */\n addAsset(input: AddAssetInput): Promise<string>;\n /** Remove an asset, deleting its canonical page before state changes when PDF-backed. */\n removeAsset(id: string): Promise<void>;\n /** Remove a library and every asset in it, ordered with in-flight library mutations. */\n removeLibrary(id: string): Promise<void>;\n // ── placement (delegates to the annotation plugin of the named document) ──\n /**\n * Arm an asset on a document: the next click on that document's pages\n * places it (and the hover ghost previews the exact placement). With\n * scripting enabled, form-backed PDFs are evaluated against that target\n * document and flattened first. Rides `annotation.armStamp` — bytes,\n * preview, and intrinsic size all travel along, so vector stamps keep\n * their true aspect.\n */\n armAsset(documentId: string, assetId: string, opts?: { targetWidth?: number }): Promise<void>;\n /** Disarm the stamp tool on a document. */\n disarm(documentId: string): void;\n}\n\nexport const StampToken = createCapabilityToken<StampCapability>('stamp');\n","import { definePlugin } from '@embedpdf/core';\nimport { createStampCapability } from './capability';\nimport { initialStampState, stampReducer } from './reducer';\nimport { StampToken } from './types';\nimport type { StampAction, StampCapability, StampConfig, StampState } from './types';\n\n/**\n * The stamp plugin. WORKSPACE-scoped: libraries are shared across every open\n * document; placement names its document explicitly (`armAsset(documentId, …)`)\n * and delegates to that document's annotation plugin — no hard `requires`,\n * because the annotation token is document-scoped and resolved lazily per\n * placement (a viewer without the annotation plugin fails at the arm call,\n * with the kernel's own missing-capability error).\n */\nexport const stampPlugin = (config: StampConfig = {}) =>\n definePlugin<StampState, StampAction, StampCapability>({\n id: 'stamp',\n token: StampToken,\n scope: 'workspace',\n initialState: initialStampState,\n reduce: stampReducer,\n capability: (ctx) => createStampCapability(ctx, config),\n });\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/capability.ts","../src/reducer.ts","../src/types.ts","../src/stamp.plugin.ts"],"sourcesContent":["import {\n EngineError,\n EngineErrorCode,\n resolveBinarySource,\n sniffBinaryMetadata,\n type BinarySource,\n type DocumentHandle,\n type Engine,\n type PageImageHandle,\n type PieceInfoEntry,\n type PieceInfoPatch,\n} from '@embedpdf/engine-core/runtime';\nimport { type PluginContext } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation';\nimport { createFormScriptingController, type FormCommitResult } from '@embedpdf/plugin-form';\n\nimport type {\n AddAssetInput,\n ImportLibraryOptions,\n StampAction,\n StampAsset,\n StampAssetPreview,\n StampCapability,\n StampConfig,\n StampLibrary,\n StampAssetKind,\n StampState,\n} from './types';\n\nconst DEFAULT_PREVIEW_WIDTH = 256;\nconst LIBRARY_PIECEINFO_APP = 'EMBD_StampLibrary';\nconst STAMP_PIECEINFO_APP = 'EMBD_Stamp';\nconst STAMP_SCHEMA_VERSION = 1;\n\n/** Session-unique ids. Assets are session-scoped for now (no persistence),\n * so a timestamp + counter is enough — durable ids come with the store port. */\nlet seq = 0;\nconst uid = (prefix: string): string =>\n `${prefix}-${Date.now().toString(36)}-${(seq++).toString(36)}`;\n\nconst entryString = (entries: Record<string, PieceInfoEntry>, key: string): string | undefined => {\n const entry = entries[key];\n return entry?.type === 'string' && entry.value.length > 0 ? entry.value : undefined;\n};\n\nconst entryName = (entries: Record<string, PieceInfoEntry>, key: string): string | undefined => {\n const entry = entries[key];\n return entry?.type === 'name' && entry.value.length > 0 ? entry.value : undefined;\n};\n\nconst entryStringArray = (\n entries: Record<string, PieceInfoEntry>,\n key: string,\n): string[] | undefined => {\n const entry = entries[key];\n return entry?.type === 'string-array' ? [...entry.value] : undefined;\n};\n\nconst kindToPdfName = (kind: StampAssetKind): string =>\n kind === 'signature' ? 'Signature' : kind === 'initials' ? 'Initials' : 'Stamp';\n\nconst kindFromPdfName = (name: string | undefined): StampAssetKind | undefined => {\n switch (name?.toLowerCase()) {\n case 'stamp':\n return 'stamp';\n case 'signature':\n return 'signature';\n case 'initials':\n return 'initials';\n default:\n return undefined;\n }\n};\n\nconst metadataPatch = (\n id: string,\n name: string,\n kind: StampAssetKind,\n subject?: string,\n categories?: readonly string[],\n): PieceInfoPatch => ({\n Version: STAMP_SCHEMA_VERSION,\n Id: id,\n Name: name,\n Kind: { name: kindToPdfName(kind) },\n Subject: subject ?? null,\n Categories: categories ?? null,\n});\n\nconst libraryMetadataPatch = (\n id: string,\n name: string,\n categories?: readonly string[],\n): PieceInfoPatch => ({\n Version: STAMP_SCHEMA_VERSION,\n Id: id,\n Name: name,\n Kind: { name: 'StampLibrary' },\n Categories: categories ?? null,\n});\n\nexport function createStampCapability(\n ctx: PluginContext<StampState, StampAction>,\n config: StampConfig = {},\n): StampCapability {\n /** Binary sidecar of the serializable store: asset bytes + cached preview,\n * keyed by asset id. The reducer never sees these (kernel rule 1). */\n const binaries = new Map<string, { bytes: Uint8Array; preview: StampAssetPreview | null }>();\n /** The durable source of truth for a canonical library. Asset PDFs above\n * are derived page extractions; this map owns the rewritten whole PDF. */\n const libraryBinaries = new Map<string, Uint8Array>();\n /** Whole-PDF rewrites must be serialized per library or two concurrent\n * appends could both start from the same bytes and lose one page. */\n const libraryMutationTails = new Map<string, Promise<void>>();\n\n const mutateLibrary = <T>(libraryId: string, mutation: () => Promise<T>): Promise<T> => {\n const previous = libraryMutationTails.get(libraryId) ?? Promise.resolve();\n const result = previous.then(mutation);\n const tail = result.then(\n () => undefined,\n () => undefined,\n );\n libraryMutationTails.set(libraryId, tail);\n return result.finally(() => {\n if (libraryMutationTails.get(libraryId) === tail) libraryMutationTails.delete(libraryId);\n });\n };\n\n // The ASSET ENGINE port. A configured factory is called (and memoized) on\n // the first import, not at viewer start; a configured instance is used\n // as-is; nothing configured falls back to the kernel's engine — correct for\n // local deployments, and rejected with an actionable error by cloud engines\n // at the first `open({ kind: 'bytes' })`.\n let assetEngineRef: Engine | Promise<Engine> | null = null;\n const assetEngine = (): Engine | Promise<Engine> => {\n if (!assetEngineRef) {\n const cfg = config.assetEngine;\n assetEngineRef = !cfg ? ctx.engine : typeof cfg === 'function' ? cfg() : cfg;\n }\n return assetEngineRef;\n };\n\n const openAssetDocument = async (\n bytes: Uint8Array,\n identity?: DocumentHandle['security']['identity'],\n ): Promise<DocumentHandle> => {\n try {\n return await (\n await assetEngine()\n ).open(\n { kind: 'bytes', id: uid('stamp-import'), bytes },\n { scope: ['*'], ...(identity ? { identity } : {}) },\n );\n } catch (err) {\n // A cloud kernel engine rejects 'bytes' with InvalidArg — turn the\n // generic contract error into the configuration fix.\n if (!config.assetEngine && EngineError.is(err, EngineErrorCode.InvalidArg)) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n \"[stamp] importing a library PDF needs an engine that can open local bytes, and this viewer's engine cannot (cloud). Pass stampPlugin({ assetEngine: () => import('@embedpdf/engine').then((m) => m.createLocalEngine()) }) — it loads lazily, on first import.\",\n );\n }\n throw err;\n }\n };\n\n /** Import-time preview render → bytes. The asset engine is local by\n * definition, so the image source is always inline bytes. */\n const imageToPreview = (image: PageImageHandle): StampAssetPreview => {\n if (image.source.kind !== 'bytes') {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] asset engine returned a URL-sourced render; asset engines must be local',\n );\n }\n return { bytes: image.source.bytes, mimeType: image.contentType };\n };\n\n const allocateId = (\n preferred: string | undefined,\n prefix: string,\n taken: Set<string>,\n ): string => {\n let id = preferred;\n if (!id || taken.has(id)) {\n do id = uid(prefix);\n while (taken.has(id));\n }\n taken.add(id);\n return id;\n };\n\n const createLooseLibrary = (name: string): string => {\n const id = uid('stamp-lib');\n ctx.dispatch({\n type: 'LIBRARY_ADDED',\n library: { id, name, storage: 'loose', assetIds: [] },\n });\n return id;\n };\n\n const importLibraryPdf = async (\n source: BinarySource,\n opts?: ImportLibraryOptions,\n ): Promise<string> => {\n const resolved = await resolveBinarySource(source);\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (meta?.mimeType !== 'application/pdf') {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] importLibraryPdf needs PDF bytes (use addAsset for a raster image)',\n );\n }\n const doc = await openAssetDocument(new Uint8Array(resolved.bytes));\n let imported:\n | {\n library: StampLibrary;\n canonicalBytes: Uint8Array;\n assets: Array<{\n asset: StampAsset;\n bytes: Uint8Array;\n preview: StampAssetPreview;\n }>;\n }\n | undefined;\n try {\n if (!doc.pieceInfo) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] canonical PDF libraries need an asset engine with pieceInfo',\n );\n }\n const snapshot = await doc.pages.list();\n if (snapshot.pageCount === 0) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] a canonical stamp library PDF must contain at least one page',\n );\n }\n\n // Discover and validate every required service before the first write.\n const pages = snapshot.pages.map((layout) => {\n const handle = doc.page(layout.pageObjectNumber);\n if (!handle.pieceInfo) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] canonical PDF libraries need page pieceInfo support',\n );\n }\n return {\n layout,\n handle,\n metadata: null as Awaited<ReturnType<typeof handle.pieceInfo.read>>,\n };\n });\n\n const catalogMetadata = await doc.pieceInfo.read(LIBRARY_PIECEINFO_APP);\n for (const page of pages) {\n page.metadata = await page.handle.pieceInfo!.read(STAMP_PIECEINFO_APP);\n }\n\n const state = ctx.getState();\n const takenLibraryIds = new Set(Object.keys(state.libraries));\n const takenAssetIds = new Set(Object.keys(state.assets));\n const catalogEntries = catalogMetadata?.entries ?? {};\n const libraryId = allocateId(entryString(catalogEntries, 'Id'), 'stamp-lib', takenLibraryIds);\n const libraryName = opts?.name ?? entryString(catalogEntries, 'Name') ?? 'Stamps';\n const libraryCategories = opts?.categories ?? entryStringArray(catalogEntries, 'Categories');\n\n const descriptors = pages.map(({ layout, handle, metadata: pageMetadata }) => {\n const entries = pageMetadata?.entries ?? {};\n const id = allocateId(entryString(entries, 'Id'), 'stamp', takenAssetIds);\n const kind = opts?.kind ?? kindFromPdfName(entryName(entries, 'Kind')) ?? 'stamp';\n return {\n handle,\n asset: {\n id,\n libraryId,\n kind,\n name:\n opts?.assetName?.(layout.index) ??\n entryString(entries, 'Name') ??\n `Stamp ${layout.index + 1}`,\n size: { width: layout.size.width, height: layout.size.height },\n format: 'pdf' as const,\n pageObjectNumber: layout.pageObjectNumber,\n subject: entryString(entries, 'Subject'),\n categories: entryStringArray(entries, 'Categories'),\n },\n };\n });\n\n await doc.pieceInfo.update(\n LIBRARY_PIECEINFO_APP,\n libraryMetadataPatch(libraryId, libraryName, libraryCategories),\n );\n\n const assets: NonNullable<typeof imported>['assets'] = [];\n for (const descriptor of descriptors) {\n const { asset, handle } = descriptor;\n await handle.pieceInfo!.update(\n STAMP_PIECEINFO_APP,\n metadataPatch(asset.id, asset.name, asset.kind, asset.subject, asset.categories),\n );\n // One canonical page → one derived placement PDF plus a transparent\n // preview. Extract after metadata so the cache carries the same id.\n const bytes = await doc.pages.extract([asset.pageObjectNumber!]);\n const image = await handle.render.image({\n viewport: { kind: 'width', width: config.previewWidth ?? DEFAULT_PREVIEW_WIDTH },\n background: 'transparent',\n includeAnnotations: true,\n format: 'png',\n });\n assets.push({ asset, bytes, preview: imageToPreview(image) });\n }\n\n imported = {\n library: {\n id: libraryId,\n name: libraryName,\n storage: 'canonical-pdf',\n categories: libraryCategories,\n assetIds: [],\n },\n canonicalBytes: await doc.download(),\n assets,\n };\n } finally {\n await doc.close();\n }\n\n libraryBinaries.set(imported.library.id, imported.canonicalBytes);\n ctx.dispatch({ type: 'LIBRARY_ADDED', library: imported.library });\n for (const { asset, bytes, preview } of imported.assets) {\n binaries.set(asset.id, { bytes, preview });\n ctx.dispatch({ type: 'ASSET_ADDED', asset });\n }\n return imported.library.id;\n };\n\n const addAsset = async (input: AddAssetInput): Promise<string> => {\n const targetLibrary = input.libraryId\n ? (ctx.getState().libraries[input.libraryId] ?? null)\n : null;\n if (input.libraryId && !targetLibrary) {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] unknown library '${input.libraryId}'`,\n );\n }\n const resolved = await resolveBinarySource(input.source);\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (!meta) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] asset source must be PNG, JPEG, or single-page PDF bytes',\n );\n }\n const isPdf = meta.mimeType === 'application/pdf';\n\n let suppliedPreview: StampAssetPreview | null = null;\n if (input.preview) {\n const preview = await resolveBinarySource(input.preview);\n suppliedPreview = {\n bytes: new Uint8Array(preview.bytes),\n mimeType: preview.mimeType ?? 'image/png',\n };\n }\n\n if (targetLibrary?.storage === 'canonical-pdf') {\n if (!isPdf) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] raster assets cannot be appended to a canonical PDF library',\n );\n }\n return mutateLibrary(targetLibrary.id, async () => {\n const liveLibrary = ctx.getState().libraries[targetLibrary.id];\n if (liveLibrary?.storage !== 'canonical-pdf') {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] canonical library '${targetLibrary.id}' no longer exists`,\n );\n }\n const canonicalBytes = libraryBinaries.get(liveLibrary.id);\n if (!canonicalBytes) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] canonical bytes are missing for library '${liveLibrary.id}'`,\n );\n }\n\n const assetId = uid('stamp');\n const doc = await openAssetDocument(canonicalBytes);\n let appended:\n | {\n asset: StampAsset;\n bytes: Uint8Array;\n preview: StampAssetPreview;\n canonical: Uint8Array;\n }\n | undefined;\n try {\n const result = await doc.pages.insert(new Uint8Array(resolved.bytes));\n if (result.insertedPageObjectNumbers.length !== 1) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] a canonical library asset must be a single-page PDF',\n );\n }\n const pageObjectNumber = result.insertedPageObjectNumbers[0];\n const layout = result.layout.pages.find(\n (candidate) => candidate.pageObjectNumber === pageObjectNumber,\n );\n const page = doc.page(pageObjectNumber);\n if (!layout || !page.pieceInfo) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] canonical PDF libraries need page layout and pieceInfo support',\n );\n }\n const asset: StampAsset = {\n id: assetId,\n libraryId: liveLibrary.id,\n kind: input.kind ?? 'stamp',\n name: input.name,\n size: { width: layout.size.width, height: layout.size.height },\n format: 'pdf',\n pageObjectNumber,\n subject: input.subject,\n categories: input.categories,\n };\n await page.pieceInfo.update(\n STAMP_PIECEINFO_APP,\n metadataPatch(asset.id, asset.name, asset.kind, asset.subject, asset.categories),\n );\n const bytes = await doc.pages.extract([pageObjectNumber]);\n let preview = suppliedPreview;\n if (!preview) {\n preview = imageToPreview(\n await page.render.image({\n viewport: { kind: 'width', width: config.previewWidth ?? DEFAULT_PREVIEW_WIDTH },\n background: 'transparent',\n includeAnnotations: true,\n format: 'png',\n }),\n );\n }\n appended = { asset, bytes, preview, canonical: await doc.download() };\n } finally {\n await doc.close();\n }\n\n libraryBinaries.set(liveLibrary.id, appended.canonical);\n binaries.set(appended.asset.id, { bytes: appended.bytes, preview: appended.preview });\n ctx.dispatch({ type: 'ASSET_ADDED', asset: appended.asset });\n return appended.asset.id;\n });\n }\n\n const size =\n input.size ?? ('width' in meta ? { width: meta.width, height: meta.height } : null);\n if (!size) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n '[stamp] a PDF asset needs `size` (its page size in points) — PDF bytes carry no sniffable dimensions',\n );\n }\n let preview = suppliedPreview;\n if (!preview && !isPdf) {\n preview = { bytes: new Uint8Array(resolved.bytes), mimeType: meta.mimeType };\n }\n const commitLooseAsset = (libraryId: string): string => {\n const asset: StampAsset = {\n id: uid('stamp'),\n libraryId,\n kind: input.kind ?? 'stamp',\n name: input.name,\n size,\n format: isPdf ? 'pdf' : meta.mimeType === 'image/png' ? 'png' : 'jpeg',\n subject: input.subject,\n categories: input.categories,\n };\n binaries.set(asset.id, { bytes: new Uint8Array(resolved.bytes), preview });\n ctx.dispatch({ type: 'ASSET_ADDED', asset });\n return asset.id;\n };\n if (!targetLibrary) return commitLooseAsset(createLooseLibrary(input.name));\n return mutateLibrary(targetLibrary.id, async () => {\n const liveLibrary = ctx.getState().libraries[targetLibrary.id];\n if (liveLibrary?.storage !== 'loose') {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] loose library '${targetLibrary.id}' no longer exists`,\n );\n }\n return commitLooseAsset(liveLibrary.id);\n });\n };\n\n const dropLibrary = (id: string): void => {\n const library = ctx.getState().libraries[id];\n if (library) for (const assetId of library.assetIds) binaries.delete(assetId);\n libraryBinaries.delete(id);\n ctx.dispatch({ type: 'LIBRARY_REMOVED', libraryId: id });\n };\n\n const removeAsset = async (id: string): Promise<void> => {\n const initialAsset = ctx.getState().assets[id];\n if (!initialAsset) return;\n return mutateLibrary(initialAsset.libraryId, async () => {\n const asset = ctx.getState().assets[id];\n if (!asset) return;\n const library = ctx.getState().libraries[asset.libraryId];\n if (library?.storage === 'canonical-pdf') {\n if (library.assetIds.length === 1) {\n dropLibrary(library.id);\n return;\n }\n if (asset.pageObjectNumber === undefined) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] canonical asset '${id}' has no page object number`,\n );\n }\n const canonicalBytes = libraryBinaries.get(library.id);\n if (!canonicalBytes) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] canonical bytes are missing for library '${library.id}'`,\n );\n }\n const doc = await openAssetDocument(canonicalBytes);\n let rewritten: Uint8Array | undefined;\n try {\n await doc.pages.delete([asset.pageObjectNumber]);\n rewritten = await doc.download();\n } finally {\n await doc.close();\n }\n libraryBinaries.set(library.id, rewritten);\n }\n binaries.delete(id);\n ctx.dispatch({ type: 'ASSET_REMOVED', assetId: id });\n });\n };\n\n const removeLibrary = (id: string): Promise<void> =>\n mutateLibrary(id, async () => dropLibrary(id));\n\n const surfaceScriptingResult = (result: FormCommitResult): void => {\n try {\n for (const effect of result.uiEffects) config.scripting?.onUiEffect?.(effect);\n for (const diagnostic of result.diagnostics) {\n config.scripting?.onDiagnostic?.(diagnostic);\n }\n if (result.error) config.scripting?.onError?.(result.error);\n } catch (error) {\n globalThis.console?.error('[stamp] scripting observer failed:', error);\n }\n };\n\n /**\n * Form-backed stamps are executable templates only until placement. Work\n * on an isolated copy so neither the canonical library nor its reusable\n * per-page extraction becomes target/user/time specific.\n */\n const materializeForPlacement = async (\n documentId: string,\n asset: StampAsset,\n bin: { bytes: Uint8Array; preview: StampAssetPreview | null },\n ): Promise<{ bytes: Uint8Array; preview: StampAssetPreview | null }> => {\n if (asset.format !== 'pdf' || !config.scripting?.enabled) return bin;\n\n const targetDoc = ctx.documentHandle(documentId);\n const targetMeta = ctx.core().documents[documentId] ?? null;\n if (!targetDoc || !targetMeta) {\n throw new EngineError(\n EngineErrorCode.NotFound,\n `[stamp] target document '${documentId}' is not open`,\n );\n }\n\n // A page extraction intentionally does not retain catalog-owned AcroForm\n // and action structures. Canonical assets therefore evaluate from the\n // whole library PDF, then extract only their selected page after flatten.\n const canonicalBytes = libraryBinaries.get(asset.libraryId);\n const sourceBytes = canonicalBytes ?? bin.bytes;\n const doc = await openAssetDocument(new Uint8Array(sourceBytes), targetDoc.security.identity);\n let scripting: ReturnType<typeof createFormScriptingController> | null = null;\n try {\n const layout = await doc.pages.list();\n const selectedPage =\n asset.pageObjectNumber === undefined\n ? layout.pageCount === 1\n ? layout.pages[0]\n : undefined\n : layout.pages.find(\n ({ pageObjectNumber }) => pageObjectNumber === asset.pageObjectNumber,\n );\n if (!selectedPage) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n canonicalBytes\n ? `[stamp] canonical page ${asset.pageObjectNumber ?? 'unknown'} no longer exists`\n : '[stamp] a loose dynamic stamp asset must contain exactly one page',\n );\n }\n const snapshot = await doc.forms.list();\n const hasSelectedPageField = snapshot.fields.some((field) =>\n field.widgets.some(\n ({ pageObjectNumber }) => pageObjectNumber === selectedPage.pageObjectNumber,\n ),\n );\n if (!hasSelectedPageField) return bin;\n if (!doc.pages.flatten || !doc.pages.extract) {\n throw new EngineError(\n EngineErrorCode.NotImplemented,\n '[stamp] dynamic PDF stamps need an asset engine with pages.flatten and pages.extract',\n );\n }\n\n const scriptingConfig = config.scripting;\n scripting = createFormScriptingController({\n doc,\n document: () => targetMeta,\n config: scriptingConfig,\n sandboxFactory:\n scriptingConfig.sandboxFactory ??\n (() =>\n import('@embedpdf/core-js-sandbox').then(({ createQuickJsSandbox }) =>\n createQuickJsSandbox(),\n )),\n });\n const result = await scripting.recalculate(snapshot);\n surfaceScriptingResult(result);\n if (result.status === 'failed') {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] dynamic stamp scripting failed: ${result.error?.message ?? 'native form effect failed'}`,\n );\n }\n\n const pageObjectNumber = selectedPage.pageObjectNumber;\n const flattened = await doc.pages.flatten([pageObjectNumber], 'display');\n const failed = flattened.results.find(\n ({ status }) => status === 'failed' || status === 'skipped',\n );\n if (failed) {\n throw new EngineError(\n EngineErrorCode.Unknown,\n `[stamp] dynamic stamp flatten failed for page ${failed.pageObjectNumber}`,\n );\n }\n\n const bytes = await doc.pages.extract([pageObjectNumber]);\n const image = await doc.page(pageObjectNumber).render.image({\n viewport: { kind: 'width', width: config.previewWidth ?? DEFAULT_PREVIEW_WIDTH },\n background: 'transparent',\n includeAnnotations: false,\n format: 'png',\n });\n return { bytes, preview: imageToPreview(image) };\n } finally {\n scripting?.dispose();\n await doc.close();\n }\n };\n\n const armAsset = async (\n documentId: string,\n assetId: string,\n opts?: { targetWidth?: number },\n ): Promise<void> => {\n const asset = ctx.getState().assets[assetId];\n const bin = binaries.get(assetId);\n if (!asset || !bin) {\n throw new EngineError(EngineErrorCode.NotFound, `[stamp] unknown asset '${assetId}'`);\n }\n const placement = await materializeForPlacement(documentId, asset, bin);\n // The placement itself remains one armStamp call. Dynamic evaluation,\n // when enabled and applicable, has already produced an ephemeral static\n // page and matching preview at this boundary.\n const annotation = ctx.forDocument(AnnotationToken, documentId);\n await annotation.armStamp({\n source: placement.bytes,\n preview: placement.preview\n ? { data: placement.preview.bytes, mimeType: placement.preview.mimeType }\n : undefined,\n intrinsicSize: asset.size,\n targetWidth: opts?.targetWidth,\n });\n };\n\n ctx.cleanup(() => {\n binaries.clear();\n libraryBinaries.clear();\n libraryMutationTails.clear();\n const ownedAssetEngine = typeof config.assetEngine === 'function' ? assetEngineRef : null;\n assetEngineRef = null;\n if (ownedAssetEngine) {\n void Promise.resolve(ownedAssetEngine)\n .then((engine) => engine.destroy())\n .catch(() => {});\n }\n });\n\n return {\n libraries: () => {\n const s = ctx.getState();\n return s.libraryOrder.map((id) => s.libraries[id]).filter((l) => l != null);\n },\n library: (id) => ctx.getState().libraries[id] ?? null,\n assets: (libraryId) => {\n const s = ctx.getState();\n if (libraryId) {\n const library = s.libraries[libraryId];\n return library ? library.assetIds.map((id) => s.assets[id]).filter((a) => a != null) : [];\n }\n return s.libraryOrder.flatMap((lid) =>\n (s.libraries[lid]?.assetIds ?? []).map((id) => s.assets[id]).filter((a) => a != null),\n );\n },\n asset: (id) => ctx.getState().assets[id] ?? null,\n assetPreview: (id) => binaries.get(id)?.preview ?? null,\n assetBytes: (id) => binaries.get(id)?.bytes ?? null,\n libraryBytes: (id) => libraryBinaries.get(id) ?? null,\n importLibraryPdf,\n addAsset,\n removeAsset,\n removeLibrary,\n armAsset,\n disarm: (documentId) => ctx.forDocument(AnnotationToken, documentId).disarmStamp(),\n };\n}\n","import type { StampAction, StampState } from './types';\n\nexport const initialStampState = (): StampState => ({\n libraries: {},\n libraryOrder: [],\n assets: {},\n});\n\n/** Pure and serializable (kernel rule 1) — descriptors only; the bytes and\n * previews live in the capability and never enter the store. */\nexport const stampReducer = (state: StampState, action: StampAction): StampState => {\n switch (action.type) {\n case 'LIBRARY_ADDED':\n return {\n ...state,\n libraries: { ...state.libraries, [action.library.id]: action.library },\n libraryOrder: [...state.libraryOrder, action.library.id],\n };\n case 'LIBRARY_REMOVED': {\n const library = state.libraries[action.libraryId];\n if (!library) return state;\n const libraries = { ...state.libraries };\n delete libraries[action.libraryId];\n const assets = { ...state.assets };\n for (const id of library.assetIds) delete assets[id];\n return {\n ...state,\n libraries,\n libraryOrder: state.libraryOrder.filter((id) => id !== action.libraryId),\n assets,\n };\n }\n case 'ASSET_ADDED': {\n const library = state.libraries[action.asset.libraryId];\n if (!library) return state;\n return {\n ...state,\n assets: { ...state.assets, [action.asset.id]: action.asset },\n libraries: {\n ...state.libraries,\n [library.id]: { ...library, assetIds: [...library.assetIds, action.asset.id] },\n },\n };\n }\n case 'ASSET_REMOVED': {\n const asset = state.assets[action.assetId];\n if (!asset) return state;\n const assets = { ...state.assets };\n delete assets[action.assetId];\n const library = state.libraries[asset.libraryId];\n return {\n ...state,\n assets,\n libraries: library\n ? {\n ...state.libraries,\n [library.id]: {\n ...library,\n assetIds: library.assetIds.filter((id) => id !== action.assetId),\n },\n }\n : state.libraries,\n };\n }\n default:\n return state;\n }\n};\n","import type { BinarySource, Engine } from '@embedpdf/engine-core/runtime';\nimport { createCapabilityToken } from '@embedpdf/core';\nimport type { FormScriptingOptions } from '@embedpdf/plugin-form';\n\n/**\n * The stamp plugin: a workspace-scoped ASSET substrate.\n *\n * The design law (\"documents have a home; assets ride the wire\"): imported\n * PDF libraries retain one canonical PDF whose catalog/page `/PieceInfo`\n * carries their metadata. Per-asset PDFs and previews are derived caches used\n * for placement. Standalone PNG/JPEG assets remain loose because the engine\n * intentionally has no raster-to-PDF-page authoring primitive.\n */\n\nexport type StampAssetKind = 'stamp' | 'signature' | 'initials';\n\n/**\n * One asset's SERIALIZABLE descriptor. The bytes and the cached preview are\n * deliberately NOT here — the reducer state stays pure/serializable (kernel\n * rule 1); binary lives in the capability and crosses only as call\n * arguments/returns, mirroring the engine's own BinarySource rule.\n */\nexport interface StampAsset {\n id: string;\n libraryId: string;\n kind: StampAssetKind;\n name: string;\n /** Intrinsic size in PDF points (the source page's crop box / image pixels 1:1). */\n size: { width: number; height: number };\n /** What the asset bytes are: a single-page vector PDF, or a raster image. */\n format: 'pdf' | 'png' | 'jpeg';\n /** Canonical library page identity; present for PDF-backed libraries. */\n pageObjectNumber?: number;\n subject?: string;\n categories?: string[];\n}\n\n/** A named group of assets — one imported PDF becomes one library. */\nexport interface StampLibrary {\n id: string;\n name: string;\n /** PDF-backed libraries own canonical bytes; loose libraries are raster/pre-sliced conveniences. */\n storage: 'canonical-pdf' | 'loose';\n categories?: string[];\n /** Asset ids in display order. */\n assetIds: string[];\n}\n\nexport interface StampState {\n libraries: Record<string, StampLibrary>;\n /** Library display order (insertion order). */\n libraryOrder: string[];\n assets: Record<string, StampAsset>;\n}\n\nexport type StampAction =\n | { type: 'LIBRARY_ADDED'; library: StampLibrary }\n | { type: 'LIBRARY_REMOVED'; libraryId: string }\n | { type: 'ASSET_ADDED'; asset: StampAsset }\n | { type: 'ASSET_REMOVED'; assetId: string };\n\nexport interface StampConfig {\n /**\n * The ASSET ENGINE port: any `Engine` that can open `{ kind: 'bytes' }` —\n * used only to slice an imported library PDF into per-page assets and\n * render their previews.\n *\n * Omitted → the kernel's own engine is used, which is exactly right for a\n * local deployment (same WASM instance, zero extra cost). In a CLOUD\n * deployment the kernel engine cannot open local bytes, so pass a factory —\n * it is called (and memoized) on the first import, never at viewer boot:\n *\n * ```ts\n * stampPlugin({\n * assetEngine: () => import('@embedpdf/engine').then((m) => m.createLocalEngine()),\n * })\n * ```\n */\n assetEngine?: Engine | (() => Engine | Promise<Engine>);\n /** Cached preview width in device px (import-time render). Default 256. */\n previewWidth?: number;\n /**\n * Opt-in Acrobat JavaScript evaluation for form-backed PDF stamp assets.\n * On arm, the plugin recalculates a temporary copy using the target\n * document's identity/name/clock, flattens it, and arms the resulting\n * static page. Canonical library and derived base bytes stay unchanged.\n */\n scripting?: FormScriptingOptions;\n}\n\nexport interface ImportLibraryOptions {\n /** Library display name. Default `'Stamps'`. */\n name?: string;\n /** Library categories written to catalog `/PieceInfo`. */\n categories?: string[];\n /** Kind stamped onto every imported asset. Default `'stamp'`. */\n kind?: StampAssetKind;\n /** Per-page asset names; default `Stamp <n>`. */\n assetName?: (pageIndex: number) => string;\n}\n\nexport interface AddAssetInput {\n /** Target library; omitted → a new single-asset library named after the asset. */\n libraryId?: string;\n name: string;\n kind?: StampAssetKind;\n subject?: string;\n categories?: string[];\n /** Single-page PDF (vector) or PNG/JPEG bytes. */\n source: BinarySource;\n /**\n * Paintable preview for pickers + the hover ghost. Loose PDF assets cannot\n * derive one without opening the PDF; canonical libraries render it after\n * insertion. Raster sources default to their own bytes.\n */\n preview?: BinarySource;\n /** Intrinsic size in PDF points. Required for PDF sources; rasters are sniffed. */\n size?: { width: number; height: number };\n}\n\n/** A cached, browser-paintable render of an asset (PNG from import; raster assets as-is). */\nexport interface StampAssetPreview {\n bytes: Uint8Array;\n mimeType: string;\n}\n\nexport interface StampCapability {\n // ── selectors (pure reads over serializable state) ──\n libraries(): StampLibrary[];\n library(id: string): StampLibrary | null;\n /** Assets of one library, in library order — or every asset when omitted. */\n assets(libraryId?: string): StampAsset[];\n asset(id: string): StampAsset | null;\n // ── binary reads (capability-held, never store state) ──\n /** The asset's paintable preview, or null while none is cached. */\n assetPreview(id: string): StampAssetPreview | null;\n /** Placement bytes; derived from the canonical page for PDF-backed libraries. */\n assetBytes(id: string): Uint8Array | null;\n /** Canonical library PDF bytes, or null for a loose library/unknown id. */\n libraryBytes(id: string): Uint8Array | null;\n // ── library intents ──\n /**\n * Import a PDF as a stamp library: every page becomes one vector asset\n * (single-page PDF bytes + a cached preview render). Uses the asset\n * engine; in a cloud deployment without one configured this rejects with\n * an actionable error. Resolves to the new library id.\n */\n importLibraryPdf(source: BinarySource, opts?: ImportLibraryOptions): Promise<string>;\n /**\n * Add a single asset. A PDF added to a canonical library is inserted as a\n * page and receives `/PieceInfo`; loose assets keep their bytes directly.\n * Raster input cannot be appended to a canonical PDF library.\n */\n addAsset(input: AddAssetInput): Promise<string>;\n /** Remove an asset, deleting its canonical page before state changes when PDF-backed. */\n removeAsset(id: string): Promise<void>;\n /** Remove a library and every asset in it, ordered with in-flight library mutations. */\n removeLibrary(id: string): Promise<void>;\n // ── placement (delegates to the annotation plugin of the named document) ──\n /**\n * Arm an asset on a document: the next click on that document's pages\n * places it (and the hover ghost previews the exact placement). With\n * scripting enabled, form-backed PDFs are evaluated against that target\n * document and flattened first. Rides `annotation.armStamp` — bytes,\n * preview, and intrinsic size all travel along, so vector stamps keep\n * their true aspect.\n */\n armAsset(documentId: string, assetId: string, opts?: { targetWidth?: number }): Promise<void>;\n /** Disarm the stamp tool on a document. */\n disarm(documentId: string): void;\n}\n\nexport const StampToken = createCapabilityToken<StampCapability>('stamp');\n","import { definePlugin } from '@embedpdf/core';\nimport { createStampCapability } from './capability';\nimport { initialStampState, stampReducer } from './reducer';\nimport { StampToken } from './types';\nimport type { StampAction, StampCapability, StampConfig, StampState } from './types';\n\n/**\n * The stamp plugin. WORKSPACE-scoped: libraries are shared across every open\n * document; placement names its document explicitly (`armAsset(documentId, …)`)\n * and delegates to that document's annotation plugin — no hard `requires`,\n * because the annotation token is document-scoped and resolved lazily per\n * placement (a viewer without the annotation plugin fails at the arm call,\n * with the kernel's own missing-capability error).\n */\nexport const stampPlugin = (config: StampConfig = {}) =>\n definePlugin<StampState, StampAction, StampCapability>({\n id: 'stamp',\n token: StampToken,\n scope: 'workspace',\n initialState: initialStampState,\n reduce: stampReducer,\n capability: (ctx) => createStampCapability(ctx, config),\n });\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/plugin-stamp",
3
- "version": "3.0.0-next.0",
3
+ "version": "3.0.0-next.10",
4
4
  "private": false,
5
5
  "description": "Stamp asset libraries: retain imported PDFs as canonical PieceInfo-backed libraries, derive per-page vector assets and previews, materialize opt-in dynamic stamps, and place them through the annotation plugin's armed-stamp flow.",
6
6
  "type": "module",
@@ -18,17 +18,17 @@
18
18
  "dist"
19
19
  ],
20
20
  "dependencies": {
21
- "@embedpdf/core": "3.0.0-next.0",
22
- "@embedpdf/core-js-sandbox": "3.0.0-next.0",
23
- "@embedpdf/plugin-annotation": "3.0.0-next.0",
24
- "@embedpdf/plugin-form": "3.0.0-next.0",
25
- "@embedpdf/engine-core": "3.0.0-next.0"
21
+ "@embedpdf/core": "3.0.0-next.10",
22
+ "@embedpdf/core-js-sandbox": "3.0.0-next.10",
23
+ "@embedpdf/plugin-annotation": "3.0.0-next.10",
24
+ "@embedpdf/plugin-form": "3.0.0-next.10",
25
+ "@embedpdf/engine-core": "3.0.0-next.10"
26
26
  },
27
27
  "devDependencies": {
28
28
  "typescript": "^5.0.0",
29
29
  "vitest": "^2.1.9",
30
30
  "@embedpdf/tooling-build": "0.0.0",
31
- "@embedpdf/engine": "3.0.0-next.0"
31
+ "@embedpdf/engine": "3.0.0-next.10"
32
32
  },
33
33
  "license": "Apache-2.0",
34
34
  "sideEffects": false,