@whaly/connector-sdk 0.3.7 → 0.3.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/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { AxiosInstance, AxiosRequestHeaders, AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios';
1
+ import { AxiosRequestHeaders, AxiosInstance, AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios';
2
2
  import Ajv, { ValidateFunction, ErrorObject } from 'ajv';
3
3
  import { Dayjs } from 'dayjs';
4
4
  import { WriteStream } from 'fs';
@@ -266,6 +266,7 @@ interface BaseConfig {
266
266
  schema: string;
267
267
  syncedAtColumnName?: string;
268
268
  syncedAtColumnUseLegacyStringType?: boolean;
269
+ outputDir?: string;
269
270
  }
270
271
 
271
272
  interface ColumnMappingStoreUnsafeToSafe {
@@ -349,7 +350,8 @@ declare class StreamState$1 {
349
350
  _hasBeenLoadedYetDuringThisSync: boolean;
350
351
  replicationMethod: ReplicationMethod;
351
352
  compiledValidateFn?: ValidateFunction;
352
- constructor(streamId: StreamId, dbSync: StreamWarehouseSyncService, replicationMethod: ReplicationMethod);
353
+ tmpDir: string;
354
+ constructor(streamId: StreamId, dbSync: StreamWarehouseSyncService, replicationMethod: ReplicationMethod, tmpDir?: string);
353
355
  setSchema(schema: FlattenedSchema): void;
354
356
  getSchema(): FlattenedSchema | undefined;
355
357
  setCompiledValidateFn(fn: ValidateFunction): void;
@@ -382,6 +384,8 @@ declare abstract class ITarget<C extends BaseConfig = BaseConfig> {
382
384
  schemaHooks: TargetSchemaHook[];
383
385
  syncTime: Dayjs;
384
386
  stateProvider: StateProvider;
387
+ readonly outputDir: string;
388
+ readonly tmpDir: string;
385
389
  batchedState: any;
386
390
  flushedState: any;
387
391
  renameColumnStore: RenameColumnStore;
@@ -408,6 +412,7 @@ declare abstract class ITarget<C extends BaseConfig = BaseConfig> {
408
412
  private loadAllStreamsInWarehouse;
409
413
  private emitState;
410
414
  private uploadStreamsToWarehouse;
415
+ private logSyncSummary;
411
416
  static uploadSingleStreamToWarehouse: (streamState: StreamState$1) => Promise<void>;
412
417
  }
413
418
 
@@ -693,7 +698,7 @@ declare const addWhalyFields: (record: any, batchDate: string, columnName?: stri
693
698
 
694
699
  declare const flattenSchema: <T>(streamId: StreamId, schema: T) => FlattenedSchema;
695
700
 
696
- declare const createTemporaryFileStream: (streamId: StreamId) => TempFile;
701
+ declare const createTemporaryFileStream: (streamId: StreamId, tmpDir?: string) => TempFile;
697
702
  declare function safePath(path: string): string;
698
703
 
699
704
  /**
@@ -1356,6 +1361,199 @@ declare class ImageTransform {
1356
1361
  static toWebp(inputPath: string, options: WebpTransformOptions): Promise<string>;
1357
1362
  }
1358
1363
 
1364
+ /**
1365
+ * Metadata-only representation of a document in the source system.
1366
+ * Yielded by DocumentStream.listDocuments().
1367
+ */
1368
+ interface DocumentEntry {
1369
+ /** Unique ID in source system — the reconciliation key. */
1370
+ externalId: string;
1371
+ /** Display name in Whaly. */
1372
+ fileName: string;
1373
+ /** Original filename in source system. */
1374
+ originalFileName: string;
1375
+ /** Original file path in source system. */
1376
+ originalFilePath?: string;
1377
+ /** Document author name. */
1378
+ originalAuthor?: string;
1379
+ /** File extension without dot (e.g. "pdf", "xlsx"). */
1380
+ extension: string;
1381
+ /** Source last-modified timestamp. Used for incremental skip. */
1382
+ lastModified?: Date;
1383
+ /** ISO date string: when the document becomes valid. */
1384
+ validFrom?: string;
1385
+ /** ISO date string: when the document expires. */
1386
+ validUntil?: string;
1387
+ /** Custom key-value metadata. */
1388
+ metadata?: Record<string, string>;
1389
+ }
1390
+ /**
1391
+ * A document as it exists in Whaly (returned by the Document API).
1392
+ */
1393
+ interface WhalyDocument {
1394
+ id: string;
1395
+ file_name: string;
1396
+ external_id: string;
1397
+ original_file_name: string;
1398
+ original_file_path: string;
1399
+ original_author: string;
1400
+ extension: string;
1401
+ file_path: string;
1402
+ valid_from: string;
1403
+ valid_until: string;
1404
+ size_kb: number;
1405
+ storage: string;
1406
+ metadata: Record<string, string> | null;
1407
+ }
1408
+ /** Paginated response from the Whaly Document API. */
1409
+ interface WhalyPaginatedResponse<T> {
1410
+ data: T[];
1411
+ paging: {
1412
+ next?: {
1413
+ after: string;
1414
+ };
1415
+ };
1416
+ }
1417
+ type DocumentStatus = "created" | "updated" | "reuploaded" | "deleted" | "skipped" | "error";
1418
+ interface DocumentManifestEntry {
1419
+ externalId: string;
1420
+ fileName: string;
1421
+ status: DocumentStatus;
1422
+ error?: string;
1423
+ }
1424
+ interface DocumentStreamManifest {
1425
+ streamId: string;
1426
+ syncedAt: string;
1427
+ documents: DocumentManifestEntry[];
1428
+ summary: DocumentSummary;
1429
+ }
1430
+ interface DocumentSummary {
1431
+ total: number;
1432
+ created: number;
1433
+ updated: number;
1434
+ reuploaded: number;
1435
+ deleted: number;
1436
+ skipped: number;
1437
+ errors: number;
1438
+ }
1439
+ interface DocumentManifest {
1440
+ syncedAt: string;
1441
+ streams: DocumentStreamManifest[];
1442
+ summary: DocumentSummary;
1443
+ }
1444
+ declare function emptyDocumentSummary(): DocumentSummary;
1445
+ declare function addDocumentSummaries(a: DocumentSummary, b: DocumentSummary): DocumentSummary;
1446
+
1447
+ declare class DocumentDownloadSkipError extends Error {
1448
+ constructor(message: string);
1449
+ }
1450
+
1451
+ declare abstract class DocumentStream<C> {
1452
+ readonly streamId: string;
1453
+ readonly config: C;
1454
+ constructor(streamId: string, config: C);
1455
+ /** Yield all documents from the source (metadata only, no file download). */
1456
+ abstract listDocuments(): AsyncIterable<DocumentEntry>;
1457
+ /** Download a single document file to `destPath` on local disk. */
1458
+ abstract downloadDocument(entry: DocumentEntry, destPath: string): Promise<void>;
1459
+ /**
1460
+ * Escape hatch: should the file be re-uploaded?
1461
+ * Default: true (conservative — always re-upload).
1462
+ * Override to compare timestamps or hashes for incremental skip.
1463
+ */
1464
+ shouldReupload(_sourceEntry: DocumentEntry, _existingDoc: WhalyDocument): boolean;
1465
+ /**
1466
+ * Escape hatch: does the metadata need updating?
1467
+ * Default: compares fileName, validFrom, validUntil, originalAuthor, metadata.
1468
+ */
1469
+ shouldUpdateMetadata(sourceEntry: DocumentEntry, existingDoc: WhalyDocument): boolean;
1470
+ /**
1471
+ * Escape hatch: should this orphaned document be deleted?
1472
+ * Default: true (delete all documents no longer in source).
1473
+ */
1474
+ shouldDelete(_orphanedDoc: WhalyDocument): boolean;
1475
+ }
1476
+
1477
+ interface WhalyDocumentServiceConfig {
1478
+ /** e.g. "https://org.my.whaly.io" */
1479
+ apiEndpoint?: string;
1480
+ /** e.g. "sk:xxxx" */
1481
+ serviceAccountKey?: string;
1482
+ /** Object storage ID for file uploads. */
1483
+ objectStorageId: string;
1484
+ }
1485
+ interface WhalyUploadResult {
1486
+ storage: string;
1487
+ filePath: string;
1488
+ sizeKb: number;
1489
+ }
1490
+ declare class WhalyDocumentService {
1491
+ private axiosClient;
1492
+ readonly objectStorageId: string;
1493
+ private gcsBucket;
1494
+ constructor(config: WhalyDocumentServiceConfig);
1495
+ /** Fetch all documents from the API, handling cursor-based pagination. */
1496
+ listAllDocuments(): Promise<WhalyDocument[]>;
1497
+ /** Upload a file to object storage. Returns storage path and size. */
1498
+ uploadFile(destinationPath: string, localFilePath: string, fileName: string): Promise<WhalyUploadResult>;
1499
+ private uploadFileViaGCS;
1500
+ private uploadFileViaAPI;
1501
+ /** Create a new document record. */
1502
+ createDocument(payload: Omit<WhalyDocument, "id">): Promise<WhalyDocument>;
1503
+ /** Update an existing document record. */
1504
+ updateDocument(id: string, payload: Partial<WhalyDocument>): Promise<WhalyDocument>;
1505
+ /** Delete a document record. */
1506
+ deleteDocument(id: string): Promise<void>;
1507
+ }
1508
+
1509
+ declare class WhalyDocumentTarget {
1510
+ readonly config: WhalyDocumentServiceConfig;
1511
+ private service;
1512
+ constructor(config: WhalyDocumentServiceConfig);
1513
+ /** Fetch all existing documents from Whaly. */
1514
+ listExistingDocuments(): Promise<WhalyDocument[]>;
1515
+ /**
1516
+ * Create a new document: upload file to object storage, then create the document record.
1517
+ * @param streamId Used to namespace the file path in object storage.
1518
+ */
1519
+ createDocument(streamId: string, entry: DocumentEntry, localFilePath: string): Promise<void>;
1520
+ /**
1521
+ * Re-upload the file and update the document record.
1522
+ */
1523
+ reuploadDocument(streamId: string, docId: string, entry: DocumentEntry, localFilePath: string): Promise<void>;
1524
+ /** Update only the metadata fields (no file re-upload). */
1525
+ updateDocumentMetadata(docId: string, entry: DocumentEntry, existingDoc: WhalyDocument): Promise<void>;
1526
+ /** Delete a document record. */
1527
+ deleteDocument(docId: string, externalId: string): Promise<void>;
1528
+ }
1529
+
1530
+ declare abstract class DocumentTap<C> {
1531
+ readonly config: C;
1532
+ readonly outputDir: string;
1533
+ readonly concurrency: number;
1534
+ /**
1535
+ * The single stream for this tap.
1536
+ * Set during init(). A DocumentTap supports exactly one stream to avoid
1537
+ * cross-stream deletion issues (existing docs cannot be filtered by stream).
1538
+ */
1539
+ stream: DocumentStream<unknown>;
1540
+ target: WhalyDocumentTarget;
1541
+ constructor(config: C, outputDir?: string, concurrency?: number);
1542
+ /**
1543
+ * Initialize the tap: set `this.stream` to the single DocumentStream.
1544
+ * Called once at the start of sync().
1545
+ */
1546
+ abstract init(): Promise<void>;
1547
+ sync(): Promise<DocumentManifest>;
1548
+ private collectSourceEntries;
1549
+ private computeDiff;
1550
+ private executeCreate;
1551
+ private executeReupload;
1552
+ private executeMetadataUpdate;
1553
+ private executeDelete;
1554
+ private computeSummary;
1555
+ }
1556
+
1359
1557
  interface BigQueryConfig extends BaseConfig {
1360
1558
  schema: string;
1361
1559
  project_id: string;
@@ -1437,4 +1635,4 @@ declare class GCSStateProvider implements StateProvider {
1437
1635
  writeState(state: string): Promise<void>;
1438
1636
  }
1439
1637
 
1440
- export { ALL_STREAM_ID_KEYWORD, API_CALLS_METRIC_NAME, type AssetEntry, type AssetManifest, type AssetManifestEntry, type AssetReplicationMode, AssetStream, AssetTap, AssetTarget, Authenticator, BATCH_INTERVAL_MS, type BaseConfig, type BigQueryConfig, BigQueryTarget, type BigqueryLocation, type Bookmark, type Bookmarks, CdnAssetTarget, type CdnAssetTargetConfig, type CdnFileMetadata, CdnService, type CdnServiceConfig, type CdnUploadResult, CloudStorageService, type CloudStorageServiceOptions, type ColumnMappingStoreUnsafeToSafe, CounterMetric, CsvExtractionConfigBuilder, type CsvFieldsArrayConfig, type CsvFieldsConfig, type CsvFieldsDictConfig, type CsvFileConfig, type CsvStreamConfig, DEFAULT_MAX_CONCURRENT_STREAMS, DEFAULT_SYNCED_AT_COLUMN, type DownloadFilesOptions, EXECUTION_TIME_METRIC_NAME, type ErrorType, type ExcelCustomExtractorConfig, type ExcelDerivedField, type ExcelExtractionBaseConfig, type ExcelExtractionConfig, ExcelExtractionConfigBuilder, type ExcelFieldMapping, type ExcelFieldSpec, type ExcelSingleSheetExtractionConfig, type ExcelSourceColumn, type ExcelStreamConfig, type FieldType, FileFormat, FilePatterns, FileStream, type FileStreamConfig, type FileStreamEntry, FileTap, type FileTapConfig, type FlattenedSchema, GCSStateProvider, type GetConfig, type HTTPHeaders, type HTTPMethod, ITarget, ImageTransform, type InputTapState, type InternalTableField, type JSONSchemaFieldDefinition, type ListFilesOptions, MIME_TYPES, type Message, type MessageType, type MetricConfiguration, MissingFieldInSchemaError, MissingSchemaError, type PostConfig, type ProcessedAsset, type ProgressMarkers, type PropertiesMetadata, RESTStream, ROWS_SYNCED_METRIC_NAME, RecordMessage, RenameColumnStore, ReplicationMethod, ReplicationMethodMessage, type SafeColumnNameConverterFn, type Schema, SchemaMessage, SchemaValidationError, SftpService, type State, type StateHolder, StateMessage, type StateProvider, StateService, Stream, type StreamId, type StreamManifest, type StreamState, StreamWarehouseSyncService, type StreamWithTempFile, type SyncOptions, Tap, type TapState, type TargetSchemaHook, type TargetSchemaHookInput, type TempFile, type URLParams, VariableExtractors, type WarehouseTableField, type WebpTransformOptions, type WriteGeneratorToCsvOptions, _greaterThan, addWhalyFields, checkCsvHeaderRow, collectPaginated, countCsvLines, createCellReference, createCsvStreamConfig, createExcelGenerator, createExcelStreamConfig, createTemporaryFileStream, csvFieldsToJsonSchema, downloadFiles, excelColumnToIndex, excelFieldsToJsonSchema, excelRowToIndex, extractExcelRows, extractPrimaryKeysFromCsvConfig, extractPrimaryKeysFromExcelFields, extractStateForStream, fieldTypeToJsonSchema, finalizeStateProgressMarkers, findAllMatchingConfigs, flattenSchema, getAllMetrics, getApiEndpoint, getAxiosInstance, getCdnId, getCounterMetric, getCounterMetrics, getDownloadFileApiCall, getDryRunLimit, getJSONApiCall, getJSONApiCallWithFullResponse, getMimeType, getRawJSONApiCall, getServiceAccountKey, gracefulExit, haltAndCatchFire, incrementStreamState, indexToExcelColumn, indexToExcelRow, isDryRun, listFilesRecursively, loadJson, loadSchema, logger, optionalEnv, parseCellReference, postFormDataApiCall, postJSONApiCall, postUrlEncodedApiCall, printMemoryFootprint, processFileStreams, processFromAsyncIterable, removeParasiteProperties, requireEnv, rowGeneratorFromCsv, runWithConcurrency, safePath, unzip, validateExcelConfig, writeDataToCsv, writeGeneratorToCSV };
1638
+ export { ALL_STREAM_ID_KEYWORD, API_CALLS_METRIC_NAME, type AssetEntry, type AssetManifest, type AssetManifestEntry, type AssetReplicationMode, AssetStream, AssetTap, AssetTarget, Authenticator, BATCH_INTERVAL_MS, type BaseConfig, type BigQueryConfig, BigQueryTarget, type BigqueryLocation, type Bookmark, type Bookmarks, CdnAssetTarget, type CdnAssetTargetConfig, type CdnFileMetadata, CdnService, type CdnServiceConfig, type CdnUploadResult, CloudStorageService, type CloudStorageServiceOptions, type ColumnMappingStoreUnsafeToSafe, CounterMetric, CsvExtractionConfigBuilder, type CsvFieldsArrayConfig, type CsvFieldsConfig, type CsvFieldsDictConfig, type CsvFileConfig, type CsvStreamConfig, DEFAULT_MAX_CONCURRENT_STREAMS, DEFAULT_SYNCED_AT_COLUMN, DocumentDownloadSkipError, type DocumentEntry, type DocumentManifest, type DocumentManifestEntry, type DocumentStatus, DocumentStream, type DocumentStreamManifest, type DocumentSummary, DocumentTap, type DownloadFilesOptions, EXECUTION_TIME_METRIC_NAME, type ErrorType, type ExcelCustomExtractorConfig, type ExcelDerivedField, type ExcelExtractionBaseConfig, type ExcelExtractionConfig, ExcelExtractionConfigBuilder, type ExcelFieldMapping, type ExcelFieldSpec, type ExcelSingleSheetExtractionConfig, type ExcelSourceColumn, type ExcelStreamConfig, type FieldType, FileFormat, FilePatterns, FileStream, type FileStreamConfig, type FileStreamEntry, FileTap, type FileTapConfig, type FlattenedSchema, GCSStateProvider, type GetConfig, type HTTPHeaders, type HTTPMethod, ITarget, ImageTransform, type InputTapState, type InternalTableField, type JSONSchemaFieldDefinition, type ListFilesOptions, MIME_TYPES, type Message, type MessageType, type MetricConfiguration, MissingFieldInSchemaError, MissingSchemaError, type PostConfig, type ProcessedAsset, type ProgressMarkers, type PropertiesMetadata, RESTStream, ROWS_SYNCED_METRIC_NAME, RecordMessage, RenameColumnStore, ReplicationMethod, ReplicationMethodMessage, type SafeColumnNameConverterFn, type Schema, SchemaMessage, SchemaValidationError, SftpService, type State, type StateHolder, StateMessage, type StateProvider, StateService, Stream, type StreamId, type StreamManifest, type StreamState, StreamWarehouseSyncService, type StreamWithTempFile, type SyncOptions, Tap, type TapState, type TargetSchemaHook, type TargetSchemaHookInput, type TempFile, type URLParams, VariableExtractors, type WarehouseTableField, type WebpTransformOptions, type WhalyDocument, WhalyDocumentService, type WhalyDocumentServiceConfig, WhalyDocumentTarget, type WhalyPaginatedResponse, type WhalyUploadResult, type WriteGeneratorToCsvOptions, _greaterThan, addDocumentSummaries, addWhalyFields, checkCsvHeaderRow, collectPaginated, countCsvLines, createCellReference, createCsvStreamConfig, createExcelGenerator, createExcelStreamConfig, createTemporaryFileStream, csvFieldsToJsonSchema, downloadFiles, emptyDocumentSummary, excelColumnToIndex, excelFieldsToJsonSchema, excelRowToIndex, extractExcelRows, extractPrimaryKeysFromCsvConfig, extractPrimaryKeysFromExcelFields, extractStateForStream, fieldTypeToJsonSchema, finalizeStateProgressMarkers, findAllMatchingConfigs, flattenSchema, getAllMetrics, getApiEndpoint, getAxiosInstance, getCdnId, getCounterMetric, getCounterMetrics, getDownloadFileApiCall, getDryRunLimit, getJSONApiCall, getJSONApiCallWithFullResponse, getMimeType, getRawJSONApiCall, getServiceAccountKey, gracefulExit, haltAndCatchFire, incrementStreamState, indexToExcelColumn, indexToExcelRow, isDryRun, listFilesRecursively, loadJson, loadSchema, logger, optionalEnv, parseCellReference, postFormDataApiCall, postJSONApiCall, postUrlEncodedApiCall, printMemoryFootprint, processFileStreams, processFromAsyncIterable, removeParasiteProperties, requireEnv, rowGeneratorFromCsv, runWithConcurrency, safePath, unzip, validateExcelConfig, writeDataToCsv, writeGeneratorToCSV };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AxiosInstance, AxiosRequestHeaders, AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios';
1
+ import { AxiosRequestHeaders, AxiosInstance, AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios';
2
2
  import Ajv, { ValidateFunction, ErrorObject } from 'ajv';
3
3
  import { Dayjs } from 'dayjs';
4
4
  import { WriteStream } from 'fs';
@@ -266,6 +266,7 @@ interface BaseConfig {
266
266
  schema: string;
267
267
  syncedAtColumnName?: string;
268
268
  syncedAtColumnUseLegacyStringType?: boolean;
269
+ outputDir?: string;
269
270
  }
270
271
 
271
272
  interface ColumnMappingStoreUnsafeToSafe {
@@ -349,7 +350,8 @@ declare class StreamState$1 {
349
350
  _hasBeenLoadedYetDuringThisSync: boolean;
350
351
  replicationMethod: ReplicationMethod;
351
352
  compiledValidateFn?: ValidateFunction;
352
- constructor(streamId: StreamId, dbSync: StreamWarehouseSyncService, replicationMethod: ReplicationMethod);
353
+ tmpDir: string;
354
+ constructor(streamId: StreamId, dbSync: StreamWarehouseSyncService, replicationMethod: ReplicationMethod, tmpDir?: string);
353
355
  setSchema(schema: FlattenedSchema): void;
354
356
  getSchema(): FlattenedSchema | undefined;
355
357
  setCompiledValidateFn(fn: ValidateFunction): void;
@@ -382,6 +384,8 @@ declare abstract class ITarget<C extends BaseConfig = BaseConfig> {
382
384
  schemaHooks: TargetSchemaHook[];
383
385
  syncTime: Dayjs;
384
386
  stateProvider: StateProvider;
387
+ readonly outputDir: string;
388
+ readonly tmpDir: string;
385
389
  batchedState: any;
386
390
  flushedState: any;
387
391
  renameColumnStore: RenameColumnStore;
@@ -408,6 +412,7 @@ declare abstract class ITarget<C extends BaseConfig = BaseConfig> {
408
412
  private loadAllStreamsInWarehouse;
409
413
  private emitState;
410
414
  private uploadStreamsToWarehouse;
415
+ private logSyncSummary;
411
416
  static uploadSingleStreamToWarehouse: (streamState: StreamState$1) => Promise<void>;
412
417
  }
413
418
 
@@ -693,7 +698,7 @@ declare const addWhalyFields: (record: any, batchDate: string, columnName?: stri
693
698
 
694
699
  declare const flattenSchema: <T>(streamId: StreamId, schema: T) => FlattenedSchema;
695
700
 
696
- declare const createTemporaryFileStream: (streamId: StreamId) => TempFile;
701
+ declare const createTemporaryFileStream: (streamId: StreamId, tmpDir?: string) => TempFile;
697
702
  declare function safePath(path: string): string;
698
703
 
699
704
  /**
@@ -1356,6 +1361,199 @@ declare class ImageTransform {
1356
1361
  static toWebp(inputPath: string, options: WebpTransformOptions): Promise<string>;
1357
1362
  }
1358
1363
 
1364
+ /**
1365
+ * Metadata-only representation of a document in the source system.
1366
+ * Yielded by DocumentStream.listDocuments().
1367
+ */
1368
+ interface DocumentEntry {
1369
+ /** Unique ID in source system — the reconciliation key. */
1370
+ externalId: string;
1371
+ /** Display name in Whaly. */
1372
+ fileName: string;
1373
+ /** Original filename in source system. */
1374
+ originalFileName: string;
1375
+ /** Original file path in source system. */
1376
+ originalFilePath?: string;
1377
+ /** Document author name. */
1378
+ originalAuthor?: string;
1379
+ /** File extension without dot (e.g. "pdf", "xlsx"). */
1380
+ extension: string;
1381
+ /** Source last-modified timestamp. Used for incremental skip. */
1382
+ lastModified?: Date;
1383
+ /** ISO date string: when the document becomes valid. */
1384
+ validFrom?: string;
1385
+ /** ISO date string: when the document expires. */
1386
+ validUntil?: string;
1387
+ /** Custom key-value metadata. */
1388
+ metadata?: Record<string, string>;
1389
+ }
1390
+ /**
1391
+ * A document as it exists in Whaly (returned by the Document API).
1392
+ */
1393
+ interface WhalyDocument {
1394
+ id: string;
1395
+ file_name: string;
1396
+ external_id: string;
1397
+ original_file_name: string;
1398
+ original_file_path: string;
1399
+ original_author: string;
1400
+ extension: string;
1401
+ file_path: string;
1402
+ valid_from: string;
1403
+ valid_until: string;
1404
+ size_kb: number;
1405
+ storage: string;
1406
+ metadata: Record<string, string> | null;
1407
+ }
1408
+ /** Paginated response from the Whaly Document API. */
1409
+ interface WhalyPaginatedResponse<T> {
1410
+ data: T[];
1411
+ paging: {
1412
+ next?: {
1413
+ after: string;
1414
+ };
1415
+ };
1416
+ }
1417
+ type DocumentStatus = "created" | "updated" | "reuploaded" | "deleted" | "skipped" | "error";
1418
+ interface DocumentManifestEntry {
1419
+ externalId: string;
1420
+ fileName: string;
1421
+ status: DocumentStatus;
1422
+ error?: string;
1423
+ }
1424
+ interface DocumentStreamManifest {
1425
+ streamId: string;
1426
+ syncedAt: string;
1427
+ documents: DocumentManifestEntry[];
1428
+ summary: DocumentSummary;
1429
+ }
1430
+ interface DocumentSummary {
1431
+ total: number;
1432
+ created: number;
1433
+ updated: number;
1434
+ reuploaded: number;
1435
+ deleted: number;
1436
+ skipped: number;
1437
+ errors: number;
1438
+ }
1439
+ interface DocumentManifest {
1440
+ syncedAt: string;
1441
+ streams: DocumentStreamManifest[];
1442
+ summary: DocumentSummary;
1443
+ }
1444
+ declare function emptyDocumentSummary(): DocumentSummary;
1445
+ declare function addDocumentSummaries(a: DocumentSummary, b: DocumentSummary): DocumentSummary;
1446
+
1447
+ declare class DocumentDownloadSkipError extends Error {
1448
+ constructor(message: string);
1449
+ }
1450
+
1451
+ declare abstract class DocumentStream<C> {
1452
+ readonly streamId: string;
1453
+ readonly config: C;
1454
+ constructor(streamId: string, config: C);
1455
+ /** Yield all documents from the source (metadata only, no file download). */
1456
+ abstract listDocuments(): AsyncIterable<DocumentEntry>;
1457
+ /** Download a single document file to `destPath` on local disk. */
1458
+ abstract downloadDocument(entry: DocumentEntry, destPath: string): Promise<void>;
1459
+ /**
1460
+ * Escape hatch: should the file be re-uploaded?
1461
+ * Default: true (conservative — always re-upload).
1462
+ * Override to compare timestamps or hashes for incremental skip.
1463
+ */
1464
+ shouldReupload(_sourceEntry: DocumentEntry, _existingDoc: WhalyDocument): boolean;
1465
+ /**
1466
+ * Escape hatch: does the metadata need updating?
1467
+ * Default: compares fileName, validFrom, validUntil, originalAuthor, metadata.
1468
+ */
1469
+ shouldUpdateMetadata(sourceEntry: DocumentEntry, existingDoc: WhalyDocument): boolean;
1470
+ /**
1471
+ * Escape hatch: should this orphaned document be deleted?
1472
+ * Default: true (delete all documents no longer in source).
1473
+ */
1474
+ shouldDelete(_orphanedDoc: WhalyDocument): boolean;
1475
+ }
1476
+
1477
+ interface WhalyDocumentServiceConfig {
1478
+ /** e.g. "https://org.my.whaly.io" */
1479
+ apiEndpoint?: string;
1480
+ /** e.g. "sk:xxxx" */
1481
+ serviceAccountKey?: string;
1482
+ /** Object storage ID for file uploads. */
1483
+ objectStorageId: string;
1484
+ }
1485
+ interface WhalyUploadResult {
1486
+ storage: string;
1487
+ filePath: string;
1488
+ sizeKb: number;
1489
+ }
1490
+ declare class WhalyDocumentService {
1491
+ private axiosClient;
1492
+ readonly objectStorageId: string;
1493
+ private gcsBucket;
1494
+ constructor(config: WhalyDocumentServiceConfig);
1495
+ /** Fetch all documents from the API, handling cursor-based pagination. */
1496
+ listAllDocuments(): Promise<WhalyDocument[]>;
1497
+ /** Upload a file to object storage. Returns storage path and size. */
1498
+ uploadFile(destinationPath: string, localFilePath: string, fileName: string): Promise<WhalyUploadResult>;
1499
+ private uploadFileViaGCS;
1500
+ private uploadFileViaAPI;
1501
+ /** Create a new document record. */
1502
+ createDocument(payload: Omit<WhalyDocument, "id">): Promise<WhalyDocument>;
1503
+ /** Update an existing document record. */
1504
+ updateDocument(id: string, payload: Partial<WhalyDocument>): Promise<WhalyDocument>;
1505
+ /** Delete a document record. */
1506
+ deleteDocument(id: string): Promise<void>;
1507
+ }
1508
+
1509
+ declare class WhalyDocumentTarget {
1510
+ readonly config: WhalyDocumentServiceConfig;
1511
+ private service;
1512
+ constructor(config: WhalyDocumentServiceConfig);
1513
+ /** Fetch all existing documents from Whaly. */
1514
+ listExistingDocuments(): Promise<WhalyDocument[]>;
1515
+ /**
1516
+ * Create a new document: upload file to object storage, then create the document record.
1517
+ * @param streamId Used to namespace the file path in object storage.
1518
+ */
1519
+ createDocument(streamId: string, entry: DocumentEntry, localFilePath: string): Promise<void>;
1520
+ /**
1521
+ * Re-upload the file and update the document record.
1522
+ */
1523
+ reuploadDocument(streamId: string, docId: string, entry: DocumentEntry, localFilePath: string): Promise<void>;
1524
+ /** Update only the metadata fields (no file re-upload). */
1525
+ updateDocumentMetadata(docId: string, entry: DocumentEntry, existingDoc: WhalyDocument): Promise<void>;
1526
+ /** Delete a document record. */
1527
+ deleteDocument(docId: string, externalId: string): Promise<void>;
1528
+ }
1529
+
1530
+ declare abstract class DocumentTap<C> {
1531
+ readonly config: C;
1532
+ readonly outputDir: string;
1533
+ readonly concurrency: number;
1534
+ /**
1535
+ * The single stream for this tap.
1536
+ * Set during init(). A DocumentTap supports exactly one stream to avoid
1537
+ * cross-stream deletion issues (existing docs cannot be filtered by stream).
1538
+ */
1539
+ stream: DocumentStream<unknown>;
1540
+ target: WhalyDocumentTarget;
1541
+ constructor(config: C, outputDir?: string, concurrency?: number);
1542
+ /**
1543
+ * Initialize the tap: set `this.stream` to the single DocumentStream.
1544
+ * Called once at the start of sync().
1545
+ */
1546
+ abstract init(): Promise<void>;
1547
+ sync(): Promise<DocumentManifest>;
1548
+ private collectSourceEntries;
1549
+ private computeDiff;
1550
+ private executeCreate;
1551
+ private executeReupload;
1552
+ private executeMetadataUpdate;
1553
+ private executeDelete;
1554
+ private computeSummary;
1555
+ }
1556
+
1359
1557
  interface BigQueryConfig extends BaseConfig {
1360
1558
  schema: string;
1361
1559
  project_id: string;
@@ -1437,4 +1635,4 @@ declare class GCSStateProvider implements StateProvider {
1437
1635
  writeState(state: string): Promise<void>;
1438
1636
  }
1439
1637
 
1440
- export { ALL_STREAM_ID_KEYWORD, API_CALLS_METRIC_NAME, type AssetEntry, type AssetManifest, type AssetManifestEntry, type AssetReplicationMode, AssetStream, AssetTap, AssetTarget, Authenticator, BATCH_INTERVAL_MS, type BaseConfig, type BigQueryConfig, BigQueryTarget, type BigqueryLocation, type Bookmark, type Bookmarks, CdnAssetTarget, type CdnAssetTargetConfig, type CdnFileMetadata, CdnService, type CdnServiceConfig, type CdnUploadResult, CloudStorageService, type CloudStorageServiceOptions, type ColumnMappingStoreUnsafeToSafe, CounterMetric, CsvExtractionConfigBuilder, type CsvFieldsArrayConfig, type CsvFieldsConfig, type CsvFieldsDictConfig, type CsvFileConfig, type CsvStreamConfig, DEFAULT_MAX_CONCURRENT_STREAMS, DEFAULT_SYNCED_AT_COLUMN, type DownloadFilesOptions, EXECUTION_TIME_METRIC_NAME, type ErrorType, type ExcelCustomExtractorConfig, type ExcelDerivedField, type ExcelExtractionBaseConfig, type ExcelExtractionConfig, ExcelExtractionConfigBuilder, type ExcelFieldMapping, type ExcelFieldSpec, type ExcelSingleSheetExtractionConfig, type ExcelSourceColumn, type ExcelStreamConfig, type FieldType, FileFormat, FilePatterns, FileStream, type FileStreamConfig, type FileStreamEntry, FileTap, type FileTapConfig, type FlattenedSchema, GCSStateProvider, type GetConfig, type HTTPHeaders, type HTTPMethod, ITarget, ImageTransform, type InputTapState, type InternalTableField, type JSONSchemaFieldDefinition, type ListFilesOptions, MIME_TYPES, type Message, type MessageType, type MetricConfiguration, MissingFieldInSchemaError, MissingSchemaError, type PostConfig, type ProcessedAsset, type ProgressMarkers, type PropertiesMetadata, RESTStream, ROWS_SYNCED_METRIC_NAME, RecordMessage, RenameColumnStore, ReplicationMethod, ReplicationMethodMessage, type SafeColumnNameConverterFn, type Schema, SchemaMessage, SchemaValidationError, SftpService, type State, type StateHolder, StateMessage, type StateProvider, StateService, Stream, type StreamId, type StreamManifest, type StreamState, StreamWarehouseSyncService, type StreamWithTempFile, type SyncOptions, Tap, type TapState, type TargetSchemaHook, type TargetSchemaHookInput, type TempFile, type URLParams, VariableExtractors, type WarehouseTableField, type WebpTransformOptions, type WriteGeneratorToCsvOptions, _greaterThan, addWhalyFields, checkCsvHeaderRow, collectPaginated, countCsvLines, createCellReference, createCsvStreamConfig, createExcelGenerator, createExcelStreamConfig, createTemporaryFileStream, csvFieldsToJsonSchema, downloadFiles, excelColumnToIndex, excelFieldsToJsonSchema, excelRowToIndex, extractExcelRows, extractPrimaryKeysFromCsvConfig, extractPrimaryKeysFromExcelFields, extractStateForStream, fieldTypeToJsonSchema, finalizeStateProgressMarkers, findAllMatchingConfigs, flattenSchema, getAllMetrics, getApiEndpoint, getAxiosInstance, getCdnId, getCounterMetric, getCounterMetrics, getDownloadFileApiCall, getDryRunLimit, getJSONApiCall, getJSONApiCallWithFullResponse, getMimeType, getRawJSONApiCall, getServiceAccountKey, gracefulExit, haltAndCatchFire, incrementStreamState, indexToExcelColumn, indexToExcelRow, isDryRun, listFilesRecursively, loadJson, loadSchema, logger, optionalEnv, parseCellReference, postFormDataApiCall, postJSONApiCall, postUrlEncodedApiCall, printMemoryFootprint, processFileStreams, processFromAsyncIterable, removeParasiteProperties, requireEnv, rowGeneratorFromCsv, runWithConcurrency, safePath, unzip, validateExcelConfig, writeDataToCsv, writeGeneratorToCSV };
1638
+ export { ALL_STREAM_ID_KEYWORD, API_CALLS_METRIC_NAME, type AssetEntry, type AssetManifest, type AssetManifestEntry, type AssetReplicationMode, AssetStream, AssetTap, AssetTarget, Authenticator, BATCH_INTERVAL_MS, type BaseConfig, type BigQueryConfig, BigQueryTarget, type BigqueryLocation, type Bookmark, type Bookmarks, CdnAssetTarget, type CdnAssetTargetConfig, type CdnFileMetadata, CdnService, type CdnServiceConfig, type CdnUploadResult, CloudStorageService, type CloudStorageServiceOptions, type ColumnMappingStoreUnsafeToSafe, CounterMetric, CsvExtractionConfigBuilder, type CsvFieldsArrayConfig, type CsvFieldsConfig, type CsvFieldsDictConfig, type CsvFileConfig, type CsvStreamConfig, DEFAULT_MAX_CONCURRENT_STREAMS, DEFAULT_SYNCED_AT_COLUMN, DocumentDownloadSkipError, type DocumentEntry, type DocumentManifest, type DocumentManifestEntry, type DocumentStatus, DocumentStream, type DocumentStreamManifest, type DocumentSummary, DocumentTap, type DownloadFilesOptions, EXECUTION_TIME_METRIC_NAME, type ErrorType, type ExcelCustomExtractorConfig, type ExcelDerivedField, type ExcelExtractionBaseConfig, type ExcelExtractionConfig, ExcelExtractionConfigBuilder, type ExcelFieldMapping, type ExcelFieldSpec, type ExcelSingleSheetExtractionConfig, type ExcelSourceColumn, type ExcelStreamConfig, type FieldType, FileFormat, FilePatterns, FileStream, type FileStreamConfig, type FileStreamEntry, FileTap, type FileTapConfig, type FlattenedSchema, GCSStateProvider, type GetConfig, type HTTPHeaders, type HTTPMethod, ITarget, ImageTransform, type InputTapState, type InternalTableField, type JSONSchemaFieldDefinition, type ListFilesOptions, MIME_TYPES, type Message, type MessageType, type MetricConfiguration, MissingFieldInSchemaError, MissingSchemaError, type PostConfig, type ProcessedAsset, type ProgressMarkers, type PropertiesMetadata, RESTStream, ROWS_SYNCED_METRIC_NAME, RecordMessage, RenameColumnStore, ReplicationMethod, ReplicationMethodMessage, type SafeColumnNameConverterFn, type Schema, SchemaMessage, SchemaValidationError, SftpService, type State, type StateHolder, StateMessage, type StateProvider, StateService, Stream, type StreamId, type StreamManifest, type StreamState, StreamWarehouseSyncService, type StreamWithTempFile, type SyncOptions, Tap, type TapState, type TargetSchemaHook, type TargetSchemaHookInput, type TempFile, type URLParams, VariableExtractors, type WarehouseTableField, type WebpTransformOptions, type WhalyDocument, WhalyDocumentService, type WhalyDocumentServiceConfig, WhalyDocumentTarget, type WhalyPaginatedResponse, type WhalyUploadResult, type WriteGeneratorToCsvOptions, _greaterThan, addDocumentSummaries, addWhalyFields, checkCsvHeaderRow, collectPaginated, countCsvLines, createCellReference, createCsvStreamConfig, createExcelGenerator, createExcelStreamConfig, createTemporaryFileStream, csvFieldsToJsonSchema, downloadFiles, emptyDocumentSummary, excelColumnToIndex, excelFieldsToJsonSchema, excelRowToIndex, extractExcelRows, extractPrimaryKeysFromCsvConfig, extractPrimaryKeysFromExcelFields, extractStateForStream, fieldTypeToJsonSchema, finalizeStateProgressMarkers, findAllMatchingConfigs, flattenSchema, getAllMetrics, getApiEndpoint, getAxiosInstance, getCdnId, getCounterMetric, getCounterMetrics, getDownloadFileApiCall, getDryRunLimit, getJSONApiCall, getJSONApiCallWithFullResponse, getMimeType, getRawJSONApiCall, getServiceAccountKey, gracefulExit, haltAndCatchFire, incrementStreamState, indexToExcelColumn, indexToExcelRow, isDryRun, listFilesRecursively, loadJson, loadSchema, logger, optionalEnv, parseCellReference, postFormDataApiCall, postJSONApiCall, postUrlEncodedApiCall, printMemoryFootprint, processFileStreams, processFromAsyncIterable, removeParasiteProperties, requireEnv, rowGeneratorFromCsv, runWithConcurrency, safePath, unzip, validateExcelConfig, writeDataToCsv, writeGeneratorToCSV };