@bulkimport/core 0.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.
@@ -0,0 +1,335 @@
1
+ type FieldType = 'string' | 'number' | 'boolean' | 'date' | 'email' | 'custom';
2
+ interface ValidationFieldResult {
3
+ valid: boolean;
4
+ message?: string;
5
+ }
6
+ interface FieldDefinition {
7
+ readonly name: string;
8
+ readonly type: FieldType;
9
+ readonly required: boolean;
10
+ readonly pattern?: RegExp;
11
+ readonly customValidator?: (value: unknown) => ValidationFieldResult;
12
+ readonly transform?: (value: unknown) => unknown;
13
+ readonly defaultValue?: unknown;
14
+ }
15
+
16
+ interface SchemaDefinition {
17
+ readonly fields: readonly FieldDefinition[];
18
+ readonly strict?: boolean;
19
+ readonly skipEmptyRows?: boolean;
20
+ }
21
+
22
+ declare const ImportStatus: {
23
+ readonly CREATED: "CREATED";
24
+ readonly PREVIEWING: "PREVIEWING";
25
+ readonly PREVIEWED: "PREVIEWED";
26
+ readonly PROCESSING: "PROCESSING";
27
+ readonly PAUSED: "PAUSED";
28
+ readonly COMPLETED: "COMPLETED";
29
+ readonly ABORTED: "ABORTED";
30
+ readonly FAILED: "FAILED";
31
+ };
32
+ type ImportStatus = (typeof ImportStatus)[keyof typeof ImportStatus];
33
+
34
+ declare const BatchStatus: {
35
+ readonly PENDING: "PENDING";
36
+ readonly PROCESSING: "PROCESSING";
37
+ readonly PAUSED: "PAUSED";
38
+ readonly COMPLETED: "COMPLETED";
39
+ readonly FAILED: "FAILED";
40
+ };
41
+ type BatchStatus = (typeof BatchStatus)[keyof typeof BatchStatus];
42
+
43
+ type ValidationErrorCode = 'REQUIRED' | 'TYPE_MISMATCH' | 'PATTERN_MISMATCH' | 'CUSTOM_VALIDATION' | 'UNKNOWN_FIELD';
44
+ interface ValidationError {
45
+ readonly field: string;
46
+ readonly message: string;
47
+ readonly code: ValidationErrorCode;
48
+ readonly value?: unknown;
49
+ }
50
+ interface ValidationResult {
51
+ readonly isValid: boolean;
52
+ readonly errors: readonly ValidationError[];
53
+ }
54
+
55
+ type RecordStatus = 'valid' | 'invalid' | 'processed' | 'failed' | 'pending';
56
+ interface RawRecord {
57
+ readonly [key: string]: unknown;
58
+ }
59
+ interface ProcessedRecord {
60
+ readonly index: number;
61
+ readonly raw: RawRecord;
62
+ readonly parsed: RawRecord;
63
+ readonly status: RecordStatus;
64
+ readonly errors: readonly ValidationError[];
65
+ readonly processingError?: string;
66
+ }
67
+
68
+ interface Batch {
69
+ readonly id: string;
70
+ readonly index: number;
71
+ readonly status: BatchStatus;
72
+ readonly records: readonly ProcessedRecord[];
73
+ readonly processedCount: number;
74
+ readonly failedCount: number;
75
+ }
76
+
77
+ interface ImportJobConfig {
78
+ readonly id?: string;
79
+ readonly schema: SchemaDefinition;
80
+ readonly batchSize: number;
81
+ readonly maxConcurrentBatches?: number;
82
+ readonly continueOnError?: boolean;
83
+ }
84
+ interface ImportJobState {
85
+ readonly id: string;
86
+ readonly config: ImportJobConfig;
87
+ readonly status: ImportStatus;
88
+ readonly batches: readonly Batch[];
89
+ readonly totalRecords: number;
90
+ readonly startedAt?: number;
91
+ readonly completedAt?: number;
92
+ }
93
+ interface ImportProgress {
94
+ readonly totalRecords: number;
95
+ readonly processedRecords: number;
96
+ readonly failedRecords: number;
97
+ readonly pendingRecords: number;
98
+ readonly percentage: number;
99
+ readonly currentBatch: number;
100
+ readonly totalBatches: number;
101
+ readonly elapsedMs: number;
102
+ readonly estimatedRemainingMs?: number;
103
+ }
104
+ interface ImportSummary {
105
+ readonly total: number;
106
+ readonly processed: number;
107
+ readonly failed: number;
108
+ readonly skipped: number;
109
+ readonly elapsedMs: number;
110
+ }
111
+ interface PreviewResult {
112
+ readonly validRecords: readonly ProcessedRecord[];
113
+ readonly invalidRecords: readonly ProcessedRecord[];
114
+ readonly totalSampled: number;
115
+ readonly columns: readonly string[];
116
+ }
117
+
118
+ interface ParserOptions {
119
+ readonly delimiter?: string;
120
+ readonly encoding?: string;
121
+ readonly hasHeader?: boolean;
122
+ }
123
+ interface SourceParser {
124
+ parse(data: string | Buffer): AsyncIterable<RawRecord> | Iterable<RawRecord>;
125
+ detect?(sample: string | Buffer): ParserOptions;
126
+ }
127
+
128
+ interface SourceMetadata {
129
+ readonly fileName?: string;
130
+ readonly fileSize?: number;
131
+ readonly mimeType?: string;
132
+ }
133
+ interface DataSource {
134
+ read(): AsyncIterable<string | Buffer>;
135
+ sample(maxBytes?: number): Promise<string | Buffer>;
136
+ metadata(): SourceMetadata;
137
+ }
138
+
139
+ interface BatchState {
140
+ readonly batchId: string;
141
+ readonly status: BatchStatus;
142
+ readonly processedCount: number;
143
+ readonly failedCount: number;
144
+ }
145
+ interface StateStore {
146
+ saveJobState(job: ImportJobState): Promise<void>;
147
+ getJobState(jobId: string): Promise<ImportJobState | null>;
148
+ updateBatchState(jobId: string, batchId: string, state: BatchState): Promise<void>;
149
+ saveProcessedRecord(jobId: string, batchId: string, record: ProcessedRecord): Promise<void>;
150
+ getFailedRecords(jobId: string): Promise<readonly ProcessedRecord[]>;
151
+ getPendingRecords(jobId: string): Promise<readonly ProcessedRecord[]>;
152
+ getProcessedRecords(jobId: string): Promise<readonly ProcessedRecord[]>;
153
+ getProgress(jobId: string): Promise<ImportProgress>;
154
+ }
155
+
156
+ interface ProcessingContext {
157
+ readonly jobId: string;
158
+ readonly batchId: string;
159
+ readonly batchIndex: number;
160
+ readonly recordIndex: number;
161
+ readonly totalRecords: number;
162
+ readonly signal: AbortSignal;
163
+ }
164
+ type RecordProcessorFn = (record: RawRecord, context: ProcessingContext) => Promise<void>;
165
+
166
+ interface ImportStartedEvent {
167
+ readonly type: 'import:started';
168
+ readonly jobId: string;
169
+ readonly totalRecords: number;
170
+ readonly totalBatches: number;
171
+ readonly timestamp: number;
172
+ }
173
+ interface ImportCompletedEvent {
174
+ readonly type: 'import:completed';
175
+ readonly jobId: string;
176
+ readonly summary: ImportSummary;
177
+ readonly timestamp: number;
178
+ }
179
+ interface ImportPausedEvent {
180
+ readonly type: 'import:paused';
181
+ readonly jobId: string;
182
+ readonly progress: ImportProgress;
183
+ readonly timestamp: number;
184
+ }
185
+ interface ImportAbortedEvent {
186
+ readonly type: 'import:aborted';
187
+ readonly jobId: string;
188
+ readonly progress: ImportProgress;
189
+ readonly timestamp: number;
190
+ }
191
+ interface ImportFailedEvent {
192
+ readonly type: 'import:failed';
193
+ readonly jobId: string;
194
+ readonly error: string;
195
+ readonly timestamp: number;
196
+ }
197
+ interface ImportProgressEvent {
198
+ readonly type: 'import:progress';
199
+ readonly jobId: string;
200
+ readonly progress: ImportProgress;
201
+ readonly timestamp: number;
202
+ }
203
+ interface BatchStartedEvent {
204
+ readonly type: 'batch:started';
205
+ readonly jobId: string;
206
+ readonly batchId: string;
207
+ readonly batchIndex: number;
208
+ readonly recordCount: number;
209
+ readonly timestamp: number;
210
+ }
211
+ interface BatchCompletedEvent {
212
+ readonly type: 'batch:completed';
213
+ readonly jobId: string;
214
+ readonly batchId: string;
215
+ readonly batchIndex: number;
216
+ readonly processedCount: number;
217
+ readonly failedCount: number;
218
+ readonly totalCount: number;
219
+ readonly timestamp: number;
220
+ }
221
+ interface BatchFailedEvent {
222
+ readonly type: 'batch:failed';
223
+ readonly jobId: string;
224
+ readonly batchId: string;
225
+ readonly batchIndex: number;
226
+ readonly error: string;
227
+ readonly timestamp: number;
228
+ }
229
+ interface RecordProcessedEvent {
230
+ readonly type: 'record:processed';
231
+ readonly jobId: string;
232
+ readonly batchId: string;
233
+ readonly recordIndex: number;
234
+ readonly timestamp: number;
235
+ }
236
+ interface RecordFailedEvent {
237
+ readonly type: 'record:failed';
238
+ readonly jobId: string;
239
+ readonly batchId: string;
240
+ readonly recordIndex: number;
241
+ readonly error: string;
242
+ readonly record: ProcessedRecord;
243
+ readonly timestamp: number;
244
+ }
245
+ type DomainEvent = ImportStartedEvent | ImportCompletedEvent | ImportPausedEvent | ImportAbortedEvent | ImportFailedEvent | ImportProgressEvent | BatchStartedEvent | BatchCompletedEvent | BatchFailedEvent | RecordProcessedEvent | RecordFailedEvent;
246
+ type EventType = DomainEvent['type'];
247
+ type EventPayload<T extends EventType> = Extract<DomainEvent, {
248
+ type: T;
249
+ }>;
250
+
251
+ interface BulkImportConfig {
252
+ readonly schema: SchemaDefinition;
253
+ readonly batchSize?: number;
254
+ readonly maxConcurrentBatches?: number;
255
+ readonly continueOnError?: boolean;
256
+ readonly stateStore?: StateStore;
257
+ }
258
+ declare class BulkImport {
259
+ private readonly config;
260
+ private readonly validator;
261
+ private readonly eventBus;
262
+ private readonly stateStore;
263
+ private source;
264
+ private parser;
265
+ private jobId;
266
+ private status;
267
+ private batches;
268
+ private allRecords;
269
+ private totalRecords;
270
+ private startedAt?;
271
+ private abortController;
272
+ private pausePromise;
273
+ constructor(config: BulkImportConfig);
274
+ from(source: DataSource, parser: SourceParser): this;
275
+ on<T extends EventType>(type: T, handler: (event: EventPayload<T>) => void): this;
276
+ preview(maxRecords?: number): Promise<PreviewResult>;
277
+ start(processor: RecordProcessorFn): Promise<void>;
278
+ pause(): Promise<void>;
279
+ resume(): void;
280
+ abort(): Promise<void>;
281
+ getStatus(): {
282
+ state: ImportStatus;
283
+ progress: ImportProgress;
284
+ batches: readonly Batch[];
285
+ };
286
+ getFailedRecords(): readonly ProcessedRecord[];
287
+ getPendingRecords(): readonly ProcessedRecord[];
288
+ getJobId(): string;
289
+ private processBatch;
290
+ private parseRecords;
291
+ private splitIntoBatches;
292
+ private updateRecord;
293
+ private updateBatchStatus;
294
+ private transitionTo;
295
+ private buildProgress;
296
+ private buildSummary;
297
+ private emitProgress;
298
+ private saveState;
299
+ private checkPause;
300
+ private createPausePromise;
301
+ private assertSourceConfigured;
302
+ private assertCanStart;
303
+ }
304
+
305
+ declare class CsvParser implements SourceParser {
306
+ private readonly options;
307
+ constructor(options?: Partial<ParserOptions>);
308
+ parse(data: string | Buffer): Iterable<RawRecord>;
309
+ detect(sample: string | Buffer): ParserOptions;
310
+ private isEmptyRow;
311
+ }
312
+
313
+ declare class BufferSource implements DataSource {
314
+ private readonly content;
315
+ private readonly meta;
316
+ constructor(data: string | Buffer, metadata?: Partial<SourceMetadata>);
317
+ read(): AsyncIterable<string>;
318
+ sample(maxBytes?: number): Promise<string>;
319
+ metadata(): SourceMetadata;
320
+ }
321
+
322
+ declare class InMemoryStateStore implements StateStore {
323
+ private jobs;
324
+ private records;
325
+ saveJobState(job: ImportJobState): Promise<void>;
326
+ getJobState(jobId: string): Promise<ImportJobState | null>;
327
+ updateBatchState(jobId: string, batchId: string, state: BatchState): Promise<void>;
328
+ saveProcessedRecord(jobId: string, _batchId: string, record: ProcessedRecord): Promise<void>;
329
+ getFailedRecords(jobId: string): Promise<readonly ProcessedRecord[]>;
330
+ getPendingRecords(jobId: string): Promise<readonly ProcessedRecord[]>;
331
+ getProcessedRecords(jobId: string): Promise<readonly ProcessedRecord[]>;
332
+ getProgress(jobId: string): Promise<ImportProgress>;
333
+ }
334
+
335
+ export { type Batch, type BatchCompletedEvent, type BatchFailedEvent, type BatchStartedEvent, BatchStatus, BufferSource, BulkImport, type BulkImportConfig, CsvParser, type DataSource, type DomainEvent, type EventPayload, type EventType, type FieldDefinition, type FieldType, type ImportAbortedEvent, type ImportCompletedEvent, type ImportFailedEvent, type ImportJobConfig, type ImportJobState, type ImportPausedEvent, type ImportProgress, type ImportProgressEvent, type ImportStartedEvent, ImportStatus, type ImportSummary, InMemoryStateStore, type ParserOptions, type PreviewResult, type ProcessedRecord, type ProcessingContext, type RawRecord, type RecordFailedEvent, type RecordProcessedEvent, type RecordProcessorFn, type RecordStatus, type SchemaDefinition, type SourceMetadata, type SourceParser, type StateStore, type ValidationError, type ValidationErrorCode, type ValidationFieldResult, type ValidationResult };