@xberg-io/langchain-xberg 1.0.14 → 1.1.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.
package/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  A [LangChain.js](https://js.langchain.com) document loader for [Xberg](https://github.com/xberg-io/xberg).
13
13
  Point it at a file, a directory, or raw bytes and it returns LangChain `Document`s with the extracted
14
- text, tables, and rich metadata from 101 document formats — with optional OCR for scans and images.
14
+ text, tables, and rich metadata from 107 document formats — with optional OCR for scans and images.
15
15
 
16
16
  Extraction runs locally in-process through the `@xberg-io/xberg` native binding. No API key, no cloud
17
17
  call, no data leaves your machine.
@@ -69,13 +69,13 @@ const pages = await loader.load(); // metadata.page is 0-indexed
69
69
 
70
70
  ## Supported formats
71
71
 
72
- Xberg extracts from 101 formats including PDF, DOCX, PPTX, XLSX, HTML, EPUB, images, and more. See the
72
+ Xberg extracts from 107 formats including PDF, DOCX, PPTX, XLSX, HTML, EPUB, images, and more. See the
73
73
  [Xberg documentation](https://docs.xberg.io) for the full list and the extraction configuration
74
74
  reference.
75
75
 
76
76
  ## Part of Xberg.io
77
77
 
78
- - [Xberg](https://github.com/xberg-io/xberg) — document intelligence: text, tables, metadata from 101 formats with optional OCR.
78
+ - [Xberg](https://github.com/xberg-io/xberg) — document intelligence: text, tables, metadata from 107 formats with optional OCR.
79
79
  - [Xberg Enterprise](https://github.com/xberg-io/xberg-enterprise) — managed extraction API with SDKs, dashboards, and observability.
80
80
 
81
81
  ## License
package/dist/index.cjs CHANGED
@@ -162,8 +162,7 @@ function pagesToDocuments(document, source) {
162
162
  const baseMetadata = buildMetadata(document, source);
163
163
  const documents = [];
164
164
  for (const page of document.pages ?? []) {
165
- const metadata = { ...baseMetadata };
166
- metadata.page = page.pageNumber - 1;
165
+ const metadata = { ...baseMetadata, page: page.pageNumber - 1 };
167
166
  if (page.isBlank != null) {
168
167
  metadata.is_blank = page.isBlank;
169
168
  }
@@ -233,7 +232,7 @@ var XbergLoader = class extends import_base.BaseDocumentLoader {
233
232
  result = batch ? await (0, import_xberg.extractBatch)(inputs, this.config ?? null) : await (0, import_xberg.extract)(inputs[0], this.config ?? null);
234
233
  } catch (error) {
235
234
  const source = sources[0] ?? "input";
236
- throw new Error(`Failed to extract '${source}': ${errorMessage(error)}`);
235
+ throw new Error(`Failed to extract '${source}': ${errorMessage(error)}`, { cause: error });
237
236
  }
238
237
  return resultToDocuments(result, sources, {
239
238
  chunking: isChunkingEnabled(this.config),
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/loader.ts","../src/mapping.ts"],"sourcesContent":["export { XbergLoader, type XbergLoaderOptions } from \"./loader\";\n","import { stat } from \"node:fs/promises\";\nimport { BaseDocumentLoader } from \"@langchain/core/document_loaders/base\";\nimport type { Document } from \"@langchain/core/documents\";\nimport { extract, extractBatch, ExtractInputKind } from \"@xberg-io/xberg\";\nimport type { ExtractInput, ExtractionConfig } from \"@xberg-io/xberg\";\nimport fastGlob from \"fast-glob\";\nimport { isChunkingEnabled, isPerPageEnabled, resultToDocuments, type ResultEnvelope } from \"./mapping\";\n\nconst DEFAULT_GLOB = \"**/*\";\n\nexport interface XbergLoaderOptions {\n /** File path, list of file paths, or directory path to load. */\n filePath?: string | string[];\n /** Raw bytes to extract from. Mutually exclusive with `filePath`. */\n data?: Uint8Array;\n /** MIME type hint. Required when using `data`, optional for `filePath`. */\n mimeType?: string;\n /** Glob pattern for directory mode. Defaults to matching all files. */\n glob?: string;\n /** Xberg extraction configuration controlling output format, OCR, pages, chunking, etc. */\n config?: ExtractionConfig;\n}\n\n/**\n * Load documents using Xberg, supporting 101 file formats with true async extraction.\n *\n * By default each source becomes one Document. Enable `chunking` on the\n * `ExtractionConfig` to emit one Document per chunk, or `pages` for one Document\n * per page. Multiple paths (a list or a directory glob) are extracted with a single\n * `extractBatch` call so concurrency happens Rust-side.\n */\nexport class XbergLoader extends BaseDocumentLoader {\n private readonly filePath?: string | string[];\n private readonly data?: Uint8Array;\n private readonly mimeType?: string;\n private readonly glob?: string;\n private readonly config?: ExtractionConfig;\n\n constructor(options: XbergLoaderOptions) {\n super();\n const { filePath, data, mimeType, glob, config } = options;\n if (filePath === undefined && data === undefined) {\n throw new Error(\"Either 'filePath' or 'data' must be provided.\");\n }\n if (filePath !== undefined && data !== undefined) {\n throw new Error(\"Cannot specify both 'filePath' and 'data'. Use one or the other.\");\n }\n if (data !== undefined && mimeType === undefined) {\n throw new Error(\"'mimeType' is required when using 'data'.\");\n }\n\n this.filePath = filePath;\n this.data = data;\n this.mimeType = mimeType;\n this.glob = glob;\n this.config = config;\n }\n\n async load(): Promise<Document[]> {\n const { inputs, sources, batch } = await this.buildInputs();\n if (inputs.length === 0) {\n return [];\n }\n\n let result;\n try {\n result = batch ? await extractBatch(inputs, this.config ?? null) : await extract(inputs[0], this.config ?? null);\n } catch (error) {\n const source = sources[0] ?? \"input\";\n throw new Error(`Failed to extract '${source}': ${errorMessage(error)}`);\n }\n\n return resultToDocuments(result as unknown as ResultEnvelope, sources, {\n chunking: isChunkingEnabled(this.config),\n perPage: isPerPageEnabled(this.config),\n });\n }\n\n private async buildInputs(): Promise<{ inputs: ExtractInput[]; sources: string[]; batch: boolean }> {\n if (this.data !== undefined) {\n const source = `bytes://${this.mimeType}`;\n const input: ExtractInput = { kind: ExtractInputKind.Bytes, bytes: this.data, mimeType: this.mimeType };\n return { inputs: [input], sources: [source], batch: false };\n }\n\n const { paths, batch } = await this.resolvePaths();\n const inputs: ExtractInput[] = paths.map((path) => ({\n kind: ExtractInputKind.Uri,\n uri: path,\n mimeType: this.mimeType,\n }));\n return { inputs, sources: paths, batch };\n }\n\n private async resolvePaths(): Promise<{ paths: string[]; batch: boolean }> {\n const filePath = this.filePath;\n if (Array.isArray(filePath)) {\n return { paths: filePath, batch: true };\n }\n if (typeof filePath === \"string\") {\n if (await isDirectory(filePath)) {\n const pattern = this.glob ?? DEFAULT_GLOB;\n const matches = await fastGlob(pattern, { cwd: filePath, onlyFiles: true, absolute: true });\n return { paths: matches.sort(), batch: true };\n }\n return { paths: [filePath], batch: false };\n }\n return { paths: [], batch: false };\n }\n}\n\nasync function isDirectory(path: string): Promise<boolean> {\n try {\n const stats = await stat(path);\n return stats.isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { Document } from \"@langchain/core/documents\";\nimport type { DocumentCounts, ExtractionConfig, Keyword, Metadata, ProcessingWarning, Table } from \"@xberg-io/xberg\";\n\n// Metadata fields (from Xberg Metadata) that carry JSON-friendly scalar/list values,\n// mapped from the binding's camelCase keys to the snake_case output keys used by the\n// Python adapter. Opaque nested fields (pages, format, imagePreprocessing, jsonSchema,\n// error) are skipped because they are native objects, not plain data. ~keep\nconst METADATA_FIELDS: ReadonlyArray<readonly [string, keyof Metadata]> = [\n [\"title\", \"title\"],\n [\"subject\", \"subject\"],\n [\"authors\", \"authors\"],\n [\"keywords\", \"keywords\"],\n [\"language\", \"language\"],\n [\"created_at\", \"createdAt\"],\n [\"modified_at\", \"modifiedAt\"],\n [\"created_by\", \"createdBy\"],\n [\"modified_by\", \"modifiedBy\"],\n [\"category\", \"category\"],\n [\"tags\", \"tags\"],\n [\"document_version\", \"documentVersion\"],\n [\"abstract_text\", \"abstractText\"],\n [\"output_format\", \"outputFormat\"],\n [\"ocr_used\", \"ocrUsed\"],\n [\"extraction_duration_ms\", \"extractionDurationMs\"],\n];\n\nconst CONTENT_SEPARATOR = \"\\n\\n\";\n\nexport interface ChunkMetadataShape {\n chunkIndex: number;\n totalChunks: number;\n headingPath?: string[];\n tokenCount?: number;\n firstPage?: number;\n lastPage?: number;\n}\n\nexport interface ChunkShape {\n content: string;\n chunkType: unknown;\n metadata: ChunkMetadataShape;\n}\n\nexport interface PageShape {\n pageNumber: number;\n content: string;\n tables?: Table[];\n isBlank?: boolean;\n}\n\n// Structural view of a binding ExtractedDocument. The binding types its own fields\n// through unexported `Js*` aliases; this interface uses the clean exported types plus\n// local chunk/page shapes so the mapper is fully typed and testable without the addon. ~keep\nexport interface ExtractedDoc {\n content?: string;\n mimeType?: string;\n metadata?: Metadata;\n tables?: Table[];\n counts?: DocumentCounts;\n detectedLanguages?: string[];\n chunks?: ChunkShape[];\n pages?: PageShape[];\n extractedKeywords?: Keyword[];\n qualityScore?: number;\n processingWarnings?: ProcessingWarning[];\n}\n\nexport interface ResultEnvelope {\n errors?: Array<{ source: string; message: string }>;\n results?: ExtractedDoc[];\n}\n\nexport interface SplitOptions {\n chunking: boolean;\n perPage: boolean;\n}\n\nexport function isChunkingEnabled(config?: ExtractionConfig | null): boolean {\n return config?.chunking != null;\n}\n\nexport function isPerPageEnabled(config?: ExtractionConfig | null): boolean {\n return Boolean(config?.pages?.extractPages);\n}\n\nexport function flattenMetadata(metadata?: Metadata): Record<string, unknown> {\n const flat: Record<string, unknown> = {};\n if (!metadata) {\n return flat;\n }\n\n for (const [snakeKey, camelKey] of METADATA_FIELDS) {\n const value = metadata[camelKey];\n if (value != null) {\n flat[snakeKey] = value;\n }\n }\n\n const additional = metadata.additional;\n if (additional && Object.keys(additional).length > 0) {\n flat.additional = { ...additional };\n }\n\n return flat;\n}\n\nexport function assembleContent(content: string | undefined, tables: Table[] | undefined): string {\n const text = content ?? \"\";\n if (!tables || tables.length === 0) {\n return text;\n }\n const parts = tables.map((table) => table.markdown ?? \"\").filter((markdown) => markdown.length > 0);\n if (parts.length === 0) {\n return text;\n }\n return [text, ...parts].join(CONTENT_SEPARATOR);\n}\n\nexport function buildMetadata(document: ExtractedDoc, source: string): Record<string, unknown> {\n const metadata = flattenMetadata(document.metadata);\n\n metadata.mime_type = document.mimeType;\n if (document.qualityScore != null) {\n metadata.quality_score = document.qualityScore;\n }\n if (document.detectedLanguages && document.detectedLanguages.length > 0) {\n metadata.detected_languages = document.detectedLanguages;\n }\n if (document.counts != null) {\n metadata.page_count = document.counts.pages;\n }\n\n if (document.extractedKeywords && document.extractedKeywords.length > 0) {\n metadata.extracted_keywords = document.extractedKeywords.map((keyword) => ({\n text: keyword.text,\n score: keyword.score,\n algorithm: String(keyword.algorithm),\n }));\n }\n\n const tables = document.tables ?? [];\n metadata.table_count = tables.length;\n if (tables.length > 0) {\n metadata.tables = tables.map((table) => ({\n cells: table.cells,\n markdown: table.markdown,\n page_number: table.pageNumber,\n }));\n }\n\n if (document.processingWarnings && document.processingWarnings.length > 0) {\n metadata.processing_warnings = document.processingWarnings.map((warning) => ({\n source: warning.source,\n message: warning.message,\n }));\n }\n\n metadata.source = source;\n return metadata;\n}\n\nfunction chunksToDocuments(document: ExtractedDoc, source: string): Document[] {\n const baseMetadata = buildMetadata(document, source);\n const documents: Document[] = [];\n\n for (const chunk of document.chunks ?? []) {\n const metadata: Record<string, unknown> = { ...baseMetadata };\n const chunkMetadata = chunk.metadata;\n metadata.chunk_index = chunkMetadata.chunkIndex;\n metadata.total_chunks = chunkMetadata.totalChunks;\n metadata.chunk_type = String(chunk.chunkType);\n if (chunkMetadata.headingPath && chunkMetadata.headingPath.length > 0) {\n metadata.heading_path = [...chunkMetadata.headingPath];\n }\n if (chunkMetadata.tokenCount != null) {\n metadata.token_count = chunkMetadata.tokenCount;\n }\n if (chunkMetadata.firstPage != null) {\n // Xberg uses 1-indexed pages; LangChain convention is 0-indexed. ~keep\n metadata.page = chunkMetadata.firstPage - 1;\n metadata.first_page = chunkMetadata.firstPage;\n }\n if (chunkMetadata.lastPage != null) {\n metadata.last_page = chunkMetadata.lastPage;\n }\n documents.push(new Document({ pageContent: chunk.content, metadata }));\n }\n\n return documents;\n}\n\nfunction pagesToDocuments(document: ExtractedDoc, source: string): Document[] {\n const baseMetadata = buildMetadata(document, source);\n const documents: Document[] = [];\n\n for (const page of document.pages ?? []) {\n const metadata: Record<string, unknown> = { ...baseMetadata };\n // Xberg uses 1-indexed pages; LangChain convention is 0-indexed. ~keep\n metadata.page = page.pageNumber - 1;\n if (page.isBlank != null) {\n metadata.is_blank = page.isBlank;\n }\n const pageContent = assembleContent(page.content, page.tables);\n documents.push(new Document({ pageContent, metadata }));\n }\n\n return documents;\n}\n\nexport function documentToDocuments(document: ExtractedDoc, source: string, options: SplitOptions): Document[] {\n if (options.chunking && document.chunks && document.chunks.length > 0) {\n return chunksToDocuments(document, source);\n }\n if (options.perPage && document.pages && document.pages.length > 0) {\n return pagesToDocuments(document, source);\n }\n const metadata = buildMetadata(document, source);\n const pageContent = assembleContent(document.content, document.tables);\n return [new Document({ pageContent, metadata })];\n}\n\nexport function resultToDocuments(result: ResultEnvelope, sources: string[], options: SplitOptions): Document[] {\n if (result.errors && result.errors.length > 0) {\n const error = result.errors[0];\n throw new Error(`Failed to extract '${error.source}': ${error.message}`);\n }\n\n const documents: Document[] = [];\n const results = result.results ?? [];\n results.forEach((document, index) => {\n const source = sources[index] ?? (sources.length > 0 ? sources[sources.length - 1] : \"\");\n documents.push(...documentToDocuments(document, source, options));\n });\n return documents;\n}\n"],"mappings":"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","names":["fastGlob"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/loader.ts","../src/mapping.ts"],"sourcesContent":["export { XbergLoader, type XbergLoaderOptions } from \"./loader\";\n","import { stat } from \"node:fs/promises\";\nimport { BaseDocumentLoader } from \"@langchain/core/document_loaders/base\";\nimport type { Document } from \"@langchain/core/documents\";\nimport { extract, extractBatch, ExtractInputKind } from \"@xberg-io/xberg\";\nimport type { ExtractInput, ExtractionConfig } from \"@xberg-io/xberg\";\nimport fastGlob from \"fast-glob\";\nimport { isChunkingEnabled, isPerPageEnabled, resultToDocuments, type ResultEnvelope } from \"./mapping\";\n\nconst DEFAULT_GLOB = \"**/*\";\n\nexport interface XbergLoaderOptions {\n /** File path, list of file paths, or directory path to load. */\n filePath?: string | string[];\n /** Raw bytes to extract from. Mutually exclusive with `filePath`. */\n data?: Uint8Array;\n /** MIME type hint. Required when using `data`, optional for `filePath`. */\n mimeType?: string;\n /** Glob pattern for directory mode. Defaults to matching all files. */\n glob?: string;\n /** Xberg extraction configuration controlling output format, OCR, pages, chunking, etc. */\n config?: ExtractionConfig;\n}\n\n/**\n * Load documents using Xberg, supporting 107 file formats with true async extraction.\n *\n * By default each source becomes one Document. Enable `chunking` on the\n * `ExtractionConfig` to emit one Document per chunk, or `pages` for one Document\n * per page. Multiple paths (a list or a directory glob) are extracted with a single\n * `extractBatch` call so concurrency happens Rust-side.\n */\nexport class XbergLoader extends BaseDocumentLoader {\n private readonly filePath?: string | string[];\n private readonly data?: Uint8Array;\n private readonly mimeType?: string;\n private readonly glob?: string;\n private readonly config?: ExtractionConfig;\n\n constructor(options: XbergLoaderOptions) {\n super();\n const { filePath, data, mimeType, glob, config } = options;\n if (filePath === undefined && data === undefined) {\n throw new Error(\"Either 'filePath' or 'data' must be provided.\");\n }\n if (filePath !== undefined && data !== undefined) {\n throw new Error(\"Cannot specify both 'filePath' and 'data'. Use one or the other.\");\n }\n if (data !== undefined && mimeType === undefined) {\n throw new Error(\"'mimeType' is required when using 'data'.\");\n }\n\n this.filePath = filePath;\n this.data = data;\n this.mimeType = mimeType;\n this.glob = glob;\n this.config = config;\n }\n\n async load(): Promise<Document[]> {\n const { inputs, sources, batch } = await this.buildInputs();\n if (inputs.length === 0) {\n return [];\n }\n\n let result;\n try {\n result = batch ? await extractBatch(inputs, this.config ?? null) : await extract(inputs[0], this.config ?? null);\n } catch (error) {\n const source = sources[0] ?? \"input\";\n throw new Error(`Failed to extract '${source}': ${errorMessage(error)}`, { cause: error });\n }\n\n return resultToDocuments(result as unknown as ResultEnvelope, sources, {\n chunking: isChunkingEnabled(this.config),\n perPage: isPerPageEnabled(this.config),\n });\n }\n\n private async buildInputs(): Promise<{ inputs: ExtractInput[]; sources: string[]; batch: boolean }> {\n if (this.data !== undefined) {\n const source = `bytes://${this.mimeType}`;\n const input: ExtractInput = { kind: ExtractInputKind.Bytes, bytes: this.data, mimeType: this.mimeType };\n return { inputs: [input], sources: [source], batch: false };\n }\n\n const { paths, batch } = await this.resolvePaths();\n const inputs: ExtractInput[] = paths.map((path) => ({\n kind: ExtractInputKind.Uri,\n uri: path,\n mimeType: this.mimeType,\n }));\n return { inputs, sources: paths, batch };\n }\n\n private async resolvePaths(): Promise<{ paths: string[]; batch: boolean }> {\n const filePath = this.filePath;\n if (Array.isArray(filePath)) {\n return { paths: filePath, batch: true };\n }\n if (typeof filePath === \"string\") {\n if (await isDirectory(filePath)) {\n const pattern = this.glob ?? DEFAULT_GLOB;\n const matches = await fastGlob(pattern, { cwd: filePath, onlyFiles: true, absolute: true });\n return { paths: matches.sort(), batch: true };\n }\n return { paths: [filePath], batch: false };\n }\n return { paths: [], batch: false };\n }\n}\n\nasync function isDirectory(path: string): Promise<boolean> {\n try {\n const stats = await stat(path);\n return stats.isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { Document } from \"@langchain/core/documents\";\nimport type { DocumentCounts, ExtractionConfig, Keyword, Metadata, ProcessingWarning, Table } from \"@xberg-io/xberg\";\n\n// Metadata fields (from Xberg Metadata) that carry JSON-friendly scalar/list values,\n// mapped from the binding's camelCase keys to the snake_case output keys used by the\n// Python adapter. Opaque nested fields (pages, format, imagePreprocessing, jsonSchema,\n// error) are skipped because they are native objects, not plain data. ~keep\nconst METADATA_FIELDS: ReadonlyArray<readonly [string, keyof Metadata]> = [\n [\"title\", \"title\"],\n [\"subject\", \"subject\"],\n [\"authors\", \"authors\"],\n [\"keywords\", \"keywords\"],\n [\"language\", \"language\"],\n [\"created_at\", \"createdAt\"],\n [\"modified_at\", \"modifiedAt\"],\n [\"created_by\", \"createdBy\"],\n [\"modified_by\", \"modifiedBy\"],\n [\"category\", \"category\"],\n [\"tags\", \"tags\"],\n [\"document_version\", \"documentVersion\"],\n [\"abstract_text\", \"abstractText\"],\n [\"output_format\", \"outputFormat\"],\n [\"ocr_used\", \"ocrUsed\"],\n [\"extraction_duration_ms\", \"extractionDurationMs\"],\n];\n\nconst CONTENT_SEPARATOR = \"\\n\\n\";\n\nexport interface ChunkMetadataShape {\n chunkIndex: number;\n totalChunks: number;\n headingPath?: string[];\n tokenCount?: number;\n firstPage?: number;\n lastPage?: number;\n}\n\nexport interface ChunkShape {\n content: string;\n chunkType: unknown;\n metadata: ChunkMetadataShape;\n}\n\nexport interface PageShape {\n pageNumber: number;\n content: string;\n tables?: Table[];\n isBlank?: boolean;\n}\n\n// Structural view of a binding ExtractedDocument. The binding types its own fields\n// through unexported `Js*` aliases; this interface uses the clean exported types plus\n// local chunk/page shapes so the mapper is fully typed and testable without the addon. ~keep\nexport interface ExtractedDoc {\n content?: string;\n mimeType?: string;\n metadata?: Metadata;\n tables?: Table[];\n counts?: DocumentCounts;\n detectedLanguages?: string[];\n chunks?: ChunkShape[];\n pages?: PageShape[];\n extractedKeywords?: Keyword[];\n qualityScore?: number;\n processingWarnings?: ProcessingWarning[];\n}\n\nexport interface ResultEnvelope {\n errors?: Array<{ source: string; message: string }>;\n results?: ExtractedDoc[];\n}\n\nexport interface SplitOptions {\n chunking: boolean;\n perPage: boolean;\n}\n\nexport function isChunkingEnabled(config?: ExtractionConfig | null): boolean {\n return config?.chunking != null;\n}\n\nexport function isPerPageEnabled(config?: ExtractionConfig | null): boolean {\n return Boolean(config?.pages?.extractPages);\n}\n\nexport function flattenMetadata(metadata?: Metadata): Record<string, unknown> {\n const flat: Record<string, unknown> = {};\n if (!metadata) {\n return flat;\n }\n\n for (const [snakeKey, camelKey] of METADATA_FIELDS) {\n const value = metadata[camelKey];\n if (value != null) {\n flat[snakeKey] = value;\n }\n }\n\n const additional = metadata.additional;\n if (additional && Object.keys(additional).length > 0) {\n flat.additional = { ...additional };\n }\n\n return flat;\n}\n\nexport function assembleContent(content: string | undefined, tables: Table[] | undefined): string {\n const text = content ?? \"\";\n if (!tables || tables.length === 0) {\n return text;\n }\n const parts = tables.map((table) => table.markdown ?? \"\").filter((markdown) => markdown.length > 0);\n if (parts.length === 0) {\n return text;\n }\n return [text, ...parts].join(CONTENT_SEPARATOR);\n}\n\nexport function buildMetadata(document: ExtractedDoc, source: string): Record<string, unknown> {\n const metadata = flattenMetadata(document.metadata);\n\n metadata.mime_type = document.mimeType;\n if (document.qualityScore != null) {\n metadata.quality_score = document.qualityScore;\n }\n if (document.detectedLanguages && document.detectedLanguages.length > 0) {\n metadata.detected_languages = document.detectedLanguages;\n }\n if (document.counts != null) {\n metadata.page_count = document.counts.pages;\n }\n\n if (document.extractedKeywords && document.extractedKeywords.length > 0) {\n metadata.extracted_keywords = document.extractedKeywords.map((keyword) => ({\n text: keyword.text,\n score: keyword.score,\n algorithm: String(keyword.algorithm),\n }));\n }\n\n const tables = document.tables ?? [];\n metadata.table_count = tables.length;\n if (tables.length > 0) {\n metadata.tables = tables.map((table) => ({\n cells: table.cells,\n markdown: table.markdown,\n page_number: table.pageNumber,\n }));\n }\n\n if (document.processingWarnings && document.processingWarnings.length > 0) {\n metadata.processing_warnings = document.processingWarnings.map((warning) => ({\n source: warning.source,\n message: warning.message,\n }));\n }\n\n metadata.source = source;\n return metadata;\n}\n\nfunction chunksToDocuments(document: ExtractedDoc, source: string): Document[] {\n const baseMetadata = buildMetadata(document, source);\n const documents: Document[] = [];\n\n for (const chunk of document.chunks ?? []) {\n const metadata: Record<string, unknown> = { ...baseMetadata };\n const chunkMetadata = chunk.metadata;\n metadata.chunk_index = chunkMetadata.chunkIndex;\n metadata.total_chunks = chunkMetadata.totalChunks;\n metadata.chunk_type = String(chunk.chunkType);\n if (chunkMetadata.headingPath && chunkMetadata.headingPath.length > 0) {\n metadata.heading_path = [...chunkMetadata.headingPath];\n }\n if (chunkMetadata.tokenCount != null) {\n metadata.token_count = chunkMetadata.tokenCount;\n }\n if (chunkMetadata.firstPage != null) {\n // Xberg uses 1-indexed pages; LangChain convention is 0-indexed. ~keep\n metadata.page = chunkMetadata.firstPage - 1;\n metadata.first_page = chunkMetadata.firstPage;\n }\n if (chunkMetadata.lastPage != null) {\n metadata.last_page = chunkMetadata.lastPage;\n }\n documents.push(new Document({ pageContent: chunk.content, metadata }));\n }\n\n return documents;\n}\n\nfunction pagesToDocuments(document: ExtractedDoc, source: string): Document[] {\n const baseMetadata = buildMetadata(document, source);\n const documents: Document[] = [];\n\n for (const page of document.pages ?? []) {\n // Xberg uses 1-indexed pages; LangChain convention is 0-indexed. ~keep\n const metadata: Record<string, unknown> = { ...baseMetadata, page: page.pageNumber - 1 };\n if (page.isBlank != null) {\n metadata.is_blank = page.isBlank;\n }\n const pageContent = assembleContent(page.content, page.tables);\n documents.push(new Document({ pageContent, metadata }));\n }\n\n return documents;\n}\n\nexport function documentToDocuments(document: ExtractedDoc, source: string, options: SplitOptions): Document[] {\n if (options.chunking && document.chunks && document.chunks.length > 0) {\n return chunksToDocuments(document, source);\n }\n if (options.perPage && document.pages && document.pages.length > 0) {\n return pagesToDocuments(document, source);\n }\n const metadata = buildMetadata(document, source);\n const pageContent = assembleContent(document.content, document.tables);\n return [new Document({ pageContent, metadata })];\n}\n\nexport function resultToDocuments(result: ResultEnvelope, sources: string[], options: SplitOptions): Document[] {\n if (result.errors && result.errors.length > 0) {\n const error = result.errors[0];\n throw new Error(`Failed to extract '${error.source}': ${error.message}`);\n }\n\n const documents: Document[] = [];\n const results = result.results ?? [];\n results.forEach((document, index) => {\n const source = sources[index] ?? (sources.length > 0 ? sources[sources.length - 1] : \"\");\n documents.push(...documentToDocuments(document, source, options));\n });\n return documents;\n}\n"],"mappings":"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","names":["fastGlob"]}
package/dist/index.d.cts CHANGED
@@ -15,7 +15,7 @@ interface XbergLoaderOptions {
15
15
  config?: ExtractionConfig;
16
16
  }
17
17
  /**
18
- * Load documents using Xberg, supporting 101 file formats with true async extraction.
18
+ * Load documents using Xberg, supporting 107 file formats with true async extraction.
19
19
  *
20
20
  * By default each source becomes one Document. Enable `chunking` on the
21
21
  * `ExtractionConfig` to emit one Document per chunk, or `pages` for one Document
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@ interface XbergLoaderOptions {
15
15
  config?: ExtractionConfig;
16
16
  }
17
17
  /**
18
- * Load documents using Xberg, supporting 101 file formats with true async extraction.
18
+ * Load documents using Xberg, supporting 107 file formats with true async extraction.
19
19
  *
20
20
  * By default each source becomes one Document. Enable `chunking` on the
21
21
  * `ExtractionConfig` to emit one Document per chunk, or `pages` for one Document
package/dist/index.js CHANGED
@@ -126,8 +126,7 @@ function pagesToDocuments(document, source) {
126
126
  const baseMetadata = buildMetadata(document, source);
127
127
  const documents = [];
128
128
  for (const page of document.pages ?? []) {
129
- const metadata = { ...baseMetadata };
130
- metadata.page = page.pageNumber - 1;
129
+ const metadata = { ...baseMetadata, page: page.pageNumber - 1 };
131
130
  if (page.isBlank != null) {
132
131
  metadata.is_blank = page.isBlank;
133
132
  }
@@ -197,7 +196,7 @@ var XbergLoader = class extends BaseDocumentLoader {
197
196
  result = batch ? await extractBatch(inputs, this.config ?? null) : await extract(inputs[0], this.config ?? null);
198
197
  } catch (error) {
199
198
  const source = sources[0] ?? "input";
200
- throw new Error(`Failed to extract '${source}': ${errorMessage(error)}`);
199
+ throw new Error(`Failed to extract '${source}': ${errorMessage(error)}`, { cause: error });
201
200
  }
202
201
  return resultToDocuments(result, sources, {
203
202
  chunking: isChunkingEnabled(this.config),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/loader.ts","../src/mapping.ts"],"sourcesContent":["import { stat } from \"node:fs/promises\";\nimport { BaseDocumentLoader } from \"@langchain/core/document_loaders/base\";\nimport type { Document } from \"@langchain/core/documents\";\nimport { extract, extractBatch, ExtractInputKind } from \"@xberg-io/xberg\";\nimport type { ExtractInput, ExtractionConfig } from \"@xberg-io/xberg\";\nimport fastGlob from \"fast-glob\";\nimport { isChunkingEnabled, isPerPageEnabled, resultToDocuments, type ResultEnvelope } from \"./mapping\";\n\nconst DEFAULT_GLOB = \"**/*\";\n\nexport interface XbergLoaderOptions {\n /** File path, list of file paths, or directory path to load. */\n filePath?: string | string[];\n /** Raw bytes to extract from. Mutually exclusive with `filePath`. */\n data?: Uint8Array;\n /** MIME type hint. Required when using `data`, optional for `filePath`. */\n mimeType?: string;\n /** Glob pattern for directory mode. Defaults to matching all files. */\n glob?: string;\n /** Xberg extraction configuration controlling output format, OCR, pages, chunking, etc. */\n config?: ExtractionConfig;\n}\n\n/**\n * Load documents using Xberg, supporting 101 file formats with true async extraction.\n *\n * By default each source becomes one Document. Enable `chunking` on the\n * `ExtractionConfig` to emit one Document per chunk, or `pages` for one Document\n * per page. Multiple paths (a list or a directory glob) are extracted with a single\n * `extractBatch` call so concurrency happens Rust-side.\n */\nexport class XbergLoader extends BaseDocumentLoader {\n private readonly filePath?: string | string[];\n private readonly data?: Uint8Array;\n private readonly mimeType?: string;\n private readonly glob?: string;\n private readonly config?: ExtractionConfig;\n\n constructor(options: XbergLoaderOptions) {\n super();\n const { filePath, data, mimeType, glob, config } = options;\n if (filePath === undefined && data === undefined) {\n throw new Error(\"Either 'filePath' or 'data' must be provided.\");\n }\n if (filePath !== undefined && data !== undefined) {\n throw new Error(\"Cannot specify both 'filePath' and 'data'. Use one or the other.\");\n }\n if (data !== undefined && mimeType === undefined) {\n throw new Error(\"'mimeType' is required when using 'data'.\");\n }\n\n this.filePath = filePath;\n this.data = data;\n this.mimeType = mimeType;\n this.glob = glob;\n this.config = config;\n }\n\n async load(): Promise<Document[]> {\n const { inputs, sources, batch } = await this.buildInputs();\n if (inputs.length === 0) {\n return [];\n }\n\n let result;\n try {\n result = batch ? await extractBatch(inputs, this.config ?? null) : await extract(inputs[0], this.config ?? null);\n } catch (error) {\n const source = sources[0] ?? \"input\";\n throw new Error(`Failed to extract '${source}': ${errorMessage(error)}`);\n }\n\n return resultToDocuments(result as unknown as ResultEnvelope, sources, {\n chunking: isChunkingEnabled(this.config),\n perPage: isPerPageEnabled(this.config),\n });\n }\n\n private async buildInputs(): Promise<{ inputs: ExtractInput[]; sources: string[]; batch: boolean }> {\n if (this.data !== undefined) {\n const source = `bytes://${this.mimeType}`;\n const input: ExtractInput = { kind: ExtractInputKind.Bytes, bytes: this.data, mimeType: this.mimeType };\n return { inputs: [input], sources: [source], batch: false };\n }\n\n const { paths, batch } = await this.resolvePaths();\n const inputs: ExtractInput[] = paths.map((path) => ({\n kind: ExtractInputKind.Uri,\n uri: path,\n mimeType: this.mimeType,\n }));\n return { inputs, sources: paths, batch };\n }\n\n private async resolvePaths(): Promise<{ paths: string[]; batch: boolean }> {\n const filePath = this.filePath;\n if (Array.isArray(filePath)) {\n return { paths: filePath, batch: true };\n }\n if (typeof filePath === \"string\") {\n if (await isDirectory(filePath)) {\n const pattern = this.glob ?? DEFAULT_GLOB;\n const matches = await fastGlob(pattern, { cwd: filePath, onlyFiles: true, absolute: true });\n return { paths: matches.sort(), batch: true };\n }\n return { paths: [filePath], batch: false };\n }\n return { paths: [], batch: false };\n }\n}\n\nasync function isDirectory(path: string): Promise<boolean> {\n try {\n const stats = await stat(path);\n return stats.isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { Document } from \"@langchain/core/documents\";\nimport type { DocumentCounts, ExtractionConfig, Keyword, Metadata, ProcessingWarning, Table } from \"@xberg-io/xberg\";\n\n// Metadata fields (from Xberg Metadata) that carry JSON-friendly scalar/list values,\n// mapped from the binding's camelCase keys to the snake_case output keys used by the\n// Python adapter. Opaque nested fields (pages, format, imagePreprocessing, jsonSchema,\n// error) are skipped because they are native objects, not plain data. ~keep\nconst METADATA_FIELDS: ReadonlyArray<readonly [string, keyof Metadata]> = [\n [\"title\", \"title\"],\n [\"subject\", \"subject\"],\n [\"authors\", \"authors\"],\n [\"keywords\", \"keywords\"],\n [\"language\", \"language\"],\n [\"created_at\", \"createdAt\"],\n [\"modified_at\", \"modifiedAt\"],\n [\"created_by\", \"createdBy\"],\n [\"modified_by\", \"modifiedBy\"],\n [\"category\", \"category\"],\n [\"tags\", \"tags\"],\n [\"document_version\", \"documentVersion\"],\n [\"abstract_text\", \"abstractText\"],\n [\"output_format\", \"outputFormat\"],\n [\"ocr_used\", \"ocrUsed\"],\n [\"extraction_duration_ms\", \"extractionDurationMs\"],\n];\n\nconst CONTENT_SEPARATOR = \"\\n\\n\";\n\nexport interface ChunkMetadataShape {\n chunkIndex: number;\n totalChunks: number;\n headingPath?: string[];\n tokenCount?: number;\n firstPage?: number;\n lastPage?: number;\n}\n\nexport interface ChunkShape {\n content: string;\n chunkType: unknown;\n metadata: ChunkMetadataShape;\n}\n\nexport interface PageShape {\n pageNumber: number;\n content: string;\n tables?: Table[];\n isBlank?: boolean;\n}\n\n// Structural view of a binding ExtractedDocument. The binding types its own fields\n// through unexported `Js*` aliases; this interface uses the clean exported types plus\n// local chunk/page shapes so the mapper is fully typed and testable without the addon. ~keep\nexport interface ExtractedDoc {\n content?: string;\n mimeType?: string;\n metadata?: Metadata;\n tables?: Table[];\n counts?: DocumentCounts;\n detectedLanguages?: string[];\n chunks?: ChunkShape[];\n pages?: PageShape[];\n extractedKeywords?: Keyword[];\n qualityScore?: number;\n processingWarnings?: ProcessingWarning[];\n}\n\nexport interface ResultEnvelope {\n errors?: Array<{ source: string; message: string }>;\n results?: ExtractedDoc[];\n}\n\nexport interface SplitOptions {\n chunking: boolean;\n perPage: boolean;\n}\n\nexport function isChunkingEnabled(config?: ExtractionConfig | null): boolean {\n return config?.chunking != null;\n}\n\nexport function isPerPageEnabled(config?: ExtractionConfig | null): boolean {\n return Boolean(config?.pages?.extractPages);\n}\n\nexport function flattenMetadata(metadata?: Metadata): Record<string, unknown> {\n const flat: Record<string, unknown> = {};\n if (!metadata) {\n return flat;\n }\n\n for (const [snakeKey, camelKey] of METADATA_FIELDS) {\n const value = metadata[camelKey];\n if (value != null) {\n flat[snakeKey] = value;\n }\n }\n\n const additional = metadata.additional;\n if (additional && Object.keys(additional).length > 0) {\n flat.additional = { ...additional };\n }\n\n return flat;\n}\n\nexport function assembleContent(content: string | undefined, tables: Table[] | undefined): string {\n const text = content ?? \"\";\n if (!tables || tables.length === 0) {\n return text;\n }\n const parts = tables.map((table) => table.markdown ?? \"\").filter((markdown) => markdown.length > 0);\n if (parts.length === 0) {\n return text;\n }\n return [text, ...parts].join(CONTENT_SEPARATOR);\n}\n\nexport function buildMetadata(document: ExtractedDoc, source: string): Record<string, unknown> {\n const metadata = flattenMetadata(document.metadata);\n\n metadata.mime_type = document.mimeType;\n if (document.qualityScore != null) {\n metadata.quality_score = document.qualityScore;\n }\n if (document.detectedLanguages && document.detectedLanguages.length > 0) {\n metadata.detected_languages = document.detectedLanguages;\n }\n if (document.counts != null) {\n metadata.page_count = document.counts.pages;\n }\n\n if (document.extractedKeywords && document.extractedKeywords.length > 0) {\n metadata.extracted_keywords = document.extractedKeywords.map((keyword) => ({\n text: keyword.text,\n score: keyword.score,\n algorithm: String(keyword.algorithm),\n }));\n }\n\n const tables = document.tables ?? [];\n metadata.table_count = tables.length;\n if (tables.length > 0) {\n metadata.tables = tables.map((table) => ({\n cells: table.cells,\n markdown: table.markdown,\n page_number: table.pageNumber,\n }));\n }\n\n if (document.processingWarnings && document.processingWarnings.length > 0) {\n metadata.processing_warnings = document.processingWarnings.map((warning) => ({\n source: warning.source,\n message: warning.message,\n }));\n }\n\n metadata.source = source;\n return metadata;\n}\n\nfunction chunksToDocuments(document: ExtractedDoc, source: string): Document[] {\n const baseMetadata = buildMetadata(document, source);\n const documents: Document[] = [];\n\n for (const chunk of document.chunks ?? []) {\n const metadata: Record<string, unknown> = { ...baseMetadata };\n const chunkMetadata = chunk.metadata;\n metadata.chunk_index = chunkMetadata.chunkIndex;\n metadata.total_chunks = chunkMetadata.totalChunks;\n metadata.chunk_type = String(chunk.chunkType);\n if (chunkMetadata.headingPath && chunkMetadata.headingPath.length > 0) {\n metadata.heading_path = [...chunkMetadata.headingPath];\n }\n if (chunkMetadata.tokenCount != null) {\n metadata.token_count = chunkMetadata.tokenCount;\n }\n if (chunkMetadata.firstPage != null) {\n // Xberg uses 1-indexed pages; LangChain convention is 0-indexed. ~keep\n metadata.page = chunkMetadata.firstPage - 1;\n metadata.first_page = chunkMetadata.firstPage;\n }\n if (chunkMetadata.lastPage != null) {\n metadata.last_page = chunkMetadata.lastPage;\n }\n documents.push(new Document({ pageContent: chunk.content, metadata }));\n }\n\n return documents;\n}\n\nfunction pagesToDocuments(document: ExtractedDoc, source: string): Document[] {\n const baseMetadata = buildMetadata(document, source);\n const documents: Document[] = [];\n\n for (const page of document.pages ?? []) {\n const metadata: Record<string, unknown> = { ...baseMetadata };\n // Xberg uses 1-indexed pages; LangChain convention is 0-indexed. ~keep\n metadata.page = page.pageNumber - 1;\n if (page.isBlank != null) {\n metadata.is_blank = page.isBlank;\n }\n const pageContent = assembleContent(page.content, page.tables);\n documents.push(new Document({ pageContent, metadata }));\n }\n\n return documents;\n}\n\nexport function documentToDocuments(document: ExtractedDoc, source: string, options: SplitOptions): Document[] {\n if (options.chunking && document.chunks && document.chunks.length > 0) {\n return chunksToDocuments(document, source);\n }\n if (options.perPage && document.pages && document.pages.length > 0) {\n return pagesToDocuments(document, source);\n }\n const metadata = buildMetadata(document, source);\n const pageContent = assembleContent(document.content, document.tables);\n return [new Document({ pageContent, metadata })];\n}\n\nexport function resultToDocuments(result: ResultEnvelope, sources: string[], options: SplitOptions): Document[] {\n if (result.errors && result.errors.length > 0) {\n const error = result.errors[0];\n throw new Error(`Failed to extract '${error.source}': ${error.message}`);\n }\n\n const documents: Document[] = [];\n const results = result.results ?? [];\n results.forEach((document, index) => {\n const source = sources[index] ?? (sources.length > 0 ? sources[sources.length - 1] : \"\");\n documents.push(...documentToDocuments(document, source, options));\n });\n return documents;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/loader.ts","../src/mapping.ts"],"sourcesContent":["import { stat } from \"node:fs/promises\";\nimport { BaseDocumentLoader } from \"@langchain/core/document_loaders/base\";\nimport type { Document } from \"@langchain/core/documents\";\nimport { extract, extractBatch, ExtractInputKind } from \"@xberg-io/xberg\";\nimport type { ExtractInput, ExtractionConfig } from \"@xberg-io/xberg\";\nimport fastGlob from \"fast-glob\";\nimport { isChunkingEnabled, isPerPageEnabled, resultToDocuments, type ResultEnvelope } from \"./mapping\";\n\nconst DEFAULT_GLOB = \"**/*\";\n\nexport interface XbergLoaderOptions {\n /** File path, list of file paths, or directory path to load. */\n filePath?: string | string[];\n /** Raw bytes to extract from. Mutually exclusive with `filePath`. */\n data?: Uint8Array;\n /** MIME type hint. Required when using `data`, optional for `filePath`. */\n mimeType?: string;\n /** Glob pattern for directory mode. Defaults to matching all files. */\n glob?: string;\n /** Xberg extraction configuration controlling output format, OCR, pages, chunking, etc. */\n config?: ExtractionConfig;\n}\n\n/**\n * Load documents using Xberg, supporting 107 file formats with true async extraction.\n *\n * By default each source becomes one Document. Enable `chunking` on the\n * `ExtractionConfig` to emit one Document per chunk, or `pages` for one Document\n * per page. Multiple paths (a list or a directory glob) are extracted with a single\n * `extractBatch` call so concurrency happens Rust-side.\n */\nexport class XbergLoader extends BaseDocumentLoader {\n private readonly filePath?: string | string[];\n private readonly data?: Uint8Array;\n private readonly mimeType?: string;\n private readonly glob?: string;\n private readonly config?: ExtractionConfig;\n\n constructor(options: XbergLoaderOptions) {\n super();\n const { filePath, data, mimeType, glob, config } = options;\n if (filePath === undefined && data === undefined) {\n throw new Error(\"Either 'filePath' or 'data' must be provided.\");\n }\n if (filePath !== undefined && data !== undefined) {\n throw new Error(\"Cannot specify both 'filePath' and 'data'. Use one or the other.\");\n }\n if (data !== undefined && mimeType === undefined) {\n throw new Error(\"'mimeType' is required when using 'data'.\");\n }\n\n this.filePath = filePath;\n this.data = data;\n this.mimeType = mimeType;\n this.glob = glob;\n this.config = config;\n }\n\n async load(): Promise<Document[]> {\n const { inputs, sources, batch } = await this.buildInputs();\n if (inputs.length === 0) {\n return [];\n }\n\n let result;\n try {\n result = batch ? await extractBatch(inputs, this.config ?? null) : await extract(inputs[0], this.config ?? null);\n } catch (error) {\n const source = sources[0] ?? \"input\";\n throw new Error(`Failed to extract '${source}': ${errorMessage(error)}`, { cause: error });\n }\n\n return resultToDocuments(result as unknown as ResultEnvelope, sources, {\n chunking: isChunkingEnabled(this.config),\n perPage: isPerPageEnabled(this.config),\n });\n }\n\n private async buildInputs(): Promise<{ inputs: ExtractInput[]; sources: string[]; batch: boolean }> {\n if (this.data !== undefined) {\n const source = `bytes://${this.mimeType}`;\n const input: ExtractInput = { kind: ExtractInputKind.Bytes, bytes: this.data, mimeType: this.mimeType };\n return { inputs: [input], sources: [source], batch: false };\n }\n\n const { paths, batch } = await this.resolvePaths();\n const inputs: ExtractInput[] = paths.map((path) => ({\n kind: ExtractInputKind.Uri,\n uri: path,\n mimeType: this.mimeType,\n }));\n return { inputs, sources: paths, batch };\n }\n\n private async resolvePaths(): Promise<{ paths: string[]; batch: boolean }> {\n const filePath = this.filePath;\n if (Array.isArray(filePath)) {\n return { paths: filePath, batch: true };\n }\n if (typeof filePath === \"string\") {\n if (await isDirectory(filePath)) {\n const pattern = this.glob ?? DEFAULT_GLOB;\n const matches = await fastGlob(pattern, { cwd: filePath, onlyFiles: true, absolute: true });\n return { paths: matches.sort(), batch: true };\n }\n return { paths: [filePath], batch: false };\n }\n return { paths: [], batch: false };\n }\n}\n\nasync function isDirectory(path: string): Promise<boolean> {\n try {\n const stats = await stat(path);\n return stats.isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { Document } from \"@langchain/core/documents\";\nimport type { DocumentCounts, ExtractionConfig, Keyword, Metadata, ProcessingWarning, Table } from \"@xberg-io/xberg\";\n\n// Metadata fields (from Xberg Metadata) that carry JSON-friendly scalar/list values,\n// mapped from the binding's camelCase keys to the snake_case output keys used by the\n// Python adapter. Opaque nested fields (pages, format, imagePreprocessing, jsonSchema,\n// error) are skipped because they are native objects, not plain data. ~keep\nconst METADATA_FIELDS: ReadonlyArray<readonly [string, keyof Metadata]> = [\n [\"title\", \"title\"],\n [\"subject\", \"subject\"],\n [\"authors\", \"authors\"],\n [\"keywords\", \"keywords\"],\n [\"language\", \"language\"],\n [\"created_at\", \"createdAt\"],\n [\"modified_at\", \"modifiedAt\"],\n [\"created_by\", \"createdBy\"],\n [\"modified_by\", \"modifiedBy\"],\n [\"category\", \"category\"],\n [\"tags\", \"tags\"],\n [\"document_version\", \"documentVersion\"],\n [\"abstract_text\", \"abstractText\"],\n [\"output_format\", \"outputFormat\"],\n [\"ocr_used\", \"ocrUsed\"],\n [\"extraction_duration_ms\", \"extractionDurationMs\"],\n];\n\nconst CONTENT_SEPARATOR = \"\\n\\n\";\n\nexport interface ChunkMetadataShape {\n chunkIndex: number;\n totalChunks: number;\n headingPath?: string[];\n tokenCount?: number;\n firstPage?: number;\n lastPage?: number;\n}\n\nexport interface ChunkShape {\n content: string;\n chunkType: unknown;\n metadata: ChunkMetadataShape;\n}\n\nexport interface PageShape {\n pageNumber: number;\n content: string;\n tables?: Table[];\n isBlank?: boolean;\n}\n\n// Structural view of a binding ExtractedDocument. The binding types its own fields\n// through unexported `Js*` aliases; this interface uses the clean exported types plus\n// local chunk/page shapes so the mapper is fully typed and testable without the addon. ~keep\nexport interface ExtractedDoc {\n content?: string;\n mimeType?: string;\n metadata?: Metadata;\n tables?: Table[];\n counts?: DocumentCounts;\n detectedLanguages?: string[];\n chunks?: ChunkShape[];\n pages?: PageShape[];\n extractedKeywords?: Keyword[];\n qualityScore?: number;\n processingWarnings?: ProcessingWarning[];\n}\n\nexport interface ResultEnvelope {\n errors?: Array<{ source: string; message: string }>;\n results?: ExtractedDoc[];\n}\n\nexport interface SplitOptions {\n chunking: boolean;\n perPage: boolean;\n}\n\nexport function isChunkingEnabled(config?: ExtractionConfig | null): boolean {\n return config?.chunking != null;\n}\n\nexport function isPerPageEnabled(config?: ExtractionConfig | null): boolean {\n return Boolean(config?.pages?.extractPages);\n}\n\nexport function flattenMetadata(metadata?: Metadata): Record<string, unknown> {\n const flat: Record<string, unknown> = {};\n if (!metadata) {\n return flat;\n }\n\n for (const [snakeKey, camelKey] of METADATA_FIELDS) {\n const value = metadata[camelKey];\n if (value != null) {\n flat[snakeKey] = value;\n }\n }\n\n const additional = metadata.additional;\n if (additional && Object.keys(additional).length > 0) {\n flat.additional = { ...additional };\n }\n\n return flat;\n}\n\nexport function assembleContent(content: string | undefined, tables: Table[] | undefined): string {\n const text = content ?? \"\";\n if (!tables || tables.length === 0) {\n return text;\n }\n const parts = tables.map((table) => table.markdown ?? \"\").filter((markdown) => markdown.length > 0);\n if (parts.length === 0) {\n return text;\n }\n return [text, ...parts].join(CONTENT_SEPARATOR);\n}\n\nexport function buildMetadata(document: ExtractedDoc, source: string): Record<string, unknown> {\n const metadata = flattenMetadata(document.metadata);\n\n metadata.mime_type = document.mimeType;\n if (document.qualityScore != null) {\n metadata.quality_score = document.qualityScore;\n }\n if (document.detectedLanguages && document.detectedLanguages.length > 0) {\n metadata.detected_languages = document.detectedLanguages;\n }\n if (document.counts != null) {\n metadata.page_count = document.counts.pages;\n }\n\n if (document.extractedKeywords && document.extractedKeywords.length > 0) {\n metadata.extracted_keywords = document.extractedKeywords.map((keyword) => ({\n text: keyword.text,\n score: keyword.score,\n algorithm: String(keyword.algorithm),\n }));\n }\n\n const tables = document.tables ?? [];\n metadata.table_count = tables.length;\n if (tables.length > 0) {\n metadata.tables = tables.map((table) => ({\n cells: table.cells,\n markdown: table.markdown,\n page_number: table.pageNumber,\n }));\n }\n\n if (document.processingWarnings && document.processingWarnings.length > 0) {\n metadata.processing_warnings = document.processingWarnings.map((warning) => ({\n source: warning.source,\n message: warning.message,\n }));\n }\n\n metadata.source = source;\n return metadata;\n}\n\nfunction chunksToDocuments(document: ExtractedDoc, source: string): Document[] {\n const baseMetadata = buildMetadata(document, source);\n const documents: Document[] = [];\n\n for (const chunk of document.chunks ?? []) {\n const metadata: Record<string, unknown> = { ...baseMetadata };\n const chunkMetadata = chunk.metadata;\n metadata.chunk_index = chunkMetadata.chunkIndex;\n metadata.total_chunks = chunkMetadata.totalChunks;\n metadata.chunk_type = String(chunk.chunkType);\n if (chunkMetadata.headingPath && chunkMetadata.headingPath.length > 0) {\n metadata.heading_path = [...chunkMetadata.headingPath];\n }\n if (chunkMetadata.tokenCount != null) {\n metadata.token_count = chunkMetadata.tokenCount;\n }\n if (chunkMetadata.firstPage != null) {\n // Xberg uses 1-indexed pages; LangChain convention is 0-indexed. ~keep\n metadata.page = chunkMetadata.firstPage - 1;\n metadata.first_page = chunkMetadata.firstPage;\n }\n if (chunkMetadata.lastPage != null) {\n metadata.last_page = chunkMetadata.lastPage;\n }\n documents.push(new Document({ pageContent: chunk.content, metadata }));\n }\n\n return documents;\n}\n\nfunction pagesToDocuments(document: ExtractedDoc, source: string): Document[] {\n const baseMetadata = buildMetadata(document, source);\n const documents: Document[] = [];\n\n for (const page of document.pages ?? []) {\n // Xberg uses 1-indexed pages; LangChain convention is 0-indexed. ~keep\n const metadata: Record<string, unknown> = { ...baseMetadata, page: page.pageNumber - 1 };\n if (page.isBlank != null) {\n metadata.is_blank = page.isBlank;\n }\n const pageContent = assembleContent(page.content, page.tables);\n documents.push(new Document({ pageContent, metadata }));\n }\n\n return documents;\n}\n\nexport function documentToDocuments(document: ExtractedDoc, source: string, options: SplitOptions): Document[] {\n if (options.chunking && document.chunks && document.chunks.length > 0) {\n return chunksToDocuments(document, source);\n }\n if (options.perPage && document.pages && document.pages.length > 0) {\n return pagesToDocuments(document, source);\n }\n const metadata = buildMetadata(document, source);\n const pageContent = assembleContent(document.content, document.tables);\n return [new Document({ pageContent, metadata })];\n}\n\nexport function resultToDocuments(result: ResultEnvelope, sources: string[], options: SplitOptions): Document[] {\n if (result.errors && result.errors.length > 0) {\n const error = result.errors[0];\n throw new Error(`Failed to extract '${error.source}': ${error.message}`);\n }\n\n const documents: Document[] = [];\n const results = result.results ?? [];\n results.forEach((document, index) => {\n const source = sources[index] ?? (sources.length > 0 ? sources[sources.length - 1] : \"\");\n documents.push(...documentToDocuments(document, source, options));\n });\n return documents;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xberg-io/langchain-xberg",
3
- "version": "1.0.14",
4
- "description": "LangChain.js document loader for Xberg — extract text, tables, and metadata from 101 document formats with optional OCR.",
3
+ "version": "1.1.0",
4
+ "description": "LangChain.js document loader for Xberg — extract text, tables, and metadata from 107 document formats with optional OCR.",
5
5
  "keywords": [
6
6
  "langchain",
7
7
  "langchainjs",
@@ -38,16 +38,14 @@
38
38
  "require": "./dist/index.cjs"
39
39
  }
40
40
  },
41
- "files": [
42
- "dist"
43
- ],
41
+ "files": ["dist"],
44
42
  "scripts": {
45
43
  "build": "tsup",
46
44
  "typecheck": "tsc --noEmit",
47
45
  "test": "vitest run"
48
46
  },
49
47
  "dependencies": {
50
- "@xberg-io/xberg": "1.0.14",
48
+ "@xberg-io/xberg": "1.1.0",
51
49
  "fast-glob": "^3.3.2"
52
50
  },
53
51
  "peerDependencies": {