@signiphi/page-assembly 0.2.0-beta.1 → 0.2.0-beta.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.d.mts CHANGED
@@ -2,6 +2,7 @@ import * as React from 'react';
2
2
  import React__default from 'react';
3
3
  import * as class_variance_authority_types from 'class-variance-authority/types';
4
4
  import { VariantProps } from 'class-variance-authority';
5
+ import { PDFDocument } from 'pdf-lib';
5
6
 
6
7
  /**
7
8
  * Represents a single page in the page assembly system
@@ -39,6 +40,52 @@ type FileInfo = {
39
40
  /** Pages extracted from this file */
40
41
  pages: PageInfo[];
41
42
  };
43
+ /**
44
+ * Form field with page tracking for assembly operations
45
+ */
46
+ type TrackedFormField = {
47
+ /** Field name */
48
+ name: string;
49
+ /** Field type */
50
+ type: string;
51
+ /** Field position */
52
+ position: {
53
+ x: number;
54
+ y: number;
55
+ width: number;
56
+ height: number;
57
+ page: number;
58
+ };
59
+ /** Page ID this field is associated with (for tracking across page operations) */
60
+ pageId?: string;
61
+ /** Original file ID this field came from */
62
+ originalFileId?: string;
63
+ /** All other field properties */
64
+ label?: string;
65
+ required?: boolean;
66
+ options?: string[];
67
+ placeholder?: string;
68
+ defaultValue?: string;
69
+ assignedSignerEmail?: string;
70
+ fieldId?: string;
71
+ fontSize?: number;
72
+ multiline?: boolean;
73
+ maxLength?: number;
74
+ acknowledgements?: Array<{
75
+ id: string;
76
+ title: string;
77
+ description: string;
78
+ }>;
79
+ };
80
+ /**
81
+ * Extracted fields from a file
82
+ */
83
+ type FileExtractedFields = {
84
+ /** File ID these fields came from */
85
+ fileId: string;
86
+ /** Extracted form fields */
87
+ fields: TrackedFormField[];
88
+ };
42
89
  /**
43
90
  * State of the page assembler
44
91
  */
@@ -49,6 +96,10 @@ type PageAssemblerState = {
49
96
  selection: string[];
50
97
  /** ID of the last selected page (for range selection) */
51
98
  lastSelectedPageId?: string;
99
+ /** Form fields tracked across page operations */
100
+ formFields?: TrackedFormField[];
101
+ /** Extracted fields per file (for mapping after assembly) */
102
+ extractedFieldsByFile?: FileExtractedFields[];
52
103
  };
53
104
  /**
54
105
  * Options for assembling the final PDF
@@ -136,6 +187,18 @@ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAtt
136
187
  declare function pdfToImages(pdfBytes: Uint8Array, options?: {
137
188
  hideFormFields?: boolean;
138
189
  }): Promise<PageImage[]>;
190
+ declare function rasterizePdfToPdf(pdfBytes: Uint8Array): Promise<Uint8Array>;
191
+ /**
192
+ * Prepares uploaded PDF bytes for the pdf-lib based assembly pipeline.
193
+ * Regular PDFs pass through untouched. Encrypted PDFs (typically
194
+ * permission-restricted documents that open without a password) are
195
+ * decrypted once here so every downstream `PDFDocument.load` — assembly,
196
+ * field extraction — sees a normal document. When structural decryption is
197
+ * impossible the document is rebuilt from rendered pages as a last resort.
198
+ *
199
+ * @throws {PdfPasswordRequiredError} when the PDF needs a real password
200
+ */
201
+ declare function normalizeUploadedPdfBytes(pdfBytes: Uint8Array): Promise<Uint8Array>;
139
202
  /**
140
203
  * Converts an image file to a PDF document with a single page
141
204
  *
@@ -175,4 +238,156 @@ declare function createPdfBlobUrl(pdfBytes: Uint8Array): string;
175
238
  */
176
239
  declare function downloadPdf(pdfBytes: Uint8Array, filename: string): void;
177
240
 
178
- export { type AssembleOptions, Button, type FileInfo, PageAssembler, type PageAssemblerHandle, type PageAssemblerProps, type PageAssemblerState, type PageImage, type PageInfo, createPdfBlobUrl, PageAssembler as default, downloadPdf, imageToPdf, pdfToImages };
241
+ declare class PdfPasswordRequiredError extends Error {
242
+ code: string;
243
+ recoverable: boolean;
244
+ userMessage: string;
245
+ constructor();
246
+ }
247
+ declare class UnsupportedPdfEncryptionError extends Error {
248
+ constructor(detail: string);
249
+ }
250
+ /**
251
+ * Decrypt an encrypted PDF that opens with an empty user password.
252
+ * Returns re-saved, fully decrypted bytes with `/Encrypt` removed.
253
+ *
254
+ * @throws {PdfPasswordRequiredError} when a non-empty password is required
255
+ * @throws {UnsupportedPdfEncryptionError} for non-standard security handlers
256
+ */
257
+ declare function decryptPdf(pdfBytes: Uint8Array): Promise<Uint8Array>;
258
+ /**
259
+ * Ingestion gate: returns the bytes untouched for regular PDFs, and a
260
+ * decrypted re-save for encrypted ones so every downstream `PDFDocument.load`
261
+ * (page assembly, field extraction) sees a normal document.
262
+ */
263
+ declare function normalizePdfEncryption(pdfBytes: Uint8Array): Promise<Uint8Array>;
264
+
265
+ /**
266
+ * PDF Field Extraction Utilities
267
+ * Extract form fields from PDFs with metadata support for preserving field properties
268
+ */
269
+
270
+ /**
271
+ * Extracted field information
272
+ */
273
+ interface ExtractedField {
274
+ name: string;
275
+ type: 'text' | 'signature' | 'initials' | 'date' | 'checkbox' | 'radio' | 'dropdown' | 'text_label';
276
+ page: number;
277
+ x: number;
278
+ y: number;
279
+ width: number;
280
+ height: number;
281
+ required: boolean;
282
+ label?: string;
283
+ placeholder?: string;
284
+ options?: string[];
285
+ fieldId?: string;
286
+ signer?: string;
287
+ }
288
+ /**
289
+ * SigniphiMetadata structure stored in PDF Info dictionary
290
+ */
291
+ interface SigniphiMetadata {
292
+ version: string;
293
+ fields: Record<string, {
294
+ fieldId?: string;
295
+ label?: string;
296
+ signer?: string;
297
+ placeholder?: string;
298
+ required?: boolean;
299
+ options?: string[];
300
+ acknowledgements?: Array<{
301
+ id: string;
302
+ title: string;
303
+ description: string;
304
+ }>;
305
+ }>;
306
+ fieldIdIndex?: Record<string, string>;
307
+ }
308
+ /**
309
+ * Extract SigniphiMetadata from a PDF document
310
+ */
311
+ declare function getSigniphiMetadata(pdfDoc: PDFDocument): SigniphiMetadata | null;
312
+ /**
313
+ * Extract form fields from a PDF document
314
+ * @param pdfBytes - PDF bytes
315
+ * @returns Array of extracted fields with all properties
316
+ */
317
+ declare function extractFieldsFromPdf(pdfBytes: Uint8Array): Promise<ExtractedField[]>;
318
+ /**
319
+ * Set SigniphiMetadata in a PDF document
320
+ */
321
+ declare function setSigniphiMetadata(pdfDoc: PDFDocument, metadata: SigniphiMetadata): void;
322
+
323
+ /**
324
+ * Add Form Fields to PDF
325
+ * Re-adds form fields to a PDF after page assembly operations
326
+ * This is the key to preserving form fields - don't try to preserve during copyPages,
327
+ * instead extract fields first, copy pages, then re-add fields with adjusted positions.
328
+ */
329
+ /**
330
+ * Form field type enum matching document-prepare
331
+ */
332
+ declare enum FormFieldType {
333
+ TEXT = "text",
334
+ SIGNATURE = "signature",
335
+ INITIALS = "initials",
336
+ DATE = "date",
337
+ CHECKBOX = "checkbox",
338
+ RADIO = "radio",
339
+ DROPDOWN = "dropdown",
340
+ TEXT_LABEL = "text_label"
341
+ }
342
+ /**
343
+ * Form field position
344
+ */
345
+ interface FormFieldPosition {
346
+ x: number;
347
+ y: number;
348
+ width: number;
349
+ height: number;
350
+ page: number;
351
+ }
352
+ /**
353
+ * Form field for adding to PDF
354
+ */
355
+ interface FormFieldForPdf {
356
+ name: string;
357
+ type: FormFieldType | string;
358
+ position: FormFieldPosition;
359
+ label?: string;
360
+ required?: boolean;
361
+ options?: string[];
362
+ defaultValue?: string;
363
+ placeholder?: string;
364
+ fontSize?: number;
365
+ multiline?: boolean;
366
+ maxLength?: number;
367
+ assignedSignerEmail?: string;
368
+ }
369
+ /**
370
+ * Add form fields to a PDF document
371
+ *
372
+ * @param pdfBytes - The PDF document bytes
373
+ * @param formFields - Array of form fields to add
374
+ * @param options - Options for field addition
375
+ * @returns Modified PDF bytes with form fields added
376
+ */
377
+ declare function addFormFieldsToPdf(pdfBytes: Uint8Array, formFields: FormFieldForPdf[], options?: {
378
+ removeExistingFields?: boolean;
379
+ drawLabels?: boolean;
380
+ }): Promise<Uint8Array>;
381
+ /**
382
+ * Map field positions after page assembly
383
+ * Updates field page numbers based on the final page arrangement
384
+ *
385
+ * @param fields - Original fields with positions
386
+ * @param pageMapping - Map of "originalFileId_originalPageIndex" -> newPageNumber
387
+ * @returns Fields with updated page positions
388
+ */
389
+ declare function mapFieldPositionsAfterAssembly<T extends {
390
+ position: FormFieldPosition;
391
+ }>(fields: T[], pageMapping: Map<string, number>): T[];
392
+
393
+ export { type AssembleOptions, Button, type ExtractedField, type FileExtractedFields, type FileInfo, type FormFieldForPdf, type FormFieldPosition, FormFieldType, PageAssembler, type PageAssemblerHandle, type PageAssemblerProps, type PageAssemblerState, type PageImage, type PageInfo, PdfPasswordRequiredError, type TrackedFormField, UnsupportedPdfEncryptionError, addFormFieldsToPdf, createPdfBlobUrl, decryptPdf, downloadPdf, extractFieldsFromPdf, getSigniphiMetadata, imageToPdf, mapFieldPositionsAfterAssembly, normalizePdfEncryption, normalizeUploadedPdfBytes, pdfToImages, rasterizePdfToPdf, setSigniphiMetadata };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import * as React from 'react';
2
2
  import React__default from 'react';
3
3
  import * as class_variance_authority_types from 'class-variance-authority/types';
4
4
  import { VariantProps } from 'class-variance-authority';
5
+ import { PDFDocument } from 'pdf-lib';
5
6
 
6
7
  /**
7
8
  * Represents a single page in the page assembly system
@@ -39,6 +40,52 @@ type FileInfo = {
39
40
  /** Pages extracted from this file */
40
41
  pages: PageInfo[];
41
42
  };
43
+ /**
44
+ * Form field with page tracking for assembly operations
45
+ */
46
+ type TrackedFormField = {
47
+ /** Field name */
48
+ name: string;
49
+ /** Field type */
50
+ type: string;
51
+ /** Field position */
52
+ position: {
53
+ x: number;
54
+ y: number;
55
+ width: number;
56
+ height: number;
57
+ page: number;
58
+ };
59
+ /** Page ID this field is associated with (for tracking across page operations) */
60
+ pageId?: string;
61
+ /** Original file ID this field came from */
62
+ originalFileId?: string;
63
+ /** All other field properties */
64
+ label?: string;
65
+ required?: boolean;
66
+ options?: string[];
67
+ placeholder?: string;
68
+ defaultValue?: string;
69
+ assignedSignerEmail?: string;
70
+ fieldId?: string;
71
+ fontSize?: number;
72
+ multiline?: boolean;
73
+ maxLength?: number;
74
+ acknowledgements?: Array<{
75
+ id: string;
76
+ title: string;
77
+ description: string;
78
+ }>;
79
+ };
80
+ /**
81
+ * Extracted fields from a file
82
+ */
83
+ type FileExtractedFields = {
84
+ /** File ID these fields came from */
85
+ fileId: string;
86
+ /** Extracted form fields */
87
+ fields: TrackedFormField[];
88
+ };
42
89
  /**
43
90
  * State of the page assembler
44
91
  */
@@ -49,6 +96,10 @@ type PageAssemblerState = {
49
96
  selection: string[];
50
97
  /** ID of the last selected page (for range selection) */
51
98
  lastSelectedPageId?: string;
99
+ /** Form fields tracked across page operations */
100
+ formFields?: TrackedFormField[];
101
+ /** Extracted fields per file (for mapping after assembly) */
102
+ extractedFieldsByFile?: FileExtractedFields[];
52
103
  };
53
104
  /**
54
105
  * Options for assembling the final PDF
@@ -136,6 +187,18 @@ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAtt
136
187
  declare function pdfToImages(pdfBytes: Uint8Array, options?: {
137
188
  hideFormFields?: boolean;
138
189
  }): Promise<PageImage[]>;
190
+ declare function rasterizePdfToPdf(pdfBytes: Uint8Array): Promise<Uint8Array>;
191
+ /**
192
+ * Prepares uploaded PDF bytes for the pdf-lib based assembly pipeline.
193
+ * Regular PDFs pass through untouched. Encrypted PDFs (typically
194
+ * permission-restricted documents that open without a password) are
195
+ * decrypted once here so every downstream `PDFDocument.load` — assembly,
196
+ * field extraction — sees a normal document. When structural decryption is
197
+ * impossible the document is rebuilt from rendered pages as a last resort.
198
+ *
199
+ * @throws {PdfPasswordRequiredError} when the PDF needs a real password
200
+ */
201
+ declare function normalizeUploadedPdfBytes(pdfBytes: Uint8Array): Promise<Uint8Array>;
139
202
  /**
140
203
  * Converts an image file to a PDF document with a single page
141
204
  *
@@ -175,4 +238,156 @@ declare function createPdfBlobUrl(pdfBytes: Uint8Array): string;
175
238
  */
176
239
  declare function downloadPdf(pdfBytes: Uint8Array, filename: string): void;
177
240
 
178
- export { type AssembleOptions, Button, type FileInfo, PageAssembler, type PageAssemblerHandle, type PageAssemblerProps, type PageAssemblerState, type PageImage, type PageInfo, createPdfBlobUrl, PageAssembler as default, downloadPdf, imageToPdf, pdfToImages };
241
+ declare class PdfPasswordRequiredError extends Error {
242
+ code: string;
243
+ recoverable: boolean;
244
+ userMessage: string;
245
+ constructor();
246
+ }
247
+ declare class UnsupportedPdfEncryptionError extends Error {
248
+ constructor(detail: string);
249
+ }
250
+ /**
251
+ * Decrypt an encrypted PDF that opens with an empty user password.
252
+ * Returns re-saved, fully decrypted bytes with `/Encrypt` removed.
253
+ *
254
+ * @throws {PdfPasswordRequiredError} when a non-empty password is required
255
+ * @throws {UnsupportedPdfEncryptionError} for non-standard security handlers
256
+ */
257
+ declare function decryptPdf(pdfBytes: Uint8Array): Promise<Uint8Array>;
258
+ /**
259
+ * Ingestion gate: returns the bytes untouched for regular PDFs, and a
260
+ * decrypted re-save for encrypted ones so every downstream `PDFDocument.load`
261
+ * (page assembly, field extraction) sees a normal document.
262
+ */
263
+ declare function normalizePdfEncryption(pdfBytes: Uint8Array): Promise<Uint8Array>;
264
+
265
+ /**
266
+ * PDF Field Extraction Utilities
267
+ * Extract form fields from PDFs with metadata support for preserving field properties
268
+ */
269
+
270
+ /**
271
+ * Extracted field information
272
+ */
273
+ interface ExtractedField {
274
+ name: string;
275
+ type: 'text' | 'signature' | 'initials' | 'date' | 'checkbox' | 'radio' | 'dropdown' | 'text_label';
276
+ page: number;
277
+ x: number;
278
+ y: number;
279
+ width: number;
280
+ height: number;
281
+ required: boolean;
282
+ label?: string;
283
+ placeholder?: string;
284
+ options?: string[];
285
+ fieldId?: string;
286
+ signer?: string;
287
+ }
288
+ /**
289
+ * SigniphiMetadata structure stored in PDF Info dictionary
290
+ */
291
+ interface SigniphiMetadata {
292
+ version: string;
293
+ fields: Record<string, {
294
+ fieldId?: string;
295
+ label?: string;
296
+ signer?: string;
297
+ placeholder?: string;
298
+ required?: boolean;
299
+ options?: string[];
300
+ acknowledgements?: Array<{
301
+ id: string;
302
+ title: string;
303
+ description: string;
304
+ }>;
305
+ }>;
306
+ fieldIdIndex?: Record<string, string>;
307
+ }
308
+ /**
309
+ * Extract SigniphiMetadata from a PDF document
310
+ */
311
+ declare function getSigniphiMetadata(pdfDoc: PDFDocument): SigniphiMetadata | null;
312
+ /**
313
+ * Extract form fields from a PDF document
314
+ * @param pdfBytes - PDF bytes
315
+ * @returns Array of extracted fields with all properties
316
+ */
317
+ declare function extractFieldsFromPdf(pdfBytes: Uint8Array): Promise<ExtractedField[]>;
318
+ /**
319
+ * Set SigniphiMetadata in a PDF document
320
+ */
321
+ declare function setSigniphiMetadata(pdfDoc: PDFDocument, metadata: SigniphiMetadata): void;
322
+
323
+ /**
324
+ * Add Form Fields to PDF
325
+ * Re-adds form fields to a PDF after page assembly operations
326
+ * This is the key to preserving form fields - don't try to preserve during copyPages,
327
+ * instead extract fields first, copy pages, then re-add fields with adjusted positions.
328
+ */
329
+ /**
330
+ * Form field type enum matching document-prepare
331
+ */
332
+ declare enum FormFieldType {
333
+ TEXT = "text",
334
+ SIGNATURE = "signature",
335
+ INITIALS = "initials",
336
+ DATE = "date",
337
+ CHECKBOX = "checkbox",
338
+ RADIO = "radio",
339
+ DROPDOWN = "dropdown",
340
+ TEXT_LABEL = "text_label"
341
+ }
342
+ /**
343
+ * Form field position
344
+ */
345
+ interface FormFieldPosition {
346
+ x: number;
347
+ y: number;
348
+ width: number;
349
+ height: number;
350
+ page: number;
351
+ }
352
+ /**
353
+ * Form field for adding to PDF
354
+ */
355
+ interface FormFieldForPdf {
356
+ name: string;
357
+ type: FormFieldType | string;
358
+ position: FormFieldPosition;
359
+ label?: string;
360
+ required?: boolean;
361
+ options?: string[];
362
+ defaultValue?: string;
363
+ placeholder?: string;
364
+ fontSize?: number;
365
+ multiline?: boolean;
366
+ maxLength?: number;
367
+ assignedSignerEmail?: string;
368
+ }
369
+ /**
370
+ * Add form fields to a PDF document
371
+ *
372
+ * @param pdfBytes - The PDF document bytes
373
+ * @param formFields - Array of form fields to add
374
+ * @param options - Options for field addition
375
+ * @returns Modified PDF bytes with form fields added
376
+ */
377
+ declare function addFormFieldsToPdf(pdfBytes: Uint8Array, formFields: FormFieldForPdf[], options?: {
378
+ removeExistingFields?: boolean;
379
+ drawLabels?: boolean;
380
+ }): Promise<Uint8Array>;
381
+ /**
382
+ * Map field positions after page assembly
383
+ * Updates field page numbers based on the final page arrangement
384
+ *
385
+ * @param fields - Original fields with positions
386
+ * @param pageMapping - Map of "originalFileId_originalPageIndex" -> newPageNumber
387
+ * @returns Fields with updated page positions
388
+ */
389
+ declare function mapFieldPositionsAfterAssembly<T extends {
390
+ position: FormFieldPosition;
391
+ }>(fields: T[], pageMapping: Map<string, number>): T[];
392
+
393
+ export { type AssembleOptions, Button, type ExtractedField, type FileExtractedFields, type FileInfo, type FormFieldForPdf, type FormFieldPosition, FormFieldType, PageAssembler, type PageAssemblerHandle, type PageAssemblerProps, type PageAssemblerState, type PageImage, type PageInfo, PdfPasswordRequiredError, type TrackedFormField, UnsupportedPdfEncryptionError, addFormFieldsToPdf, createPdfBlobUrl, decryptPdf, downloadPdf, extractFieldsFromPdf, getSigniphiMetadata, imageToPdf, mapFieldPositionsAfterAssembly, normalizePdfEncryption, normalizeUploadedPdfBytes, pdfToImages, rasterizePdfToPdf, setSigniphiMetadata };