@xberg-io/langchain-xberg 1.0.1 → 1.0.8

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 90+ document formats — with optional OCR for scans and images.
14
+ text, tables, and rich metadata from 101 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 98+ formats including PDF, DOCX, PPTX, XLSX, HTML, EPUB, images, and more. See the
72
+ Xberg extracts from 101 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 98+ formats with optional OCR.
78
+ - [Xberg](https://github.com/xberg-io/xberg) — document intelligence: text, tables, metadata from 101 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
@@ -243,11 +243,15 @@ var XbergLoader = class extends import_base.BaseDocumentLoader {
243
243
  async buildInputs() {
244
244
  if (this.data !== void 0) {
245
245
  const source = `bytes://${this.mimeType}`;
246
- const input = { kind: "bytes", bytes: this.data, mimeType: this.mimeType };
246
+ const input = { kind: import_xberg.ExtractInputKind.Bytes, bytes: this.data, mimeType: this.mimeType };
247
247
  return { inputs: [input], sources: [source], batch: false };
248
248
  }
249
249
  const { paths, batch } = await this.resolvePaths();
250
- const inputs = paths.map((path) => ({ kind: "uri", uri: path, mimeType: this.mimeType }));
250
+ const inputs = paths.map((path) => ({
251
+ kind: import_xberg.ExtractInputKind.Uri,
252
+ uri: path,
253
+ mimeType: this.mimeType
254
+ }));
251
255
  return { inputs, sources: paths, batch };
252
256
  }
253
257
  async resolvePaths() {
@@ -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 } 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 90+ 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: \"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) => ({ kind: \"uri\", uri: path, mimeType: this.mimeType }));\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 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"]}
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 90+ file formats with true async extraction.
18
+ * Load documents using Xberg, supporting 101 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 90+ file formats with true async extraction.
18
+ * Load documents using Xberg, supporting 101 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
@@ -1,7 +1,7 @@
1
1
  // src/loader.ts
2
2
  import { stat } from "fs/promises";
3
3
  import { BaseDocumentLoader } from "@langchain/core/document_loaders/base";
4
- import { extract, extractBatch } from "@xberg-io/xberg";
4
+ import { extract, extractBatch, ExtractInputKind } from "@xberg-io/xberg";
5
5
  import fastGlob from "fast-glob";
6
6
 
7
7
  // src/mapping.ts
@@ -207,11 +207,15 @@ var XbergLoader = class extends BaseDocumentLoader {
207
207
  async buildInputs() {
208
208
  if (this.data !== void 0) {
209
209
  const source = `bytes://${this.mimeType}`;
210
- const input = { kind: "bytes", bytes: this.data, mimeType: this.mimeType };
210
+ const input = { kind: ExtractInputKind.Bytes, bytes: this.data, mimeType: this.mimeType };
211
211
  return { inputs: [input], sources: [source], batch: false };
212
212
  }
213
213
  const { paths, batch } = await this.resolvePaths();
214
- const inputs = paths.map((path) => ({ kind: "uri", uri: path, mimeType: this.mimeType }));
214
+ const inputs = paths.map((path) => ({
215
+ kind: ExtractInputKind.Uri,
216
+ uri: path,
217
+ mimeType: this.mimeType
218
+ }));
215
219
  return { inputs, sources: paths, batch };
216
220
  }
217
221
  async resolvePaths() {
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 } 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 90+ 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: \"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) => ({ kind: \"uri\", uri: path, mimeType: this.mimeType }));\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 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":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xberg-io/langchain-xberg",
3
- "version": "1.0.1",
4
- "description": "LangChain.js document loader for Xberg — extract text, tables, and metadata from 90+ document formats with optional OCR.",
3
+ "version": "1.0.8",
4
+ "description": "LangChain.js document loader for Xberg — extract text, tables, and metadata from 101 document formats with optional OCR.",
5
5
  "keywords": [
6
6
  "langchain",
7
7
  "langchainjs",
@@ -47,7 +47,7 @@
47
47
  "test": "vitest run"
48
48
  },
49
49
  "dependencies": {
50
- "@xberg-io/xberg": "1.0.1",
50
+ "@xberg-io/xberg": "1.0.8",
51
51
  "fast-glob": "^3.3.2"
52
52
  },
53
53
  "peerDependencies": {