hazo_pdf 1.7.0 → 2.0.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.
Files changed (36) hide show
  1. package/SETUP_CHECKLIST.md +693 -0
  2. package/config/hazo_pdf_config.ini.sample +42 -0
  3. package/db_setup_postgres.sql +17 -0
  4. package/db_setup_sqlite.sql +13 -0
  5. package/dist/{chunk-NQ6KUJWG.js → chunk-7M53O3HF.js} +14 -4
  6. package/dist/chunk-7M53O3HF.js.map +1 -0
  7. package/dist/{chunk-4JJOUQ62.js → chunk-KDOQ3FIO.js} +176 -87
  8. package/dist/chunk-KDOQ3FIO.js.map +1 -0
  9. package/dist/{chunk-KHB3VZJQ.js → chunk-LFFCPDWC.js} +14 -3
  10. package/dist/chunk-LFFCPDWC.js.map +1 -0
  11. package/dist/{chunk-264BTVJT.js → chunk-TZJ5S57X.js} +18 -31
  12. package/dist/chunk-TZJ5S57X.js.map +1 -0
  13. package/dist/index.d.ts +9 -5
  14. package/dist/index.js +35 -16
  15. package/dist/index.js.map +1 -1
  16. package/dist/{pdf_saver-7FA4DAXI.js → pdf_saver-T6SEDYEE.js} +3 -3
  17. package/dist/{pdf_viewer-B6S5PJJB.js → pdf_viewer-TFCSUGWU.js} +3 -3
  18. package/dist/server/index.d.ts +5 -1
  19. package/dist/server/index.js +219 -81
  20. package/dist/server/index.js.map +1 -1
  21. package/dist/server/{text_search-2OZOVUIP.js → text_search-PVDG5Y6I.js} +14 -3
  22. package/dist/server/text_search-PVDG5Y6I.js.map +1 -0
  23. package/dist/styles/full.css +5821 -7156
  24. package/dist/styles/full.css.map +1 -1
  25. package/dist/styles/index.css +4844 -3929
  26. package/dist/styles/index.css.map +1 -1
  27. package/dist/{text_search-I2KZ7DTW.js → text_search-SO4ZOMIZ.js} +2 -2
  28. package/package.json +51 -36
  29. package/dist/chunk-264BTVJT.js.map +0 -1
  30. package/dist/chunk-4JJOUQ62.js.map +0 -1
  31. package/dist/chunk-KHB3VZJQ.js.map +0 -1
  32. package/dist/chunk-NQ6KUJWG.js.map +0 -1
  33. package/dist/server/text_search-2OZOVUIP.js.map +0 -1
  34. /package/dist/{pdf_saver-7FA4DAXI.js.map → pdf_saver-T6SEDYEE.js.map} +0 -0
  35. /package/dist/{pdf_viewer-B6S5PJJB.js.map → pdf_viewer-TFCSUGWU.js.map} +0 -0
  36. /package/dist/{text_search-I2KZ7DTW.js.map → text_search-SO4ZOMIZ.js.map} +0 -0
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  // src/utils/text_search.ts
4
+ import { HazoInternalError } from "hazo_core/errors";
4
5
  async function find_text_in_pdf(pdf, search_value, options) {
5
6
  try {
6
7
  const {
@@ -53,7 +54,12 @@ async function find_text_in_pdf(pdf, search_value, options) {
53
54
  }
54
55
  return null;
55
56
  } catch (err) {
56
- throw new Error(`Text search failed: ${err instanceof Error ? err.message : String(err)}`);
57
+ throw new HazoInternalError({
58
+ code: "HAZO_PDF_TEXT_SEARCH_FAILED",
59
+ pkg: "hazo_pdf",
60
+ message: `Text search failed: ${err instanceof Error ? err.message : String(err)}`,
61
+ cause: err instanceof Error ? err : new Error(String(err))
62
+ });
57
63
  }
58
64
  }
59
65
  async function find_all_text_in_pdf(pdf, search_value, options) {
@@ -109,7 +115,12 @@ async function find_all_text_in_pdf(pdf, search_value, options) {
109
115
  }
110
116
  return results;
111
117
  } catch (err) {
112
- throw new Error(`Text search failed: ${err instanceof Error ? err.message : String(err)}`);
118
+ throw new HazoInternalError({
119
+ code: "HAZO_PDF_TEXT_SEARCH_FAILED",
120
+ pkg: "hazo_pdf",
121
+ message: `Text search failed: ${err instanceof Error ? err.message : String(err)}`,
122
+ cause: err instanceof Error ? err : new Error(String(err))
123
+ });
113
124
  }
114
125
  }
115
126
  function extract_text_position(text_item, padding_x, padding_y, y_offset) {
@@ -154,4 +165,4 @@ export {
154
165
  find_text_in_pdf,
155
166
  find_all_text_in_pdf
156
167
  };
157
- //# sourceMappingURL=chunk-KHB3VZJQ.js.map
168
+ //# sourceMappingURL=chunk-LFFCPDWC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/text_search.ts"],"sourcesContent":["/**\n * Text search utility for finding text in PDF documents\n * Extracted from test app to be reusable across the library\n */\n\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\nimport { HazoInternalError } from 'hazo_core/errors';\n\n/**\n * Options for text search in PDF\n */\nexport interface TextSearchOptions {\n /** Page index to search (0-based) */\n page_index: number;\n\n /** Whether to normalize text by removing commas and spaces (default: true) */\n normalize?: boolean;\n\n /** Minimum length for partial matches (default: 3) */\n min_partial_match_length?: number;\n\n /** Horizontal padding around text (default: 2) */\n padding_x?: number;\n\n /** Vertical padding around text (default: 1) */\n padding_y?: number;\n\n /** Y-axis offset to adjust highlight position (default: -3) */\n y_offset?: number;\n}\n\n/**\n * Result of text search in PDF\n */\nexport interface TextSearchResult {\n /** X coordinate in PDF coordinate system */\n x: number;\n\n /** Y coordinate in PDF coordinate system */\n y: number;\n\n /** Width of the text box */\n width: number;\n\n /** Height of the text box */\n height: number;\n\n /** Type of match found */\n match_type: 'exact' | 'partial';\n\n /** The actual text that was matched */\n matched_text: string;\n}\n\n/**\n * Find text in a PDF document and return its position\n *\n * @param pdf - PDF document proxy from pdfjs\n * @param search_value - Text to search for\n * @param options - Search options\n * @returns Position and dimensions of the text, or null if not found\n */\nexport async function find_text_in_pdf(\n pdf: PDFDocumentProxy,\n search_value: string,\n options: TextSearchOptions\n): Promise<TextSearchResult | null> {\n try {\n const {\n page_index,\n normalize = true,\n min_partial_match_length = 3,\n padding_x = 2,\n padding_y = 1,\n y_offset = -3,\n } = options;\n\n // Get page (pdfjs uses 1-based indexing)\n const page = await pdf.getPage(page_index + 1);\n const text_content = await page.getTextContent();\n\n // Normalize search value if enabled\n const normalized_search = normalize\n ? search_value.toString().replace(/[,\\s]/g, '').toLowerCase()\n : search_value.toString().toLowerCase();\n\n // First pass: look for exact match\n for (const item of text_content.items) {\n if ('str' in item) {\n const text_item = item as { str: string; transform: number[]; width?: number; height?: number };\n const text = normalize\n ? text_item.str.replace(/[,\\s]/g, '').toLowerCase()\n : text_item.str.toLowerCase();\n\n // Only match if this text item equals our search value\n if (text === normalized_search) {\n const result = extract_text_position(text_item, padding_x, padding_y, y_offset);\n return {\n ...result,\n match_type: 'exact',\n matched_text: text_item.str,\n };\n }\n }\n }\n\n // Second pass: look for partial match (text item contains search value)\n if (normalized_search.length >= min_partial_match_length) {\n for (const item of text_content.items) {\n if ('str' in item) {\n const text_item = item as { str: string; transform: number[]; width?: number; height?: number };\n const text = normalize\n ? text_item.str.replace(/[,\\s]/g, '').toLowerCase()\n : text_item.str.toLowerCase();\n\n if (text.includes(normalized_search)) {\n const result = extract_partial_match_position(\n text_item, text, normalized_search, padding_x, padding_y, y_offset\n );\n return {\n ...result,\n match_type: 'partial',\n matched_text: text_item.str,\n };\n }\n }\n }\n }\n\n return null;\n } catch (err) {\n throw new HazoInternalError({\n code: 'HAZO_PDF_TEXT_SEARCH_FAILED',\n pkg: 'hazo_pdf',\n message: `Text search failed: ${err instanceof Error ? err.message : String(err)}`,\n cause: err instanceof Error ? err : new Error(String(err)),\n });\n }\n}\n\n/**\n * Find ALL occurrences of text in a PDF page and return their positions\n *\n * @param pdf - PDF document proxy from pdfjs\n * @param search_value - Text to search for\n * @param options - Search options\n * @returns Array of all matching positions (empty if none found)\n */\nexport async function find_all_text_in_pdf(\n pdf: PDFDocumentProxy,\n search_value: string,\n options: TextSearchOptions\n): Promise<TextSearchResult[]> {\n try {\n const {\n page_index,\n normalize = true,\n min_partial_match_length = 3,\n padding_x = 2,\n padding_y = 1,\n y_offset = -3,\n } = options;\n\n const page = await pdf.getPage(page_index + 1);\n const text_content = await page.getTextContent();\n\n const normalized_search = normalize\n ? search_value.toString().replace(/[,\\s]/g, '').toLowerCase()\n : search_value.toString().toLowerCase();\n\n const results: TextSearchResult[] = [];\n\n // Collect all exact matches\n for (const item of text_content.items) {\n if ('str' in item) {\n const text_item = item as { str: string; transform: number[]; width?: number; height?: number };\n const text = normalize\n ? text_item.str.replace(/[,\\s]/g, '').toLowerCase()\n : text_item.str.toLowerCase();\n\n if (text === normalized_search) {\n const result = extract_text_position(text_item, padding_x, padding_y, y_offset);\n results.push({\n ...result,\n match_type: 'exact',\n matched_text: text_item.str,\n });\n }\n }\n }\n\n // If no exact matches, collect partial matches\n if (results.length === 0 && normalized_search.length >= min_partial_match_length) {\n for (const item of text_content.items) {\n if ('str' in item) {\n const text_item = item as { str: string; transform: number[]; width?: number; height?: number };\n const text = normalize\n ? text_item.str.replace(/[,\\s]/g, '').toLowerCase()\n : text_item.str.toLowerCase();\n\n if (text.includes(normalized_search)) {\n const result = extract_partial_match_position(\n text_item, text, normalized_search, padding_x, padding_y, y_offset\n );\n results.push({\n ...result,\n match_type: 'partial',\n matched_text: text_item.str,\n });\n }\n }\n }\n }\n\n return results;\n } catch (err) {\n throw new HazoInternalError({\n code: 'HAZO_PDF_TEXT_SEARCH_FAILED',\n pkg: 'hazo_pdf',\n message: `Text search failed: ${err instanceof Error ? err.message : String(err)}`,\n cause: err instanceof Error ? err : new Error(String(err)),\n });\n }\n}\n\n/**\n * Extract position and dimensions from a PDF text item (full item bounds)\n * @private\n */\nfunction extract_text_position(\n text_item: { str: string; transform: number[]; width?: number; height?: number },\n padding_x: number,\n padding_y: number,\n y_offset: number\n): { x: number; y: number; width: number; height: number } {\n // Extract position from transform matrix [a, b, c, d, x, y]\n const x = text_item.transform[4];\n const y = text_item.transform[5];\n\n // Calculate dimensions\n const font_size = Math.abs(text_item.transform[0]) || 10;\n const base_width = text_item.width || (text_item.str.length * font_size * 0.55);\n const base_height = text_item.height || font_size;\n\n // Add padding for better visibility\n const width = base_width + (padding_x * 2);\n const height = base_height + (padding_y * 2);\n\n return {\n x: x - padding_x,\n y: y - padding_y + y_offset,\n width,\n height,\n };\n}\n\n/**\n * Extract position for a partial match — narrows the bounding box\n * to just the matched substring within the full text item.\n * @private\n */\nfunction extract_partial_match_position(\n text_item: { str: string; transform: number[]; width?: number; height?: number },\n normalized_text: string,\n normalized_search: string,\n padding_x: number,\n padding_y: number,\n y_offset: number\n): { x: number; y: number; width: number; height: number } {\n const x = text_item.transform[4];\n const y = text_item.transform[5];\n const font_size = Math.abs(text_item.transform[0]) || 10;\n const base_width = text_item.width || (text_item.str.length * font_size * 0.55);\n const base_height = text_item.height || font_size;\n\n // Calculate the proportion of the text item that the match covers\n const total_chars = normalized_text.length;\n const match_start = normalized_text.indexOf(normalized_search);\n const match_chars = normalized_search.length;\n\n if (total_chars === 0 || match_start < 0) {\n // Fallback to full item bounds\n return extract_text_position(text_item, padding_x, padding_y, y_offset);\n }\n\n // Estimate x offset and width based on character proportions\n const char_width = base_width / total_chars;\n const match_x_offset = match_start * char_width;\n const match_width = match_chars * char_width;\n\n return {\n x: x + match_x_offset - padding_x,\n y: y - padding_y + y_offset,\n width: match_width + (padding_x * 2),\n height: base_height + (padding_y * 2),\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,41 +1,28 @@
1
1
  "use client";
2
2
 
3
3
  // src/utils/logger.ts
4
+ import { createLogger } from "hazo_core";
4
5
  var console_logger = {
5
- info: (message, data) => {
6
- if (data) {
7
- console.log(`[hazo_pdf] ${message}`, data);
8
- } else {
9
- console.log(`[hazo_pdf] ${message}`);
10
- }
11
- },
12
- debug: (message, data) => {
13
- if (data) {
14
- console.debug(`[hazo_pdf] ${message}`, data);
15
- } else {
16
- console.debug(`[hazo_pdf] ${message}`);
17
- }
18
- },
19
- warn: (message, data) => {
20
- if (data) {
21
- console.warn(`[hazo_pdf] ${message}`, data);
22
- } else {
23
- console.warn(`[hazo_pdf] ${message}`);
24
- }
25
- },
26
- error: (message, data) => {
27
- if (data) {
28
- console.error(`[hazo_pdf] ${message}`, data);
29
- } else {
30
- console.error(`[hazo_pdf] ${message}`);
31
- }
32
- }
6
+ info: (message, data) => data ? console.log(`[hazo_pdf] ${message}`, data) : console.log(`[hazo_pdf] ${message}`),
7
+ debug: (message, data) => data ? console.debug(`[hazo_pdf] ${message}`, data) : console.debug(`[hazo_pdf] ${message}`),
8
+ warn: (message, data) => data ? console.warn(`[hazo_pdf] ${message}`, data) : console.warn(`[hazo_pdf] ${message}`),
9
+ error: (message, data) => data ? console.error(`[hazo_pdf] ${message}`, data) : console.error(`[hazo_pdf] ${message}`)
33
10
  };
34
- var current_logger = console_logger;
11
+ function build_default_logger() {
12
+ try {
13
+ return createLogger("hazo_pdf");
14
+ } catch {
15
+ return console_logger;
16
+ }
17
+ }
18
+ var current_logger = null;
35
19
  function set_logger(logger) {
36
- current_logger = logger || console_logger;
20
+ current_logger = logger ?? null;
37
21
  }
38
22
  function get_logger() {
23
+ if (!current_logger) {
24
+ current_logger = build_default_logger();
25
+ }
39
26
  return current_logger;
40
27
  }
41
28
 
@@ -197,4 +184,4 @@ export {
197
184
  get_logger,
198
185
  default_config
199
186
  };
200
- //# sourceMappingURL=chunk-264BTVJT.js.map
187
+ //# sourceMappingURL=chunk-TZJ5S57X.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/logger.ts","../src/config/default_config.ts"],"sourcesContent":["/**\n * Logger Utility for hazo_pdf\n *\n * Default behavior: delegates to hazo_core's createLogger('hazo_pdf'), which\n * auto-injects correlationId, env, and writes structured JSON via hazo_logs.\n * Consumers can still override with set_logger() — useful for browser-only\n * loggers or app-specific instrumentation.\n */\n\nimport { createLogger } from 'hazo_core';\n\n/**\n * Logger interface matching hazo_logs Logger type\n * This allows consumers to pass in their own logger instance\n */\nexport interface Logger {\n info: (message: string, data?: Record<string, unknown>) => void;\n debug: (message: string, data?: Record<string, unknown>) => void;\n warn: (message: string, data?: Record<string, unknown>) => void;\n error: (message: string, data?: Record<string, unknown>) => void;\n}\n\n/**\n * Console fallback used only when running in a browser where hazo_logs\n * isn't installed or fails to load. hazo_core falls back to JSON stderr in\n * Node and to console in browsers, so this is rarely exercised.\n */\nconst console_logger: Logger = {\n info: (message, data) => (data ? console.log(`[hazo_pdf] ${message}`, data) : console.log(`[hazo_pdf] ${message}`)),\n debug: (message, data) => (data ? console.debug(`[hazo_pdf] ${message}`, data) : console.debug(`[hazo_pdf] ${message}`)),\n warn: (message, data) => (data ? console.warn(`[hazo_pdf] ${message}`, data) : console.warn(`[hazo_pdf] ${message}`)),\n error: (message, data) => (data ? console.error(`[hazo_pdf] ${message}`, data) : console.error(`[hazo_pdf] ${message}`)),\n};\n\nfunction build_default_logger(): Logger {\n try {\n return createLogger('hazo_pdf') as unknown as Logger;\n } catch {\n return console_logger;\n }\n}\n\nlet current_logger: Logger | null = null;\n\n/**\n * Set the logger instance to use throughout hazo_pdf.\n * Pass `undefined` to reset to the hazo_core default.\n */\nexport function set_logger(logger: Logger | undefined): void {\n current_logger = logger ?? null;\n}\n\n/**\n * Get the current logger instance — defaults to hazo_core's createLogger\n * on first access if no consumer override has been set.\n */\nexport function get_logger(): Logger {\n if (!current_logger) {\n current_logger = build_default_logger();\n }\n return current_logger;\n}\n","/**\n * Default configuration values for hazo_pdf\n * All styling defaults organized by category\n */\n\nimport type { PdfViewerConfig } from '../types/config';\n\n/**\n * Default PDF Viewer Configuration\n * These values are used when no config file is provided or when values are missing\n */\nexport const default_config: PdfViewerConfig = {\n fonts: {\n freetext_font_family: 'Arial, sans-serif',\n freetext_font_size_min: 12,\n freetext_font_size_max: 24,\n freetext_font_size_default: 14,\n font_foreground_color: '#000000', // Black by default\n },\n\n highlight_annotation: {\n highlight_fill_color: '#FFFF00',\n highlight_fill_opacity: 0.3,\n highlight_border_color: '#FFD700',\n highlight_border_color_hover: '#FFD700',\n highlight_fill_opacity_hover: 0.4,\n },\n\n square_annotation: {\n square_fill_color: '#FF0000',\n square_fill_opacity: 0.2,\n square_border_color: '#FF0000',\n square_border_color_hover: '#CC0000',\n square_fill_opacity_hover: 0.3,\n },\n\n freetext_annotation: {\n freetext_text_color: '#000000',\n freetext_text_color_hover: '#000000',\n freetext_border_color: '#003366',\n freetext_border_width: 1,\n freetext_background_color: '#E6F3FF',\n freetext_background_opacity: 0.1,\n freetext_font_weight: 'normal',\n freetext_font_style: 'normal',\n freetext_text_decoration: 'none',\n freetext_padding_horizontal: 4,\n freetext_padding_vertical: 2,\n },\n\n page_styling: {\n page_border_color: '#999999',\n page_box_shadow: '0 2px 8px rgba(0, 0, 0, 0.3)',\n page_background_color: '#ffffff',\n },\n\n viewer: {\n viewer_background_color: '#2d2d2d',\n append_timestamp_to_text_edits: false,\n annotation_text_suffix_fixed_text: '',\n add_enclosing_brackets_to_suffixes: true,\n suffix_enclosing_brackets: '[]',\n suffix_text_position: 'below_multi_line',\n },\n\n context_menu: {\n context_menu_background_color: '#ffffff',\n context_menu_border_color: '#d1d5db',\n context_menu_item_hover_background: '#f3f4f6',\n context_menu_item_disabled_opacity: 0.5,\n right_click_custom_stamps: '', // Empty string means no custom stamps\n },\n\n dialog: {\n dialog_backdrop_opacity: 0.2,\n dialog_background_color: '#ffffff',\n dialog_border_color: '#d1d5db',\n dialog_button_submit_color: '#16a34a',\n dialog_button_submit_color_hover: '#15803d',\n dialog_button_cancel_color: '#6b7280',\n dialog_button_cancel_color_hover: '#4b5563',\n dialog_button_disabled_opacity: 0.4,\n },\n\n toolbar: {\n toolbar_background_color: '#f9fafb',\n toolbar_border_color: '#e5e7eb',\n toolbar_font_family: 'system-ui, -apple-system, sans-serif',\n toolbar_font_size: 14,\n toolbar_font_color: '#111827',\n toolbar_button_background_color: '#ffffff',\n toolbar_button_background_color_hover: '#f3f4f6',\n toolbar_button_text_color: '#374151',\n toolbar_button_active_background_color: '#3b82f6',\n toolbar_button_active_text_color: '#ffffff',\n toolbar_button_save_background_color: '#10b981',\n toolbar_button_save_background_color_hover: '#059669',\n toolbar_button_save_text_color: '#ffffff',\n toolbar_button_disabled_opacity: 0.5,\n toolbar_show_zoom_controls: true,\n toolbar_show_rotation_controls: true,\n toolbar_show_square_button: true,\n toolbar_show_undo_button: true,\n toolbar_show_redo_button: true,\n toolbar_show_save_button: true,\n toolbar_show_metadata_button: true,\n toolbar_show_annotate_button: true,\n toolbar_show_file_info_button: true,\n toolbar_show_extract_button: true,\n toolbar_show_download_button: false,\n toolbar_zoom_out_label: '−',\n toolbar_zoom_in_label: '+',\n toolbar_zoom_reset_label: 'Reset',\n toolbar_square_label: 'Square',\n toolbar_undo_label: 'Undo',\n toolbar_redo_label: 'Redo',\n toolbar_save_label: 'Save',\n toolbar_saving_label: 'Saving...',\n toolbar_metadata_label: 'Metadata',\n },\n\n file_manager: {\n file_manager_enabled: false,\n show_file_list: true,\n allow_delete: true,\n show_popout_button: true,\n file_list_height: 60,\n selected_color: '#3b82f6',\n file_list_background_color: '#f9fafb',\n file_list_border_color: '#e5e7eb',\n },\n\n file_upload: {\n upload_enabled: true,\n allowed_types: 'application/pdf,image/jpeg,image/png,image/gif,image/webp,text/plain,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel',\n max_file_size: 10485760, // 10MB\n max_files: 10,\n show_add_button: true,\n dropzone_border_color: '#d1d5db',\n dropzone_border_color_active: '#3b82f6',\n dropzone_background_color: '#f9fafb',\n direct_upload: false,\n },\n\n pdf_conversion: {\n conversion_enabled: true,\n page_size: 'letter',\n image_quality: 0.85,\n image_fit: 'fit',\n margin: 36,\n },\n\n auto_highlight: {\n auto_highlight_border_color: '#FF6B00',\n auto_highlight_background_color: '#FFF3E0',\n auto_highlight_background_opacity: 0.3,\n auto_highlight_border_width: 1,\n auto_highlight_normalize_text: true,\n auto_highlight_padding_x: 2,\n auto_highlight_padding_y: 1,\n auto_highlight_y_offset: -3,\n },\n\n file_button: {\n icon_size: 24,\n icon_color: '#6b7280',\n icon_color_hover: '#374151',\n icon_color_with_files: '#3b82f6',\n badge_background: '#3b82f6',\n badge_text_color: '#ffffff',\n },\n};\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -59,7 +59,11 @@ interface FileAccessProvider {
59
59
 
60
60
  /**
61
61
  * Logger Utility for hazo_pdf
62
- * Provides a unified logging interface that can use hazo_logs or fallback to console
62
+ *
63
+ * Default behavior: delegates to hazo_core's createLogger('hazo_pdf'), which
64
+ * auto-injects correlationId, env, and writes structured JSON via hazo_logs.
65
+ * Consumers can still override with set_logger() — useful for browser-only
66
+ * loggers or app-specific instrumentation.
63
67
  */
64
68
  /**
65
69
  * Logger interface matching hazo_logs Logger type
@@ -72,13 +76,13 @@ interface Logger {
72
76
  error: (message: string, data?: Record<string, unknown>) => void;
73
77
  }
74
78
  /**
75
- * Set the logger instance to use throughout hazo_pdf
76
- * @param logger - Logger instance (from hazo_logs or custom), or undefined to reset to console
79
+ * Set the logger instance to use throughout hazo_pdf.
80
+ * Pass `undefined` to reset to the hazo_core default.
77
81
  */
78
82
  declare function set_logger(logger: Logger | undefined): void;
79
83
  /**
80
- * Get the current logger instance
81
- * @returns Current logger (either hazo_logs instance or console fallback)
84
+ * Get the current logger instance — defaults to hazo_core's createLogger
85
+ * on first access if no consumer override has been set.
82
86
  */
83
87
  declare function get_logger(): Logger;
84
88
 
package/dist/index.js CHANGED
@@ -2,12 +2,12 @@
2
2
  import {
3
3
  find_all_text_in_pdf,
4
4
  find_text_in_pdf
5
- } from "./chunk-KHB3VZJQ.js";
5
+ } from "./chunk-LFFCPDWC.js";
6
6
  import {
7
7
  download_pdf,
8
8
  save_and_download_pdf,
9
9
  save_annotations_to_pdf
10
- } from "./chunk-NQ6KUJWG.js";
10
+ } from "./chunk-7M53O3HF.js";
11
11
  import {
12
12
  AnnotationOverlay,
13
13
  FileList,
@@ -22,7 +22,6 @@ import {
22
22
  build_config_from_ini,
23
23
  calculate_rectangle_coords,
24
24
  can_convert_to_pdf,
25
- cn,
26
25
  convert_excel_to_pdf,
27
26
  convert_image_to_pdf,
28
27
  convert_text_to_pdf,
@@ -43,19 +42,19 @@ import {
43
42
  parse_string,
44
43
  pdf_rect_to_rectangle,
45
44
  rectangle_to_pdf_rect
46
- } from "./chunk-4JJOUQ62.js";
45
+ } from "./chunk-KDOQ3FIO.js";
47
46
  import {
48
47
  default_config,
49
48
  get_logger,
50
49
  set_logger
51
- } from "./chunk-264BTVJT.js";
50
+ } from "./chunk-TZJ5S57X.js";
52
51
  import "./chunk-AOSHQP7D.js";
53
52
 
54
53
  // src/components/pdf_viewer/pdf_viewer_dialog.tsx
55
54
  import { Suspense, useCallback, useEffect, useRef, lazy } from "react";
56
55
  import { jsx } from "react/jsx-runtime";
57
56
  var PdfViewer2 = lazy(
58
- () => import("./pdf_viewer-B6S5PJJB.js").then((mod) => ({ default: mod.PdfViewer }))
57
+ () => import("./pdf_viewer-TFCSUGWU.js").then((mod) => ({ default: mod.PdfViewer }))
59
58
  );
60
59
  function PdfViewerDialog({
61
60
  open,
@@ -254,6 +253,8 @@ function export_annotations_to_xfdf(annotations, bookmarks = [], pdf_file_name =
254
253
 
255
254
  // src/components/split_viewer/pdf_split_viewer.tsx
256
255
  import { useState as useState3, useEffect as useEffect5, useCallback as useCallback3, useRef as useRef5 } from "react";
256
+ import { cn as cn5 } from "hazo_ui";
257
+ import { HazoExternalError, HazoValidationError } from "hazo_core/errors";
257
258
 
258
259
  // src/components/split_viewer/split_viewer_toolbar.tsx
259
260
  import {
@@ -268,6 +269,7 @@ import {
268
269
  Loader2,
269
270
  X
270
271
  } from "lucide-react";
272
+ import { cn } from "hazo_ui";
271
273
  import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
272
274
  var ToolbarButton = ({
273
275
  onClick,
@@ -493,6 +495,7 @@ function get_split_color(index) {
493
495
  // src/components/split_viewer/split_panel_card.tsx
494
496
  import { useState } from "react";
495
497
  import { ChevronRight, ChevronDown } from "lucide-react";
498
+ import { cn as cn2 } from "hazo_ui";
496
499
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
497
500
  var PageThumb = ({
498
501
  page_num,
@@ -593,7 +596,7 @@ var SplitPanelCard = ({
593
596
  return /* @__PURE__ */ jsxs2(
594
597
  "div",
595
598
  {
596
- className: cn("cls_split_panel_card", is_selected && "cls_split_panel_card_selected"),
599
+ className: cn2("cls_split_panel_card", is_selected && "cls_split_panel_card_selected"),
597
600
  style: {
598
601
  borderRadius: 6,
599
602
  marginBottom: 8,
@@ -973,6 +976,7 @@ import { useState as useState2, useRef as useRef4, useEffect as useEffect4, useC
973
976
 
974
977
  // src/components/split_viewer/split_page_renderer.tsx
975
978
  import { useRef as useRef3, useEffect as useEffect3, useMemo } from "react";
979
+ import { cn as cn3 } from "hazo_ui";
976
980
  import { jsx as jsx5 } from "react/jsx-runtime";
977
981
  var SplitPageRenderer = ({
978
982
  page,
@@ -1056,12 +1060,12 @@ var SplitPageRenderer = ({
1056
1060
  };
1057
1061
  }, [page, scale, page_number]);
1058
1062
  if (!page) {
1059
- return /* @__PURE__ */ jsx5("div", { className: cn("cls_split_page_loading", className), children: /* @__PURE__ */ jsx5("div", { className: "cls_split_page_spinner", children: "Loading page..." }) });
1063
+ return /* @__PURE__ */ jsx5("div", { className: cn3("cls_split_page_loading", className), children: /* @__PURE__ */ jsx5("div", { className: "cls_split_page_spinner", children: "Loading page..." }) });
1060
1064
  }
1061
1065
  return /* @__PURE__ */ jsx5(
1062
1066
  "div",
1063
1067
  {
1064
- className: cn("cls_split_page_container", className),
1068
+ className: cn3("cls_split_page_container", className),
1065
1069
  style: {
1066
1070
  position: "relative",
1067
1071
  width: viewport_dimensions.width,
@@ -1088,6 +1092,7 @@ var SplitPageRenderer = ({
1088
1092
  };
1089
1093
 
1090
1094
  // src/components/split_viewer/split_viewer_layout.tsx
1095
+ import { cn as cn4 } from "hazo_ui";
1091
1096
  import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1092
1097
  var SplitViewerLayout = ({
1093
1098
  pdf_document,
@@ -1172,7 +1177,7 @@ var SplitViewerLayout = ({
1172
1177
  return /* @__PURE__ */ jsx6(
1173
1178
  "div",
1174
1179
  {
1175
- className: cn("cls_split_viewer_layout cls_split_viewer_empty", className),
1180
+ className: cn4("cls_split_viewer_layout cls_split_viewer_empty", className),
1176
1181
  style: {
1177
1182
  display: "flex",
1178
1183
  alignItems: "center",
@@ -1190,7 +1195,7 @@ var SplitViewerLayout = ({
1190
1195
  return /* @__PURE__ */ jsx6(
1191
1196
  "div",
1192
1197
  {
1193
- className: cn("cls_split_viewer_layout cls_split_viewer_loading", className),
1198
+ className: cn4("cls_split_viewer_layout cls_split_viewer_loading", className),
1194
1199
  style: {
1195
1200
  display: "flex",
1196
1201
  alignItems: "center",
@@ -1207,7 +1212,7 @@ var SplitViewerLayout = ({
1207
1212
  return /* @__PURE__ */ jsxs4(
1208
1213
  "div",
1209
1214
  {
1210
- className: cn("cls_split_viewer_layout", className),
1215
+ className: cn4("cls_split_viewer_layout", className),
1211
1216
  style: {
1212
1217
  position: "relative",
1213
1218
  display: "flex",
@@ -1446,11 +1451,20 @@ var PdfSplitViewer = ({
1446
1451
  log.info("PdfSplitViewer: loading file via file_manager", { data: { file_id } });
1447
1452
  const result = await file_manager.downloadFile(file_id);
1448
1453
  if (!result.success || !result.data) {
1449
- throw new Error(result.error ?? "Failed to download file");
1454
+ throw new HazoExternalError({
1455
+ code: "HAZO_PDF_EXTERNAL_DOWNLOAD_FAILED",
1456
+ pkg: "hazo_pdf",
1457
+ message: result.error ?? "Failed to download file",
1458
+ httpStatus: 502
1459
+ });
1450
1460
  }
1451
1461
  source = result.data instanceof Uint8Array ? result.data : new Uint8Array(result.data);
1452
1462
  } else {
1453
- throw new Error("PdfSplitViewer: either url or file_manager + file_id must be provided");
1463
+ throw new HazoValidationError({
1464
+ code: "HAZO_PDF_VALIDATION_ERROR",
1465
+ pkg: "hazo_pdf",
1466
+ message: "PdfSplitViewer: either url or file_manager + file_id must be provided"
1467
+ });
1454
1468
  }
1455
1469
  const doc = await load_pdf_document(source);
1456
1470
  set_pdf_document(doc);
@@ -1586,7 +1600,12 @@ var PdfSplitViewer = ({
1586
1600
  });
1587
1601
  if (!response.ok) {
1588
1602
  const text = await response.text().catch(() => response.statusText);
1589
- throw new Error(`Split API error ${response.status}: ${text}`);
1603
+ throw new HazoExternalError({
1604
+ code: "HAZO_PDF_EXTERNAL_API_FAILED",
1605
+ pkg: "hazo_pdf",
1606
+ message: `Split API error ${response.status}: ${text}`,
1607
+ httpStatus: 502
1608
+ });
1590
1609
  }
1591
1610
  const result = await response.json();
1592
1611
  log.info("PdfSplitViewer: split confirmed via API", { data: { splits: result.splits.length } });
@@ -1644,7 +1663,7 @@ var PdfSplitViewer = ({
1644
1663
  const handle_add_split_toggle = useCallback3(() => {
1645
1664
  set_is_adding_split((prev) => !prev);
1646
1665
  }, []);
1647
- const root_class = cn("hazo-pdf-root cls_split_viewer", className);
1666
+ const root_class = cn5("hazo-pdf-root cls_split_viewer", className);
1648
1667
  if (pdf_loading) {
1649
1668
  return /* @__PURE__ */ jsx7(
1650
1669
  "div",