hazo_files 1.4.7 → 1.5.2

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,166 @@
1
+ type JobStatus = 'queued' | 'uploading' | 'processing' | 'awaiting_confirmation' | 'completing' | 'done' | 'error';
2
+ interface UploadFile {
3
+ file: File;
4
+ file_id?: string;
5
+ file_name: string;
6
+ mime_type: string;
7
+ download_url?: string;
8
+ }
9
+ interface PipelineContext {
10
+ files: UploadFile[];
11
+ group_id: string;
12
+ group_label?: string;
13
+ extracted_data: Record<string, unknown>;
14
+ metadata: Record<string, unknown>;
15
+ }
16
+ interface ConfirmationResult {
17
+ confirmed: boolean;
18
+ data?: unknown;
19
+ }
20
+ interface JobHandle {
21
+ job_id: string;
22
+ set_status: (status: JobStatus) => void;
23
+ set_progress: (current: number, total: number) => void;
24
+ request_confirmation: <T = unknown>(payload: T) => Promise<ConfirmationResult>;
25
+ is_cancelled: () => boolean;
26
+ }
27
+ interface PipelineStep {
28
+ name: string;
29
+ execute: (context: PipelineContext, handle: JobHandle) => Promise<void>;
30
+ }
31
+ interface CreateBatchOptions {
32
+ files: File[];
33
+ group_id: string;
34
+ group_label?: string;
35
+ metadata?: Record<string, unknown>;
36
+ pipeline_steps?: PipelineStep[];
37
+ }
38
+ interface JobSnapshot {
39
+ job_id: string;
40
+ batch_id: string;
41
+ status: JobStatus;
42
+ group_id: string;
43
+ group_label?: string;
44
+ files: UploadFile[];
45
+ progress: {
46
+ current: number;
47
+ total: number;
48
+ } | null;
49
+ extracted_data: Record<string, unknown>;
50
+ error: string | null;
51
+ metadata: Record<string, unknown>;
52
+ confirmation_payload: unknown | null;
53
+ created_at: number;
54
+ updated_at: number;
55
+ }
56
+ interface BatchInfo {
57
+ batch_id: string;
58
+ job_ids: string[];
59
+ total: number;
60
+ completed: number;
61
+ failed: number;
62
+ }
63
+ interface UploadManagerEvents {
64
+ 'job:created': {
65
+ job: JobSnapshot;
66
+ };
67
+ 'job:status_changed': {
68
+ job: JobSnapshot;
69
+ previous_status: JobStatus;
70
+ };
71
+ 'job:progress': {
72
+ job: JobSnapshot;
73
+ };
74
+ 'job:completed': {
75
+ job: JobSnapshot;
76
+ };
77
+ 'job:error': {
78
+ job: JobSnapshot;
79
+ error: string;
80
+ };
81
+ 'job:confirmation_needed': {
82
+ job: JobSnapshot;
83
+ payload: unknown;
84
+ };
85
+ 'job:confirmation_resolved': {
86
+ job: JobSnapshot;
87
+ result: ConfirmationResult;
88
+ };
89
+ 'batch:progress': {
90
+ batch: BatchInfo;
91
+ };
92
+ 'batch:completed': {
93
+ batch: BatchInfo;
94
+ };
95
+ }
96
+ interface UploadManagerConfig {
97
+ max_concurrent?: number;
98
+ default_pipeline_steps?: PipelineStep[];
99
+ }
100
+
101
+ type Listener<T> = (data: T) => void;
102
+ declare class TypedEventEmitter<TEvents extends Record<string, any>> {
103
+ private listeners;
104
+ on<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): () => void;
105
+ emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void;
106
+ off<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): void;
107
+ removeAllListeners(): void;
108
+ }
109
+
110
+ interface JobInit {
111
+ batch_id: string;
112
+ files: File[];
113
+ group_id: string;
114
+ group_label?: string;
115
+ pipeline_steps: PipelineStep[];
116
+ metadata?: Record<string, unknown>;
117
+ }
118
+ declare class Job {
119
+ readonly job_id: string;
120
+ readonly batch_id: string;
121
+ readonly created_at: number;
122
+ private status;
123
+ private progress;
124
+ private error;
125
+ private confirmation_payload;
126
+ private confirmation_resolve;
127
+ private context;
128
+ private readonly pipeline_steps;
129
+ private updated_at;
130
+ constructor(init: JobInit);
131
+ get_snapshot(): JobSnapshot;
132
+ set_status(status: JobStatus): void;
133
+ set_progress(current: number, total: number): void;
134
+ set_error(message: string): void;
135
+ request_confirmation<T>(payload: T): Promise<ConfirmationResult>;
136
+ resolve_confirmation(result: ConfirmationResult): void;
137
+ get_context(): PipelineContext;
138
+ get_pipeline_steps(): PipelineStep[];
139
+ }
140
+
141
+ declare class PipelineExecutor {
142
+ execute(job: Job, emitter: TypedEventEmitter<UploadManagerEvents>): Promise<void>;
143
+ }
144
+
145
+ declare class UploadManager {
146
+ private jobs;
147
+ private batches;
148
+ private executor;
149
+ private emitter;
150
+ private queue;
151
+ private running;
152
+ private destroyed;
153
+ private readonly config;
154
+ constructor(config?: UploadManagerConfig);
155
+ on<K extends keyof UploadManagerEvents>(event: K, listener: (data: UploadManagerEvents[K]) => void): () => void;
156
+ submit_batch(options: CreateBatchOptions): string;
157
+ get_jobs_for_group(group_id: string): JobSnapshot[];
158
+ get_job(job_id: string): JobSnapshot | null;
159
+ get_active_jobs(): JobSnapshot[];
160
+ resolve_confirmation(job_id: string, result: ConfirmationResult): void;
161
+ destroy(): void;
162
+ private process_queue;
163
+ private on_job_settled;
164
+ }
165
+
166
+ export { type BatchInfo, type ConfirmationResult, type CreateBatchOptions, Job, type JobHandle, type JobSnapshot, type JobStatus, type PipelineContext, PipelineExecutor, type PipelineStep, TypedEventEmitter, type UploadFile, UploadManager, type UploadManagerConfig, type UploadManagerEvents };
@@ -0,0 +1,166 @@
1
+ type JobStatus = 'queued' | 'uploading' | 'processing' | 'awaiting_confirmation' | 'completing' | 'done' | 'error';
2
+ interface UploadFile {
3
+ file: File;
4
+ file_id?: string;
5
+ file_name: string;
6
+ mime_type: string;
7
+ download_url?: string;
8
+ }
9
+ interface PipelineContext {
10
+ files: UploadFile[];
11
+ group_id: string;
12
+ group_label?: string;
13
+ extracted_data: Record<string, unknown>;
14
+ metadata: Record<string, unknown>;
15
+ }
16
+ interface ConfirmationResult {
17
+ confirmed: boolean;
18
+ data?: unknown;
19
+ }
20
+ interface JobHandle {
21
+ job_id: string;
22
+ set_status: (status: JobStatus) => void;
23
+ set_progress: (current: number, total: number) => void;
24
+ request_confirmation: <T = unknown>(payload: T) => Promise<ConfirmationResult>;
25
+ is_cancelled: () => boolean;
26
+ }
27
+ interface PipelineStep {
28
+ name: string;
29
+ execute: (context: PipelineContext, handle: JobHandle) => Promise<void>;
30
+ }
31
+ interface CreateBatchOptions {
32
+ files: File[];
33
+ group_id: string;
34
+ group_label?: string;
35
+ metadata?: Record<string, unknown>;
36
+ pipeline_steps?: PipelineStep[];
37
+ }
38
+ interface JobSnapshot {
39
+ job_id: string;
40
+ batch_id: string;
41
+ status: JobStatus;
42
+ group_id: string;
43
+ group_label?: string;
44
+ files: UploadFile[];
45
+ progress: {
46
+ current: number;
47
+ total: number;
48
+ } | null;
49
+ extracted_data: Record<string, unknown>;
50
+ error: string | null;
51
+ metadata: Record<string, unknown>;
52
+ confirmation_payload: unknown | null;
53
+ created_at: number;
54
+ updated_at: number;
55
+ }
56
+ interface BatchInfo {
57
+ batch_id: string;
58
+ job_ids: string[];
59
+ total: number;
60
+ completed: number;
61
+ failed: number;
62
+ }
63
+ interface UploadManagerEvents {
64
+ 'job:created': {
65
+ job: JobSnapshot;
66
+ };
67
+ 'job:status_changed': {
68
+ job: JobSnapshot;
69
+ previous_status: JobStatus;
70
+ };
71
+ 'job:progress': {
72
+ job: JobSnapshot;
73
+ };
74
+ 'job:completed': {
75
+ job: JobSnapshot;
76
+ };
77
+ 'job:error': {
78
+ job: JobSnapshot;
79
+ error: string;
80
+ };
81
+ 'job:confirmation_needed': {
82
+ job: JobSnapshot;
83
+ payload: unknown;
84
+ };
85
+ 'job:confirmation_resolved': {
86
+ job: JobSnapshot;
87
+ result: ConfirmationResult;
88
+ };
89
+ 'batch:progress': {
90
+ batch: BatchInfo;
91
+ };
92
+ 'batch:completed': {
93
+ batch: BatchInfo;
94
+ };
95
+ }
96
+ interface UploadManagerConfig {
97
+ max_concurrent?: number;
98
+ default_pipeline_steps?: PipelineStep[];
99
+ }
100
+
101
+ type Listener<T> = (data: T) => void;
102
+ declare class TypedEventEmitter<TEvents extends Record<string, any>> {
103
+ private listeners;
104
+ on<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): () => void;
105
+ emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void;
106
+ off<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): void;
107
+ removeAllListeners(): void;
108
+ }
109
+
110
+ interface JobInit {
111
+ batch_id: string;
112
+ files: File[];
113
+ group_id: string;
114
+ group_label?: string;
115
+ pipeline_steps: PipelineStep[];
116
+ metadata?: Record<string, unknown>;
117
+ }
118
+ declare class Job {
119
+ readonly job_id: string;
120
+ readonly batch_id: string;
121
+ readonly created_at: number;
122
+ private status;
123
+ private progress;
124
+ private error;
125
+ private confirmation_payload;
126
+ private confirmation_resolve;
127
+ private context;
128
+ private readonly pipeline_steps;
129
+ private updated_at;
130
+ constructor(init: JobInit);
131
+ get_snapshot(): JobSnapshot;
132
+ set_status(status: JobStatus): void;
133
+ set_progress(current: number, total: number): void;
134
+ set_error(message: string): void;
135
+ request_confirmation<T>(payload: T): Promise<ConfirmationResult>;
136
+ resolve_confirmation(result: ConfirmationResult): void;
137
+ get_context(): PipelineContext;
138
+ get_pipeline_steps(): PipelineStep[];
139
+ }
140
+
141
+ declare class PipelineExecutor {
142
+ execute(job: Job, emitter: TypedEventEmitter<UploadManagerEvents>): Promise<void>;
143
+ }
144
+
145
+ declare class UploadManager {
146
+ private jobs;
147
+ private batches;
148
+ private executor;
149
+ private emitter;
150
+ private queue;
151
+ private running;
152
+ private destroyed;
153
+ private readonly config;
154
+ constructor(config?: UploadManagerConfig);
155
+ on<K extends keyof UploadManagerEvents>(event: K, listener: (data: UploadManagerEvents[K]) => void): () => void;
156
+ submit_batch(options: CreateBatchOptions): string;
157
+ get_jobs_for_group(group_id: string): JobSnapshot[];
158
+ get_job(job_id: string): JobSnapshot | null;
159
+ get_active_jobs(): JobSnapshot[];
160
+ resolve_confirmation(job_id: string, result: ConfirmationResult): void;
161
+ destroy(): void;
162
+ private process_queue;
163
+ private on_job_settled;
164
+ }
165
+
166
+ export { type BatchInfo, type ConfirmationResult, type CreateBatchOptions, Job, type JobHandle, type JobSnapshot, type JobStatus, type PipelineContext, PipelineExecutor, type PipelineStep, TypedEventEmitter, type UploadFile, UploadManager, type UploadManagerConfig, type UploadManagerEvents };
@@ -0,0 +1,301 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/background_upload/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Job: () => Job,
24
+ PipelineExecutor: () => PipelineExecutor,
25
+ TypedEventEmitter: () => TypedEventEmitter,
26
+ UploadManager: () => UploadManager
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+
30
+ // src/background_upload/core/event-emitter.ts
31
+ var TypedEventEmitter = class {
32
+ constructor() {
33
+ this.listeners = /* @__PURE__ */ new Map();
34
+ }
35
+ on(event, listener) {
36
+ let set = this.listeners.get(event);
37
+ if (!set) {
38
+ set = /* @__PURE__ */ new Set();
39
+ this.listeners.set(event, set);
40
+ }
41
+ set.add(listener);
42
+ return () => this.off(event, listener);
43
+ }
44
+ emit(event, data) {
45
+ const set = this.listeners.get(event);
46
+ if (!set) return;
47
+ for (const listener of set) {
48
+ listener(data);
49
+ }
50
+ }
51
+ off(event, listener) {
52
+ this.listeners.get(event)?.delete(listener);
53
+ }
54
+ removeAllListeners() {
55
+ this.listeners.clear();
56
+ }
57
+ };
58
+
59
+ // src/background_upload/core/job.ts
60
+ var Job = class {
61
+ constructor(init) {
62
+ this.status = "queued";
63
+ this.progress = null;
64
+ this.error = null;
65
+ this.confirmation_payload = null;
66
+ this.confirmation_resolve = null;
67
+ this.job_id = crypto.randomUUID();
68
+ this.batch_id = init.batch_id;
69
+ this.created_at = Date.now();
70
+ this.updated_at = this.created_at;
71
+ this.pipeline_steps = init.pipeline_steps;
72
+ this.context = {
73
+ files: init.files.map((f) => ({
74
+ file: f,
75
+ file_name: f.name,
76
+ mime_type: f.type
77
+ })),
78
+ group_id: init.group_id,
79
+ group_label: init.group_label,
80
+ extracted_data: {},
81
+ metadata: { ...init.metadata ?? {} }
82
+ };
83
+ }
84
+ get_snapshot() {
85
+ return {
86
+ job_id: this.job_id,
87
+ batch_id: this.batch_id,
88
+ status: this.status,
89
+ group_id: this.context.group_id,
90
+ group_label: this.context.group_label,
91
+ files: [...this.context.files],
92
+ progress: this.progress ? { ...this.progress } : null,
93
+ extracted_data: { ...this.context.extracted_data },
94
+ error: this.error,
95
+ metadata: { ...this.context.metadata },
96
+ confirmation_payload: this.confirmation_payload,
97
+ created_at: this.created_at,
98
+ updated_at: this.updated_at
99
+ };
100
+ }
101
+ set_status(status) {
102
+ this.status = status;
103
+ this.updated_at = Date.now();
104
+ }
105
+ set_progress(current, total) {
106
+ this.progress = { current, total };
107
+ this.updated_at = Date.now();
108
+ }
109
+ set_error(message) {
110
+ this.error = message;
111
+ this.updated_at = Date.now();
112
+ }
113
+ request_confirmation(payload) {
114
+ this.confirmation_payload = payload;
115
+ this.set_status("awaiting_confirmation");
116
+ return new Promise((resolve) => {
117
+ this.confirmation_resolve = resolve;
118
+ });
119
+ }
120
+ resolve_confirmation(result) {
121
+ if (this.confirmation_resolve) {
122
+ this.confirmation_resolve(result);
123
+ this.confirmation_resolve = null;
124
+ this.confirmation_payload = null;
125
+ this.updated_at = Date.now();
126
+ }
127
+ }
128
+ get_context() {
129
+ return this.context;
130
+ }
131
+ get_pipeline_steps() {
132
+ return this.pipeline_steps;
133
+ }
134
+ };
135
+
136
+ // src/background_upload/core/pipeline-executor.ts
137
+ var PipelineExecutor = class {
138
+ async execute(job, emitter) {
139
+ const steps = job.get_pipeline_steps();
140
+ const context = job.get_context();
141
+ const handle = {
142
+ job_id: job.job_id,
143
+ set_status: (status) => {
144
+ const previous_status = job.get_snapshot().status;
145
+ job.set_status(status);
146
+ emitter.emit("job:status_changed", { job: job.get_snapshot(), previous_status });
147
+ },
148
+ set_progress: (current, total) => {
149
+ job.set_progress(current, total);
150
+ emitter.emit("job:progress", { job: job.get_snapshot() });
151
+ },
152
+ request_confirmation: async (payload) => {
153
+ const previous_status = job.get_snapshot().status;
154
+ const result_promise = job.request_confirmation(payload);
155
+ emitter.emit("job:confirmation_needed", { job: job.get_snapshot(), payload });
156
+ emitter.emit("job:status_changed", { job: job.get_snapshot(), previous_status });
157
+ const result = await result_promise;
158
+ emitter.emit("job:confirmation_resolved", { job: job.get_snapshot(), result });
159
+ return result;
160
+ },
161
+ is_cancelled: () => job.get_snapshot().status === "error"
162
+ };
163
+ try {
164
+ for (const step of steps) {
165
+ if (handle.is_cancelled()) break;
166
+ await step.execute(context, handle);
167
+ }
168
+ if (!handle.is_cancelled()) {
169
+ const previous_status = job.get_snapshot().status;
170
+ job.set_status("done");
171
+ emitter.emit("job:status_changed", { job: job.get_snapshot(), previous_status });
172
+ emitter.emit("job:completed", { job: job.get_snapshot() });
173
+ }
174
+ } catch (err) {
175
+ const message = err instanceof Error ? err.message : String(err);
176
+ const previous_status = job.get_snapshot().status;
177
+ job.set_error(message);
178
+ job.set_status("error");
179
+ emitter.emit("job:status_changed", { job: job.get_snapshot(), previous_status });
180
+ emitter.emit("job:error", { job: job.get_snapshot(), error: message });
181
+ }
182
+ }
183
+ };
184
+
185
+ // src/background_upload/core/upload-manager.ts
186
+ var UploadManager = class {
187
+ constructor(config) {
188
+ this.jobs = /* @__PURE__ */ new Map();
189
+ this.batches = /* @__PURE__ */ new Map();
190
+ this.executor = new PipelineExecutor();
191
+ this.emitter = new TypedEventEmitter();
192
+ this.queue = [];
193
+ this.running = 0;
194
+ this.destroyed = false;
195
+ this.config = {
196
+ max_concurrent: config?.max_concurrent ?? 1,
197
+ default_pipeline_steps: config?.default_pipeline_steps ?? []
198
+ };
199
+ this.emitter.on("job:completed", ({ job }) => this.on_job_settled(job));
200
+ this.emitter.on("job:error", ({ job }) => this.on_job_settled(job));
201
+ }
202
+ on(event, listener) {
203
+ return this.emitter.on(event, listener);
204
+ }
205
+ submit_batch(options) {
206
+ if (this.destroyed) throw new Error("UploadManager is destroyed");
207
+ const batch_id = crypto.randomUUID();
208
+ const job_ids = [];
209
+ const pipeline_steps = options.pipeline_steps ?? this.config.default_pipeline_steps;
210
+ for (const file of options.files) {
211
+ const job = new Job({
212
+ batch_id,
213
+ files: [file],
214
+ group_id: options.group_id,
215
+ group_label: options.group_label,
216
+ pipeline_steps,
217
+ metadata: options.metadata
218
+ });
219
+ this.jobs.set(job.job_id, job);
220
+ job_ids.push(job.job_id);
221
+ this.emitter.emit("job:created", { job: job.get_snapshot() });
222
+ this.queue.push(job.job_id);
223
+ }
224
+ this.batches.set(batch_id, {
225
+ batch_id,
226
+ job_ids,
227
+ total: options.files.length,
228
+ completed: 0,
229
+ failed: 0,
230
+ emitted_complete: false
231
+ });
232
+ this.process_queue();
233
+ return batch_id;
234
+ }
235
+ get_jobs_for_group(group_id) {
236
+ const out = [];
237
+ for (const job of this.jobs.values()) {
238
+ const snap = job.get_snapshot();
239
+ if (snap.group_id === group_id) out.push(snap);
240
+ }
241
+ return out;
242
+ }
243
+ get_job(job_id) {
244
+ return this.jobs.get(job_id)?.get_snapshot() ?? null;
245
+ }
246
+ get_active_jobs() {
247
+ const out = [];
248
+ for (const job of this.jobs.values()) {
249
+ const snap = job.get_snapshot();
250
+ if (snap.status !== "done" && snap.status !== "error") out.push(snap);
251
+ }
252
+ return out;
253
+ }
254
+ resolve_confirmation(job_id, result) {
255
+ const job = this.jobs.get(job_id);
256
+ if (job) job.resolve_confirmation(result);
257
+ }
258
+ destroy() {
259
+ this.destroyed = true;
260
+ this.emitter.removeAllListeners();
261
+ this.jobs.clear();
262
+ this.batches.clear();
263
+ this.queue = [];
264
+ }
265
+ process_queue() {
266
+ while (!this.destroyed && this.queue.length > 0 && this.running < this.config.max_concurrent) {
267
+ const job_id = this.queue.shift();
268
+ const job = this.jobs.get(job_id);
269
+ if (!job) continue;
270
+ this.running++;
271
+ void this.executor.execute(job, this.emitter).finally(() => {
272
+ this.running--;
273
+ this.process_queue();
274
+ });
275
+ }
276
+ }
277
+ on_job_settled(job) {
278
+ const batch = this.batches.get(job.batch_id);
279
+ if (!batch) return;
280
+ let completed = 0, failed = 0;
281
+ for (const jid of batch.job_ids) {
282
+ const s = this.jobs.get(jid)?.get_snapshot().status;
283
+ if (s === "done") completed++;
284
+ else if (s === "error") failed++;
285
+ }
286
+ batch.completed = completed;
287
+ batch.failed = failed;
288
+ this.emitter.emit("batch:progress", { batch: { ...batch } });
289
+ if (!batch.emitted_complete && completed + failed === batch.total) {
290
+ batch.emitted_complete = true;
291
+ this.emitter.emit("batch:completed", { batch: { ...batch } });
292
+ }
293
+ }
294
+ };
295
+ // Annotate the CommonJS export names for ESM import in node:
296
+ 0 && (module.exports = {
297
+ Job,
298
+ PipelineExecutor,
299
+ TypedEventEmitter,
300
+ UploadManager
301
+ });