@unlev/exeq 0.5.6 → 0.6.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/server.ts","../src/utils/pdfFiller.ts","../src/types/pdf-builder.ts","../src/utils/formulaResolver.ts","../src/utils/fitText.ts"],"sourcesContent":["/**\n * Server entry point — `@unlev/exeq/server`.\n *\n * The DOM-free subset of exeq: everything needed to GENERATE filled PDF bytes\n * with no browser, React, canvas, or pdfjs. The output path here is identical\n * to the one the client components use, so a PDF produced on the server matches\n * one produced in the browser (pin `metadata.creationDate`/`modificationDate`\n * for byte-identical output — see `PdfMetadata`).\n *\n * Requires a runtime with global `fetch` and `atob` (Node 18+, edge runtimes,\n * Deno, Bun). Pass `pdfSource` as an `ArrayBuffer` to skip the `fetch` entirely.\n *\n * Intentionally EXCLUDED (browser-only — import from `@unlev/exeq` instead):\n * - React components: DesignerView, SignerView, PdfViewer, SignatureCanvas, …\n * - `downloadPdf` (uses `document`/`URL.createObjectURL`)\n * - `renderPdfPages` / `RenderedPage` (pdfjs-dist + canvas, preview-only)\n *\n * import { generateFilledPdf, US_LETTER } from '@unlev/exeq/server';\n *\n * const bytes = await generateFilledPdf(\n * { pdfSource: templateArrayBuffer, fields, resolveFormulas: true },\n * { metadata: { producer: 'exeq', creationDate: new Date(0), modificationDate: new Date(0) } },\n * );\n * // bytes: Uint8Array — write to disk, upload to blob storage, email, etc.\n */\n\n// PDF generation (DOM-free output path)\nexport {\n generateFilledPdf,\n createPdfBuilder,\n applyCalibration,\n DEFAULT_CALIBRATION,\n US_LETTER,\n US_LEGAL,\n A4,\n} from '../utils/pdfFiller';\nexport type {\n FillPdfOptions,\n CreatePdfBuilderOptions,\n PdfBuilder,\n PdfMetadata,\n Calibration,\n} from '../utils/pdfFiller';\n\n// Formula resolution + shared text-fit algorithm (pure)\nexport {\n resolveFormula,\n resolveAllFormulas,\n BUILTIN_TRANSFORMS,\n parseDate,\n} from '../utils/formulaResolver';\nexport type { TransformFn, TransformMap } from '../utils/formulaResolver';\nexport { fitFontSize } from '../utils/fitText';\nexport type { FitFontSizeOptions } from '../utils/fitText';\n\n// Field/template types and pure helpers\nexport type { FormField, FieldType, TextSubtype, Template } from '../types/pdf-builder';\nexport {\n DEFAULT_SIGNER_ROLES,\n SIGNER_ROLE_COLORS,\n FIELD_DEFAULTS,\n FONT_FAMILIES,\n getSignerColor,\n createField,\n uniqueLabel,\n generateId,\n isRedactField,\n isSignatureField,\n isTextLikeField,\n getInputType,\n getCssFontFamily,\n sortFieldsByPosition,\n preserveFieldValues,\n getFieldValues,\n} from '../types/pdf-builder';\n","import {\n PDFDocument,\n PDFEmbeddedPage,\n PDFFont,\n PDFImage,\n PDFPage,\n rgb,\n StandardFonts,\n} from 'pdf-lib';\nimport type { FormField } from '@/types/pdf-builder';\nimport { isRedactField, isSignatureField } from '@/types/pdf-builder';\nimport { resolveAllFormulas, type TransformMap } from './formulaResolver';\nimport { fitFontSize } from './fitText';\n\n/** Standard PDF font variants keyed by [family][bold][italic]. */\nconst FONT_VARIANTS: Record<string, [normal: StandardFonts, bold: StandardFonts, italic: StandardFonts, boldItalic: StandardFonts]> = {\n Helvetica: [StandardFonts.Helvetica, StandardFonts.HelveticaBold, StandardFonts.HelveticaOblique, StandardFonts.HelveticaBoldOblique],\n Courier: [StandardFonts.Courier, StandardFonts.CourierBold, StandardFonts.CourierOblique, StandardFonts.CourierBoldOblique],\n TimesRoman: [StandardFonts.TimesRoman, StandardFonts.TimesRomanBold, StandardFonts.TimesRomanItalic, StandardFonts.TimesRomanBoldItalic],\n};\n\n/** Resolve a family + bold/italic flags to the matching standard PDF font. */\nfunction resolveStandardFont(family: string, bold?: boolean, italic?: boolean): StandardFonts {\n const variants = FONT_VARIANTS[family] || FONT_VARIANTS.Helvetica;\n const idx = (bold ? 1 : 0) + (italic ? 2 : 0);\n return variants[idx];\n}\n\n/** Cache key distinguishing each embedded font variant. */\nfunction fontKey(family: string, bold?: boolean, italic?: boolean): string {\n return `${family}|${bold ? 'b' : ''}|${italic ? 'i' : ''}`;\n}\n\n/** US Letter in PDF points (72pt = 1 in). */\nexport const US_LETTER: [number, number] = [612, 792];\n/** US Legal in PDF points. */\nexport const US_LEGAL: [number, number] = [612, 1008];\n/** A4 in PDF points. */\nexport const A4: [number, number] = [595.28, 841.89];\n\n// ---------------------------------------------------------------------------\n// Calibration\n// ---------------------------------------------------------------------------\n\n/**\n * Linear calibration applied to every field's percentage position and size.\n * Use to align rendered output with a physical pre-printed form when the\n * template's source PDF and the real paper don't exactly agree on crop or\n * scale.\n *\n * Math (for an output page of size [pW, pH] pt):\n * xPctOff = (xOffset / pW) * 100\n * yPctOff = (yOffset / pH) * 100\n * x' = x_pct * xScale + xPctOff\n * y' = y_pct * yScale + yPctOff\n * width' = width_pct * xScale\n * height' = height_pct * yScale\n *\n * Defaults (scale=1, offsets=0) are a no-op.\n */\nexport interface Calibration {\n /** Horizontal offset in PDF points; positive = right. */\n xOffset: number;\n /** Vertical offset in PDF points; positive = down (screen coords). */\n yOffset: number;\n /** Horizontal multiplier applied to x and width. */\n xScale: number;\n /** Vertical multiplier applied to y and height. */\n yScale: number;\n}\n\nexport const DEFAULT_CALIBRATION: Calibration = {\n xOffset: 0,\n yOffset: 0,\n xScale: 1,\n yScale: 1,\n};\n\n/**\n * Returns a copy of `fields` with calibration applied to x / y / width /\n * height. The math is page-size-aware so an `xOffset` of 5pt actually\n * shifts the rendered output 5pt to the right.\n *\n * @param pageSize Output page size in pt used to convert pt offsets to\n * percent offsets. Defaults to US Letter.\n */\nexport function applyCalibration(\n fields: FormField[],\n calibration: Calibration,\n pageSize: [number, number] = US_LETTER,\n): FormField[] {\n if (\n calibration.xOffset === 0 &&\n calibration.yOffset === 0 &&\n calibration.xScale === 1 &&\n calibration.yScale === 1\n ) {\n return fields;\n }\n const xPctOff = (calibration.xOffset / pageSize[0]) * 100;\n const yPctOff = (calibration.yOffset / pageSize[1]) * 100;\n return fields.map((f) => ({\n ...f,\n x: f.x * calibration.xScale + xPctOff,\n y: f.y * calibration.yScale + yPctOff,\n width: f.width * calibration.xScale,\n height: f.height * calibration.yScale,\n }));\n}\n\n// ---------------------------------------------------------------------------\n// Field rendering — shared by single-shot and builder\n// ---------------------------------------------------------------------------\n\nfunction hexToRgb(hex: string) {\n const r = parseInt(hex.slice(1, 3), 16) / 255;\n const g = parseInt(hex.slice(3, 5), 16) / 255;\n const b = parseInt(hex.slice(5, 7), 16) / 255;\n return rgb(r, g, b);\n}\n\nasync function renderFieldsOnPages(\n pages: PDFPage[],\n fields: FormField[],\n getFont: (family: string, bold?: boolean, italic?: boolean) => Promise<PDFFont>,\n getSignature: (dataUrl: string) => Promise<PDFImage>,\n): Promise<void> {\n for (const field of fields) {\n const page = pages[field.page];\n if (!page) continue;\n\n const pageWidth = page.getWidth();\n const pageHeight = page.getHeight();\n\n const x = (field.x / 100) * pageWidth;\n const y =\n pageHeight -\n (field.y / 100) * pageHeight -\n (field.height / 100) * pageHeight;\n const w = (field.width / 100) * pageWidth;\n const h = (field.height / 100) * pageHeight;\n\n if (isRedactField(field)) {\n page.drawRectangle({\n x,\n y,\n width: w,\n height: h,\n color: field.type === 'blackout' ? rgb(0, 0, 0) : rgb(1, 1, 1),\n });\n continue;\n }\n\n if (!field.value) continue;\n\n const inkColor = field.inkColor ? hexToRgb(field.inkColor) : rgb(0, 0, 0);\n\n if (field.type === 'checkbox') {\n if (field.value === 'true') {\n const inset = Math.min(w, h) * 0.2;\n const lineWidth = Math.min(w, h) * 0.08;\n page.drawLine({\n start: { x: x + inset, y: y + inset },\n end: { x: x + w - inset, y: y + h - inset },\n thickness: lineWidth,\n color: inkColor,\n });\n page.drawLine({\n start: { x: x + w - inset, y: y + inset },\n end: { x: x + inset, y: y + h - inset },\n thickness: lineWidth,\n color: inkColor,\n });\n }\n } else if (isSignatureField(field)) {\n if (field.value.startsWith('data:image/png')) {\n const img = await getSignature(field.value);\n page.drawImage(img, { x, y, width: w, height: h });\n }\n } else {\n // Text fields (including signed-date)\n const font = await getFont(field.fontFamily || 'Helvetica', field.bold, field.italic);\n const spacing = field.letterSpacing || 0;\n\n const textWidthAtSize = (text: string, size: number) =>\n font.widthOfTextAtSize(text, size) + spacing * (text.length - 1);\n\n // Shared with the on-screen overlay (see utils/fitText) so the preview\n // and the generated PDF shrink long values identically.\n const fontSize = fitFontSize({\n value: field.value,\n fontSize: field.fontSize,\n autoShrink: field.autoShrink,\n fieldWidthPt: w,\n fieldHeightPt: h,\n measure: textWidthAtSize,\n });\n\n // Horizontal alignment — mirrors the CSS text-align in the preview.\n const fullTextWidth = textWidthAtSize(field.value, fontSize);\n const pad = 2;\n const textX =\n field.align === 'center'\n ? x + Math.max(pad, (w - fullTextWidth) / 2)\n : field.align === 'right'\n ? x + Math.max(pad, w - fullTextWidth - pad)\n : x + pad;\n const baselineY = y + h * 0.3;\n\n if (spacing > 0) {\n let cx = textX;\n for (const char of field.value) {\n page.drawText(char, {\n x: cx,\n y: baselineY,\n size: fontSize,\n font,\n color: inkColor,\n });\n cx += font.widthOfTextAtSize(char, fontSize) + spacing;\n }\n } else {\n page.drawText(field.value, {\n x: textX,\n y: baselineY,\n size: fontSize,\n font,\n color: inkColor,\n });\n }\n\n // Underline / strikethrough decorations\n if (field.underline || field.strikethrough) {\n const textWidth = textWidthAtSize(field.value, fontSize);\n const lineThickness = Math.max(0.5, fontSize * 0.06);\n if (field.underline) {\n const uy = baselineY - fontSize * 0.12;\n page.drawLine({\n start: { x: textX, y: uy },\n end: { x: textX + textWidth, y: uy },\n thickness: lineThickness,\n color: inkColor,\n });\n }\n if (field.strikethrough) {\n const sy = baselineY + fontSize * 0.3;\n page.drawLine({\n start: { x: textX, y: sy },\n end: { x: textX + textWidth, y: sy },\n thickness: lineThickness,\n color: inkColor,\n });\n }\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Unified record options — used by both generateFilledPdf and addRecord\n// ---------------------------------------------------------------------------\n\nexport interface FillPdfOptions {\n /** Source PDF used as the background.\n * - `string` (URL): fetched, embedded once per URL across the document.\n * - `ArrayBuffer`: embedded uniquely each call.\n * - `null`: render onto blank pages (overlay-only output). */\n pdfSource: string | ArrayBuffer | null;\n /** Fields to render on top of the background. */\n fields: FormField[];\n /** Override the output page size in PDF points.\n * - With a `pdfSource`, source pages are drawn stretched to fit.\n * - With `pdfSource: null`, blank pages of this size are created.\n * - When omitted with a source, output uses the source's page sizes.\n * - When omitted with `pdfSource: null`, defaults to US Letter. */\n pageSize?: [number, number];\n /** When `pdfSource` is null, how many blank pages to render. Default `1`.\n * Fields with out-of-range `page` indices are skipped. */\n pageCount?: number;\n /** Run `resolveAllFormulas` on fields before rendering. */\n resolveFormulas?: boolean;\n /** Custom transforms merged with `BUILTIN_TRANSFORMS` during formula\n * resolution. Only meaningful when `resolveFormulas` is true. */\n customTransforms?: TransformMap;\n /** Extra named values made available to formula sources (e.g. imported CSV/\n * form data) even when there is no placed field for them. Only meaningful\n * when `resolveFormulas` is true. */\n formulaValues?: Record<string, string>;\n /** Linear calibration applied to field positions before rendering. */\n calibration?: Calibration;\n}\n\n// ---------------------------------------------------------------------------\n// Single-record API\n// ---------------------------------------------------------------------------\n\n/**\n * Generates one filled PDF.\n *\n * const bytes = await generateFilledPdf({\n * pdfSource: '/forms/template.pdf',\n * fields: template.fields,\n * pageSize: US_LETTER,\n * resolveFormulas: true,\n * });\n *\n * For multi-record output that shares a background, use `createPdfBuilder`\n * — it dedupes the embedded source across all pages.\n */\nexport async function generateFilledPdf(\n opts: FillPdfOptions,\n builderOptions?: Omit<CreatePdfBuilderOptions, 'pageSize'>,\n): Promise<Uint8Array> {\n const builder = await createPdfBuilder({\n pageSize: opts.pageSize,\n metadata: builderOptions?.metadata,\n });\n await builder.addRecord(opts);\n return builder.save();\n}\n\n// ---------------------------------------------------------------------------\n// Batch API\n// ---------------------------------------------------------------------------\n\nexport interface PdfBuilder {\n /** Underlying pdf-lib document — exposed for advanced post-processing\n * (audit-trail pages, custom metadata, etc.). */\n readonly doc: PDFDocument;\n /** Append one record's pages to the output. */\n addRecord(opts: FillPdfOptions): Promise<void>;\n /** Finalize and return the merged PDF bytes. */\n save(): Promise<Uint8Array>;\n}\n\n/** Document-level metadata applied at `save()` time. */\nexport interface PdfMetadata {\n title?: string;\n author?: string;\n subject?: string;\n creator?: string;\n producer?: string;\n /** Document creation date. Pin to a fixed `Date` for reproducible output. */\n creationDate?: Date;\n /** Document modification date. Pin to a fixed `Date` for reproducible output. */\n modificationDate?: Date;\n}\n\nexport interface CreatePdfBuilderOptions {\n /** Default `pageSize` for any `addRecord` call that doesn't set its own. */\n pageSize?: [number, number];\n /** Document metadata applied at `save()` time. Pin `creationDate` and\n * `modificationDate` to fixed `Date`s for byte-identical output across runs\n * — pdf-lib otherwise stamps the current time, so two runs of identical\n * input would differ. Useful for server-side generation and caching. */\n metadata?: PdfMetadata;\n}\n\n/** Apply optional metadata to a pdf-lib document just before serialization. */\nfunction applyMetadata(doc: PDFDocument, m?: PdfMetadata): void {\n if (!m) return;\n if (m.title !== undefined) doc.setTitle(m.title);\n if (m.author !== undefined) doc.setAuthor(m.author);\n if (m.subject !== undefined) doc.setSubject(m.subject);\n if (m.creator !== undefined) doc.setCreator(m.creator);\n if (m.producer !== undefined) doc.setProducer(m.producer);\n if (m.creationDate !== undefined) doc.setCreationDate(m.creationDate);\n if (m.modificationDate !== undefined) doc.setModificationDate(m.modificationDate);\n}\n\n/**\n * Creates a builder that merges multiple filled records into one PDF.\n *\n * Resources (source PDFs indexed by URL, embedded fonts, signature PNGs) are\n * embedded once across the whole document and reused — critical for\n * mail-merge style batches where dozens of records share the same background.\n *\n * const builder = await createPdfBuilder({ pageSize: US_LETTER });\n * for (const record of records) {\n * await builder.addRecord({\n * pdfSource: '/forms/template.pdf',\n * fields: record.fields,\n * resolveFormulas: true,\n * });\n * }\n * const bytes = await builder.save();\n * downloadPdf(bytes, 'merged.pdf');\n */\nexport async function createPdfBuilder(\n defaults: CreatePdfBuilderOptions = {},\n): Promise<PdfBuilder> {\n const doc = await PDFDocument.create();\n const fontCache = new Map<string, PDFFont>();\n const embeddedPagesByUrl = new Map<string, PDFEmbeddedPage[]>();\n const signatureCache = new Map<string, PDFImage>();\n\n async function getFont(family: string, bold?: boolean, italic?: boolean): Promise<PDFFont> {\n const key = fontKey(family, bold, italic);\n let f = fontCache.get(key);\n if (!f) {\n f = await doc.embedFont(resolveStandardFont(family, bold, italic));\n fontCache.set(key, f);\n }\n return f;\n }\n\n async function ensureFonts(fields: FormField[]) {\n const keys = new Map<string, FormField>();\n for (const f of fields) keys.set(fontKey(f.fontFamily || 'Helvetica', f.bold, f.italic), f);\n for (const f of keys.values()) await getFont(f.fontFamily || 'Helvetica', f.bold, f.italic);\n }\n\n async function embedSource(\n source: string | ArrayBuffer,\n ): Promise<PDFEmbeddedPage[]> {\n if (typeof source === 'string') {\n let pages = embeddedPagesByUrl.get(source);\n if (!pages) {\n const res = await fetch(source);\n const bytes = await res.arrayBuffer();\n const srcDoc = await PDFDocument.load(bytes);\n pages = await Promise.all(\n srcDoc.getPages().map((p) => doc.embedPage(p)),\n );\n embeddedPagesByUrl.set(source, pages);\n }\n return pages;\n }\n // ArrayBuffer sources are treated as unique per call.\n const srcDoc = await PDFDocument.load(source);\n return Promise.all(srcDoc.getPages().map((p) => doc.embedPage(p)));\n }\n\n async function getSignature(dataUrl: string): Promise<PDFImage> {\n let img = signatureCache.get(dataUrl);\n if (!img) {\n const b64 = dataUrl.split(',')[1] ?? '';\n const pngBytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));\n img = await doc.embedPng(pngBytes);\n signatureCache.set(dataUrl, img);\n }\n return img;\n }\n\n return {\n doc,\n async addRecord(opts: FillPdfOptions) {\n const pageSize = opts.pageSize ?? defaults.pageSize;\n\n let fields = opts.resolveFormulas\n ? resolveAllFormulas(opts.fields, opts.customTransforms, opts.formulaValues)\n : opts.fields;\n\n if (opts.calibration) {\n fields = applyCalibration(\n fields,\n opts.calibration,\n pageSize ?? US_LETTER,\n );\n }\n\n await ensureFonts(fields);\n\n let sourcePages: PDFEmbeddedPage[] = [];\n let pageCount: number;\n if (opts.pdfSource !== null) {\n sourcePages = await embedSource(opts.pdfSource);\n pageCount = sourcePages.length;\n } else {\n pageCount = opts.pageCount ?? 1;\n }\n\n const newPages: PDFPage[] = [];\n for (let i = 0; i < pageCount; i++) {\n const size: [number, number] = pageSize\n ? pageSize\n : sourcePages[i]\n ? [sourcePages[i].width, sourcePages[i].height]\n : US_LETTER;\n const page = doc.addPage(size);\n newPages.push(page);\n if (sourcePages[i]) {\n page.drawPage(sourcePages[i], {\n x: 0,\n y: 0,\n width: size[0],\n height: size[1],\n });\n }\n }\n\n await renderFieldsOnPages(newPages, fields, getFont, getSignature);\n },\n async save() {\n applyMetadata(doc, defaults.metadata);\n return doc.save();\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Browser helpers\n// ---------------------------------------------------------------------------\n\nexport function downloadPdf(bytes: Uint8Array, filename: string) {\n const blob = new Blob([bytes.slice().buffer], { type: 'application/pdf' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n a.click();\n URL.revokeObjectURL(url);\n}\n\nexport async function postPdfToCallback(\n bytes: Uint8Array,\n callbackUrl: string,\n filename: string,\n) {\n const blob = new Blob([bytes.slice().buffer], { type: 'application/pdf' });\n const formData = new FormData();\n formData.append('file', blob, filename);\n\n await fetch(callbackUrl, {\n method: 'POST',\n body: formData,\n });\n}\n","export function generateId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport type FieldType = 'text' | 'dropdown' | 'signature' | 'signed-date' | 'checkbox' | 'initials' | 'blackout' | 'whiteout';\n\nexport type TextSubtype = 'freeform' | 'number' | 'date' | 'email' | 'phone';\n\nexport interface FormField {\n id: string;\n type: FieldType;\n textSubtype?: TextSubtype;\n label: string;\n placeholder: string;\n required: boolean;\n assignee: string; // signer role e.g. \"Sender\", \"Signer 1\"\n page: number; // 0-indexed page number\n x: number; // percentage of page width (0-100)\n y: number; // percentage of page height (0-100)\n width: number; // percentage of page width\n height: number; // percentage of page height\n fontSize: number; // in points\n value: string; // pre-filled value or current value\n inkColor?: string; // ink color for text/signature fields (default: '#000000')\n letterSpacing?: number; // extra spacing between characters in points (default: 0)\n lineHeight?: number; // line height multiplier (default: 1.2)\n align?: 'left' | 'center' | 'right'; // horizontal text alignment (default: 'left')\n bold?: boolean; // render text in the bold variant of fontFamily (default: false)\n italic?: boolean; // render text in the italic/oblique variant of fontFamily (default: false)\n underline?: boolean; // draw an underline beneath the text (default: false)\n strikethrough?: boolean; // draw a line through the text (default: false)\n minLength?: number; // min character count (0 = no minimum)\n maxLength?: number; // max character count (0 = unlimited)\n fontFamily?: string; // font family (default: 'Helvetica')\n options?: string[]; // predefined options for dropdown/radio selection\n formula?: string; // template expression e.g. \"{{Date Field | month}}\" — auto-computed from other fields\n locked?: boolean; // when true, field cannot be moved or edited in designer\n autoShrink?: boolean; // when true, font auto-shrinks to fit field width (default: false)\n}\n\nexport interface Template {\n fields: FormField[];\n signerRoles: string[];\n pdfUrl: string;\n}\n\nexport const DEFAULT_SIGNER_ROLES = ['Sender', 'Signer 1'];\n\nexport const SIGNER_ROLE_COLORS: Record<string, string> = {\n 'Sender': '#6366f1',\n 'Signer 1': '#22c55e',\n 'Signer 2': '#f59e0b',\n 'Signer 3': '#ef4444',\n 'Signer 4': '#06b6d4',\n 'Signer 5': '#d946ef',\n};\n\nexport function getSignerColor(role: string): string {\n return SIGNER_ROLE_COLORS[role] || '#888888';\n}\n\n// ── Field type helpers ──────────────────────\n\nexport function isRedactField(f: FormField | { type: FieldType }): boolean {\n return f.type === 'blackout' || f.type === 'whiteout';\n}\n\nexport function isSignatureField(f: FormField | { type: FieldType }): boolean {\n return f.type === 'signature' || f.type === 'initials';\n}\n\nexport function isTextLikeField(f: FormField | { type: FieldType }): boolean {\n return f.type === 'text' || f.type === 'dropdown' || f.type === 'signed-date';\n}\n\nexport function getInputType(subtype?: TextSubtype): string {\n switch (subtype) {\n case 'email': return 'email';\n case 'number': return 'number';\n case 'phone': return 'tel';\n case 'date': return 'date';\n default: return 'text';\n }\n}\n\nconst CSS_FONT_MAP: Record<string, string> = {\n Courier: '\"Courier New\", Courier, monospace',\n TimesRoman: '\"Times New Roman\", Times, serif',\n Helvetica: 'Helvetica, Arial, sans-serif',\n};\n\nexport function getCssFontFamily(fontFamily?: string): string | undefined {\n return fontFamily ? CSS_FONT_MAP[fontFamily] : undefined;\n}\n\n/**\n * CSS style fragment for a field's text formatting (font family + bold /\n * italic / underline / strikethrough), so the on-screen preview matches the\n * generated PDF. Spread alongside fontSize / letterSpacing / lineHeight.\n */\nexport function getCssTextStyle(field: Pick<FormField, 'fontFamily' | 'bold' | 'italic' | 'underline' | 'strikethrough' | 'align'>): Record<string, string | undefined> {\n const decorations: string[] = [];\n if (field.underline) decorations.push('underline');\n if (field.strikethrough) decorations.push('line-through');\n const align = field.align ?? 'left';\n return {\n fontFamily: getCssFontFamily(field.fontFamily),\n fontWeight: field.bold ? 'bold' : undefined,\n fontStyle: field.italic ? 'italic' : undefined,\n textDecorationLine: decorations.length ? decorations.join(' ') : undefined,\n textAlign: field.align,\n // Hug the alignment edge — no padding on the trailing side — so text reaches\n // the container edge (matches the PDF's 2pt offsets).\n paddingLeft: align === 'right' ? '0px' : '2px',\n paddingRight: align === 'left' ? '0px' : '2px',\n };\n}\n\nexport function sortFieldsByPosition(fields: FormField[]): FormField[] {\n return [...fields].sort((a, b) => {\n if (a.page !== b.page) return a.page - b.page;\n const bandThreshold = 2;\n if (Math.abs(a.y - b.y) > bandThreshold) return a.y - b.y;\n return a.x - b.x;\n });\n}\n\nexport function preserveFieldValues(oldFields: FormField[], newFields: FormField[]): FormField[] {\n const valueMap = new Map(oldFields.filter(f => f.value).map(f => [f.id, f.value]));\n return newFields.map(f => valueMap.has(f.id) ? { ...f, value: valueMap.get(f.id)! } : f);\n}\n\nexport function getFieldValues(fields: FormField[]): Record<string, string> {\n const values: Record<string, string> = {};\n fields.forEach(f => { if (!isRedactField(f)) values[f.label] = f.value || ''; });\n return values;\n}\n\nexport const FONT_FAMILIES = [\n { value: 'Helvetica', label: 'Helvetica' },\n { value: 'Courier', label: 'Courier New' },\n { value: 'TimesRoman', label: 'Times New Roman' },\n] as const;\n\nexport const FIELD_DEFAULTS: Record<FieldType, Partial<FormField>> = {\n text: {\n width: 20,\n height: 3,\n fontSize: 12,\n placeholder: 'Enter text',\n textSubtype: 'freeform',\n },\n dropdown: {\n width: 20,\n height: 3,\n fontSize: 12,\n placeholder: 'Select...',\n },\n signature: {\n width: 20,\n height: 6,\n fontSize: 12,\n placeholder: 'Sign here',\n },\n 'signed-date': {\n width: 15,\n height: 3,\n fontSize: 12,\n placeholder: 'Date',\n },\n checkbox: {\n width: 2.5,\n height: 2.5,\n fontSize: 12,\n placeholder: '',\n },\n initials: {\n width: 8,\n height: 5,\n fontSize: 12,\n placeholder: 'Initials',\n },\n blackout: {\n width: 20,\n height: 3,\n fontSize: 12,\n placeholder: '',\n },\n whiteout: {\n width: 20,\n height: 3,\n fontSize: 12,\n placeholder: '',\n },\n};\n\nconst TYPE_LABELS: Record<FieldType, string> = {\n text: 'Text Field',\n dropdown: 'Dropdown',\n signature: 'Signature',\n 'signed-date': 'Signed Date',\n checkbox: 'Checkbox',\n initials: 'Initials',\n blackout: 'Blackout',\n whiteout: 'Whiteout',\n};\n\n/** Given a desired label and a list of existing labels, return a unique label by appending a number if needed. */\nexport function uniqueLabel(desired: string, existingLabels: string[]): string {\n const lower = desired.toLowerCase();\n if (!existingLabels.some(l => l.toLowerCase() === lower)) return desired;\n let i = 2;\n while (existingLabels.some(l => l.toLowerCase() === `${lower} ${i}`)) i++;\n return `${desired} ${i}`;\n}\n\nexport function createField(\n type: FieldType,\n assignee: string,\n page: number,\n x: number,\n y: number,\n existingFields?: FormField[],\n): FormField {\n const defaults = FIELD_DEFAULTS[type];\n const baseLabel = TYPE_LABELS[type];\n const existingLabels = existingFields?.map(f => f.label) ?? [];\n return {\n id: generateId(),\n type,\n label: uniqueLabel(baseLabel, existingLabels),\n placeholder: defaults.placeholder || '',\n required: type === 'checkbox' || type === 'blackout' || type === 'whiteout' ? false : true,\n assignee,\n page,\n x,\n y,\n width: defaults.width || 20,\n height: defaults.height || 3,\n fontSize: defaults.fontSize || 12,\n value: '',\n ...(type === 'text' ? { textSubtype: defaults.textSubtype as TextSubtype } : {}),\n };\n}\n","import type { FormField } from '@/types/pdf-builder';\n\nexport type TransformFn = (value: string) => string;\nexport type TransformMap = Record<string, TransformFn>;\n\n/**\n * Parse a date string robustly into a local Date (midnight, local TZ) so that\n * getMonth/getDate/getFullYear are calendar-correct. Handles:\n * - ISO date-only \"YYYY-MM-DD\" → parsed as LOCAL (avoids the classic UTC\n * off-by-one where \"2024-03-15\" becomes the 14th in western timezones).\n * - Excel serial numbers (a bare integer, e.g. \"45000\") → converted.\n * - Anything else → native `new Date` (handles \"M/D/YYYY\", ISO datetimes, …).\n * Returns null when unparseable.\n */\nexport function parseDate(value: string): Date | null {\n const s = value.trim();\n if (!s) return null;\n\n // Excel serial date (purely numeric): days since 1899-12-30.\n if (/^\\d+(\\.\\d+)?$/.test(s)) {\n const serial = parseFloat(s);\n if (serial > 59) {\n const utc = new Date(Math.round((serial - 25569) * 86400000));\n if (!isNaN(utc.getTime())) {\n return new Date(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate());\n }\n }\n }\n\n // ISO date-only → construct in local time to avoid UTC shift.\n const iso = s.match(/^(\\d{4})-(\\d{2})-(\\d{2})$/);\n if (iso) return new Date(+iso[1], +iso[2] - 1, +iso[3]);\n\n const d = new Date(s);\n return isNaN(d.getTime()) ? null : d;\n}\n\n/** Built-in transforms that ship with exeq. */\nexport const BUILTIN_TRANSFORMS: TransformMap = {\n // Date transforms (expects a parseable date string)\n month: (v) => { const d = parseDate(v); return d ? String(d.getMonth() + 1) : ''; },\n month2: (v) => { const d = parseDate(v); return d ? String(d.getMonth() + 1).padStart(2, '0') : ''; },\n monthname: (v) => { const d = parseDate(v); return d ? d.toLocaleString('en', { month: 'long' }) : ''; },\n monthshort: (v) => { const d = parseDate(v); return d ? d.toLocaleString('en', { month: 'short' }) : ''; },\n day: (v) => { const d = parseDate(v); return d ? String(d.getDate()) : ''; },\n day2: (v) => { const d = parseDate(v); return d ? String(d.getDate()).padStart(2, '0') : ''; },\n year: (v) => { const d = parseDate(v); return d ? String(d.getFullYear()) : ''; },\n year2: (v) => { const d = parseDate(v); return d ? String(d.getFullYear()).slice(-2) : ''; },\n\n // String transforms\n upper: (v) => v.toUpperCase(),\n lower: (v) => v.toLowerCase(),\n trim: (v) => v.trim(),\n first: (v) => v.split(/\\s+/)[0] || '',\n last: (v) => { const parts = v.split(/\\s+/); return parts[parts.length - 1] || ''; },\n initials: (v) => v.split(/\\s+/).map(w => w[0] || '').join('').toUpperCase(),\n\n // Name parts. Handles \"Last, First [Middle]\" (comma form) and \"First [Middle]\n // Last\" (no comma). firstName → the given name(s); lastName → the surname.\n firstName: (v) => {\n const c = v.indexOf(',');\n if (c >= 0) return v.slice(c + 1).trim();\n const parts = v.trim().split(/\\s+/).filter(Boolean);\n return parts.length > 1 ? parts.slice(0, -1).join(' ') : (parts[0] || '');\n },\n lastName: (v) => {\n const c = v.indexOf(',');\n if (c >= 0) return v.slice(0, c).trim();\n const parts = v.trim().split(/\\s+/).filter(Boolean);\n return parts.length > 1 ? parts[parts.length - 1] : (parts[0] || '');\n },\n\n // Numeric / substring\n last4: (v) => v.slice(-4),\n last2: (v) => v.slice(-2),\n first4: (v) => v.slice(0, 4),\n first2: (v) => v.slice(0, 2),\n digits: (v) => v.replace(/\\D/g, ''),\n number: (v) => { const n = parseFloat(v); return isNaN(n) ? '' : String(n); },\n currency: (v) => { const n = parseFloat(v.replace(/[^0-9.-]/g, '')); return isNaN(n) ? '' : `$${n.toFixed(2)}`; },\n};\n\nconst FORMULA_RE = /\\{\\{(.+?)\\}\\}/g;\nconst PIPE_RE = /^(.+?)\\s*\\|\\s*(.+)$/;\n\n/** Current date as a local \"YYYY-MM-DD\" string (safe for the date transforms). */\nfunction todayIso(): string {\n const d = new Date();\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;\n}\n\n/**\n * Resolve a single formula string against a set of fields and transforms.\n * Formula format: \"{{Source Field Label | transform}}\" or \"{{Source Field Label}}\" (no transform = raw value).\n * Multiple expressions can appear in one formula: \"{{First}} {{Last}}\" → \"Jane Smith\"\n *\n * Source resolution order for \"{{Name}}\":\n * 1. a placed field whose label (case-insensitive) or id matches Name\n * 2. `values[Name]` — imported/contextual data not tied to a placed field\n * 3. the built-in `today` / `now` source (current date)\n *\n * @param values Extra named values (e.g. imported CSV/form data) made available\n * to formula sources even when there is no placed field for them.\n */\nexport function resolveFormula(\n formula: string,\n fields: FormField[],\n customTransforms?: TransformMap,\n values?: Record<string, string>,\n): string {\n const transforms = { ...BUILTIN_TRANSFORMS, ...customTransforms };\n\n return formula.replace(FORMULA_RE, (_match, expr: string) => {\n const pipeMatch = expr.match(PIPE_RE);\n const sourceLabel = (pipeMatch ? pipeMatch[1] : expr).trim();\n const transformName = pipeMatch ? pipeMatch[2].trim() : null;\n const lowerLabel = sourceLabel.toLowerCase();\n\n // 1. Placed field by label (case-insensitive) or id\n const sourceField = fields.find(f => f.label.toLowerCase() === lowerLabel)\n || fields.find(f => f.id === sourceLabel);\n\n let rawValue: string | undefined;\n\n // 1. A placed field with a non-empty value wins.\n if (sourceField && sourceField.value) {\n rawValue = sourceField.value;\n }\n\n // 2. Otherwise the provided values map (case-insensitive). This also covers\n // a placed field that exists but is empty — e.g. the source is imported\n // from a spreadsheet column rather than typed into a drawn field.\n if (rawValue === undefined && values) {\n const key = Object.keys(values).find(k => k.toLowerCase() === lowerLabel);\n if (key !== undefined) rawValue = values[key] || '';\n }\n\n // 2b. An empty placed field with no imported value resolves to empty.\n if (rawValue === undefined && sourceField) {\n rawValue = sourceField.value || '';\n }\n\n // 3. Built-in current-date source\n if (rawValue === undefined && (lowerLabel === 'today' || lowerLabel === 'now')) {\n rawValue = todayIso();\n }\n\n if (rawValue === undefined) return '';\n if (!transformName) return rawValue;\n\n const fn = transforms[transformName];\n if (!fn) return rawValue; // unknown transform → return raw value\n\n try {\n return fn(rawValue);\n } catch {\n return rawValue;\n }\n });\n}\n\n/**\n * Resolve all formula fields in a fields array.\n * Returns a new array with computed values filled in.\n *\n * @param values Extra named values available to formula sources (see resolveFormula).\n */\nexport function resolveAllFormulas(\n fields: FormField[],\n customTransforms?: TransformMap,\n values?: Record<string, string>,\n): FormField[] {\n return fields.map(f => {\n if (!f.formula) return f;\n const computed = resolveFormula(f.formula, fields, customTransforms, values);\n return computed !== f.value ? { ...f, value: computed } : f;\n });\n}\n","/**\n * Shared \"shrink text to fit a field\" logic, used by BOTH the PDF filler and\n * the on-screen signer/designer overlay so the live preview matches the\n * generated PDF exactly (previously the PDF auto-shrank long values but the\n * overlay rendered them at the raw font size, so the two disagreed).\n *\n * The measurement is injected so each side can supply its own text-width\n * function (pdf-lib's font metrics for the PDF; canvas measureText for the\n * browser) while sharing the identical fit algorithm.\n */\n\nimport { getCssFontFamily } from '../types/pdf-builder';\n\nexport interface FitFontSizeOptions {\n value: string;\n /** The field's configured font size, in points. */\n fontSize: number;\n /** When true, cap at 70% of field height and shrink to fit the width. */\n autoShrink?: boolean;\n /** Field width in points. */\n fieldWidthPt: number;\n /** Field height in points. */\n fieldHeightPt: number;\n /** Width of `text` at `size` (points), in the same units as fieldWidthPt. */\n measure: (text: string, size: number) => number;\n}\n\n/**\n * Mirrors the algorithm in pdfFiller: start from the configured size (capped at\n * height*0.7 when autoShrink), then step down by 0.5pt until the value fits the\n * field width minus a small padding. Floored at 4pt.\n */\nexport function fitFontSize(o: FitFontSizeOptions): number {\n let size = o.autoShrink ? Math.min(o.fontSize, o.fieldHeightPt * 0.7) : o.fontSize;\n if (o.autoShrink && o.value) {\n const padding = 4;\n while (size > 4) {\n if (o.measure(o.value, size) <= o.fieldWidthPt - padding) break;\n size -= 0.5;\n }\n }\n return size;\n}\n\nlet measureCtx: CanvasRenderingContext2D | null = null;\n\n/**\n * Browser text-width measurement for the overlay. Returns the width of `text`\n * rendered at `size` with the field's font — numerically comparable to a field\n * width expressed in points (the ratio is scale-invariant), so it can drive\n * `fitFontSize` directly.\n */\nexport function measureTextWidth(\n text: string,\n size: number,\n opts?: { fontFamily?: string; bold?: boolean; italic?: boolean; letterSpacing?: number },\n): number {\n if (typeof document === 'undefined') return text.length * size * 0.5;\n if (!measureCtx) measureCtx = document.createElement('canvas').getContext('2d');\n if (!measureCtx) return text.length * size * 0.5;\n const family = getCssFontFamily(opts?.fontFamily) || 'Helvetica, Arial, sans-serif';\n measureCtx.font = `${opts?.italic ? 'italic ' : ''}${opts?.bold ? 'bold ' : ''}${size}px ${family}`;\n const base = measureCtx.measureText(text).width;\n const spacing = opts?.letterSpacing ? opts.letterSpacing * Math.max(0, text.length - 1) : 0;\n return base + spacing;\n}\n"],"mappings":"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","names":["srcDoc"]}
@@ -0,0 +1,61 @@
1
+ import {
2
+ A4,
3
+ BUILTIN_TRANSFORMS,
4
+ DEFAULT_CALIBRATION,
5
+ DEFAULT_SIGNER_ROLES,
6
+ FIELD_DEFAULTS,
7
+ FONT_FAMILIES,
8
+ SIGNER_ROLE_COLORS,
9
+ US_LEGAL,
10
+ US_LETTER,
11
+ applyCalibration,
12
+ createField,
13
+ createPdfBuilder,
14
+ fitFontSize,
15
+ generateFilledPdf,
16
+ generateId,
17
+ getCssFontFamily,
18
+ getFieldValues,
19
+ getInputType,
20
+ getSignerColor,
21
+ isRedactField,
22
+ isSignatureField,
23
+ isTextLikeField,
24
+ parseDate,
25
+ preserveFieldValues,
26
+ resolveAllFormulas,
27
+ resolveFormula,
28
+ sortFieldsByPosition,
29
+ uniqueLabel
30
+ } from "./chunk-OLRWRBLO.mjs";
31
+ export {
32
+ A4,
33
+ BUILTIN_TRANSFORMS,
34
+ DEFAULT_CALIBRATION,
35
+ DEFAULT_SIGNER_ROLES,
36
+ FIELD_DEFAULTS,
37
+ FONT_FAMILIES,
38
+ SIGNER_ROLE_COLORS,
39
+ US_LEGAL,
40
+ US_LETTER,
41
+ applyCalibration,
42
+ createField,
43
+ createPdfBuilder,
44
+ fitFontSize,
45
+ generateFilledPdf,
46
+ generateId,
47
+ getCssFontFamily,
48
+ getFieldValues,
49
+ getInputType,
50
+ getSignerColor,
51
+ isRedactField,
52
+ isSignatureField,
53
+ isTextLikeField,
54
+ parseDate,
55
+ preserveFieldValues,
56
+ resolveAllFormulas,
57
+ resolveFormula,
58
+ sortFieldsByPosition,
59
+ uniqueLabel
60
+ };
61
+ //# sourceMappingURL=server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unlev/exeq",
3
- "version": "0.5.6",
3
+ "version": "0.6.0",
4
4
  "description": "Embeddable PDF form builder and document signing — client-side, no backend required",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -12,6 +12,11 @@
12
12
  "import": "./dist/index.mjs",
13
13
  "require": "./dist/index.js"
14
14
  },
15
+ "./server": {
16
+ "types": "./dist/server.d.ts",
17
+ "import": "./dist/server.mjs",
18
+ "require": "./dist/server.js"
19
+ },
15
20
  "./styles": "./dist/index.css"
16
21
  },
17
22
  "files": [
@@ -22,7 +27,13 @@
22
27
  "dist/index.css",
23
28
  "dist/index.css.map",
24
29
  "dist/index.js.map",
25
- "dist/index.mjs.map"
30
+ "dist/index.mjs.map",
31
+ "dist/server.js",
32
+ "dist/server.mjs",
33
+ "dist/server.d.ts",
34
+ "dist/server.d.mts",
35
+ "dist/server.js.map",
36
+ "dist/server.mjs.map"
26
37
  ],
27
38
  "sideEffects": [
28
39
  "*.css"