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.
- package/CHANGE_LOG.md +486 -0
- package/README.md +158 -0
- package/SETUP_CHECKLIST.md +1309 -0
- package/dist/background-upload/index.d.mts +166 -0
- package/dist/background-upload/index.d.ts +166 -0
- package/dist/background-upload/index.js +301 -0
- package/dist/background-upload/index.mjs +271 -0
- package/dist/background-upload/react/index.d.mts +149 -0
- package/dist/background-upload/react/index.d.ts +149 -0
- package/dist/background-upload/react/index.js +474 -0
- package/dist/background-upload/react/index.mjs +433 -0
- package/package.json +26 -4
- package/docs/SETUP_CHECKLIST.md +0 -260
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/background_upload/react/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
FileUploadContext: () => FileUploadContext,
|
|
34
|
+
HazoFileUploadProvider: () => HazoFileUploadProvider,
|
|
35
|
+
useFileUpload: () => useFileUpload,
|
|
36
|
+
useFileUploadToasts: () => useFileUploadToasts,
|
|
37
|
+
useJobStatus: () => useJobStatus
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(index_exports);
|
|
40
|
+
|
|
41
|
+
// src/background_upload/react/provider.tsx
|
|
42
|
+
var import_react3 = require("react");
|
|
43
|
+
|
|
44
|
+
// src/background_upload/core/job.ts
|
|
45
|
+
var Job = class {
|
|
46
|
+
constructor(init) {
|
|
47
|
+
this.status = "queued";
|
|
48
|
+
this.progress = null;
|
|
49
|
+
this.error = null;
|
|
50
|
+
this.confirmation_payload = null;
|
|
51
|
+
this.confirmation_resolve = null;
|
|
52
|
+
this.job_id = crypto.randomUUID();
|
|
53
|
+
this.batch_id = init.batch_id;
|
|
54
|
+
this.created_at = Date.now();
|
|
55
|
+
this.updated_at = this.created_at;
|
|
56
|
+
this.pipeline_steps = init.pipeline_steps;
|
|
57
|
+
this.context = {
|
|
58
|
+
files: init.files.map((f) => ({
|
|
59
|
+
file: f,
|
|
60
|
+
file_name: f.name,
|
|
61
|
+
mime_type: f.type
|
|
62
|
+
})),
|
|
63
|
+
group_id: init.group_id,
|
|
64
|
+
group_label: init.group_label,
|
|
65
|
+
extracted_data: {},
|
|
66
|
+
metadata: { ...init.metadata ?? {} }
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
get_snapshot() {
|
|
70
|
+
return {
|
|
71
|
+
job_id: this.job_id,
|
|
72
|
+
batch_id: this.batch_id,
|
|
73
|
+
status: this.status,
|
|
74
|
+
group_id: this.context.group_id,
|
|
75
|
+
group_label: this.context.group_label,
|
|
76
|
+
files: [...this.context.files],
|
|
77
|
+
progress: this.progress ? { ...this.progress } : null,
|
|
78
|
+
extracted_data: { ...this.context.extracted_data },
|
|
79
|
+
error: this.error,
|
|
80
|
+
metadata: { ...this.context.metadata },
|
|
81
|
+
confirmation_payload: this.confirmation_payload,
|
|
82
|
+
created_at: this.created_at,
|
|
83
|
+
updated_at: this.updated_at
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
set_status(status) {
|
|
87
|
+
this.status = status;
|
|
88
|
+
this.updated_at = Date.now();
|
|
89
|
+
}
|
|
90
|
+
set_progress(current, total) {
|
|
91
|
+
this.progress = { current, total };
|
|
92
|
+
this.updated_at = Date.now();
|
|
93
|
+
}
|
|
94
|
+
set_error(message) {
|
|
95
|
+
this.error = message;
|
|
96
|
+
this.updated_at = Date.now();
|
|
97
|
+
}
|
|
98
|
+
request_confirmation(payload) {
|
|
99
|
+
this.confirmation_payload = payload;
|
|
100
|
+
this.set_status("awaiting_confirmation");
|
|
101
|
+
return new Promise((resolve) => {
|
|
102
|
+
this.confirmation_resolve = resolve;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
resolve_confirmation(result) {
|
|
106
|
+
if (this.confirmation_resolve) {
|
|
107
|
+
this.confirmation_resolve(result);
|
|
108
|
+
this.confirmation_resolve = null;
|
|
109
|
+
this.confirmation_payload = null;
|
|
110
|
+
this.updated_at = Date.now();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
get_context() {
|
|
114
|
+
return this.context;
|
|
115
|
+
}
|
|
116
|
+
get_pipeline_steps() {
|
|
117
|
+
return this.pipeline_steps;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// src/background_upload/core/pipeline-executor.ts
|
|
122
|
+
var PipelineExecutor = class {
|
|
123
|
+
async execute(job, emitter) {
|
|
124
|
+
const steps = job.get_pipeline_steps();
|
|
125
|
+
const context = job.get_context();
|
|
126
|
+
const handle = {
|
|
127
|
+
job_id: job.job_id,
|
|
128
|
+
set_status: (status) => {
|
|
129
|
+
const previous_status = job.get_snapshot().status;
|
|
130
|
+
job.set_status(status);
|
|
131
|
+
emitter.emit("job:status_changed", { job: job.get_snapshot(), previous_status });
|
|
132
|
+
},
|
|
133
|
+
set_progress: (current, total) => {
|
|
134
|
+
job.set_progress(current, total);
|
|
135
|
+
emitter.emit("job:progress", { job: job.get_snapshot() });
|
|
136
|
+
},
|
|
137
|
+
request_confirmation: async (payload) => {
|
|
138
|
+
const previous_status = job.get_snapshot().status;
|
|
139
|
+
const result_promise = job.request_confirmation(payload);
|
|
140
|
+
emitter.emit("job:confirmation_needed", { job: job.get_snapshot(), payload });
|
|
141
|
+
emitter.emit("job:status_changed", { job: job.get_snapshot(), previous_status });
|
|
142
|
+
const result = await result_promise;
|
|
143
|
+
emitter.emit("job:confirmation_resolved", { job: job.get_snapshot(), result });
|
|
144
|
+
return result;
|
|
145
|
+
},
|
|
146
|
+
is_cancelled: () => job.get_snapshot().status === "error"
|
|
147
|
+
};
|
|
148
|
+
try {
|
|
149
|
+
for (const step of steps) {
|
|
150
|
+
if (handle.is_cancelled()) break;
|
|
151
|
+
await step.execute(context, handle);
|
|
152
|
+
}
|
|
153
|
+
if (!handle.is_cancelled()) {
|
|
154
|
+
const previous_status = job.get_snapshot().status;
|
|
155
|
+
job.set_status("done");
|
|
156
|
+
emitter.emit("job:status_changed", { job: job.get_snapshot(), previous_status });
|
|
157
|
+
emitter.emit("job:completed", { job: job.get_snapshot() });
|
|
158
|
+
}
|
|
159
|
+
} catch (err) {
|
|
160
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
161
|
+
const previous_status = job.get_snapshot().status;
|
|
162
|
+
job.set_error(message);
|
|
163
|
+
job.set_status("error");
|
|
164
|
+
emitter.emit("job:status_changed", { job: job.get_snapshot(), previous_status });
|
|
165
|
+
emitter.emit("job:error", { job: job.get_snapshot(), error: message });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// src/background_upload/core/event-emitter.ts
|
|
171
|
+
var TypedEventEmitter = class {
|
|
172
|
+
constructor() {
|
|
173
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
174
|
+
}
|
|
175
|
+
on(event, listener) {
|
|
176
|
+
let set = this.listeners.get(event);
|
|
177
|
+
if (!set) {
|
|
178
|
+
set = /* @__PURE__ */ new Set();
|
|
179
|
+
this.listeners.set(event, set);
|
|
180
|
+
}
|
|
181
|
+
set.add(listener);
|
|
182
|
+
return () => this.off(event, listener);
|
|
183
|
+
}
|
|
184
|
+
emit(event, data) {
|
|
185
|
+
const set = this.listeners.get(event);
|
|
186
|
+
if (!set) return;
|
|
187
|
+
for (const listener of set) {
|
|
188
|
+
listener(data);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
off(event, listener) {
|
|
192
|
+
this.listeners.get(event)?.delete(listener);
|
|
193
|
+
}
|
|
194
|
+
removeAllListeners() {
|
|
195
|
+
this.listeners.clear();
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// src/background_upload/core/upload-manager.ts
|
|
200
|
+
var UploadManager = class {
|
|
201
|
+
constructor(config) {
|
|
202
|
+
this.jobs = /* @__PURE__ */ new Map();
|
|
203
|
+
this.batches = /* @__PURE__ */ new Map();
|
|
204
|
+
this.executor = new PipelineExecutor();
|
|
205
|
+
this.emitter = new TypedEventEmitter();
|
|
206
|
+
this.queue = [];
|
|
207
|
+
this.running = 0;
|
|
208
|
+
this.destroyed = false;
|
|
209
|
+
this.config = {
|
|
210
|
+
max_concurrent: config?.max_concurrent ?? 1,
|
|
211
|
+
default_pipeline_steps: config?.default_pipeline_steps ?? []
|
|
212
|
+
};
|
|
213
|
+
this.emitter.on("job:completed", ({ job }) => this.on_job_settled(job));
|
|
214
|
+
this.emitter.on("job:error", ({ job }) => this.on_job_settled(job));
|
|
215
|
+
}
|
|
216
|
+
on(event, listener) {
|
|
217
|
+
return this.emitter.on(event, listener);
|
|
218
|
+
}
|
|
219
|
+
submit_batch(options) {
|
|
220
|
+
if (this.destroyed) throw new Error("UploadManager is destroyed");
|
|
221
|
+
const batch_id = crypto.randomUUID();
|
|
222
|
+
const job_ids = [];
|
|
223
|
+
const pipeline_steps = options.pipeline_steps ?? this.config.default_pipeline_steps;
|
|
224
|
+
for (const file of options.files) {
|
|
225
|
+
const job = new Job({
|
|
226
|
+
batch_id,
|
|
227
|
+
files: [file],
|
|
228
|
+
group_id: options.group_id,
|
|
229
|
+
group_label: options.group_label,
|
|
230
|
+
pipeline_steps,
|
|
231
|
+
metadata: options.metadata
|
|
232
|
+
});
|
|
233
|
+
this.jobs.set(job.job_id, job);
|
|
234
|
+
job_ids.push(job.job_id);
|
|
235
|
+
this.emitter.emit("job:created", { job: job.get_snapshot() });
|
|
236
|
+
this.queue.push(job.job_id);
|
|
237
|
+
}
|
|
238
|
+
this.batches.set(batch_id, {
|
|
239
|
+
batch_id,
|
|
240
|
+
job_ids,
|
|
241
|
+
total: options.files.length,
|
|
242
|
+
completed: 0,
|
|
243
|
+
failed: 0,
|
|
244
|
+
emitted_complete: false
|
|
245
|
+
});
|
|
246
|
+
this.process_queue();
|
|
247
|
+
return batch_id;
|
|
248
|
+
}
|
|
249
|
+
get_jobs_for_group(group_id) {
|
|
250
|
+
const out = [];
|
|
251
|
+
for (const job of this.jobs.values()) {
|
|
252
|
+
const snap = job.get_snapshot();
|
|
253
|
+
if (snap.group_id === group_id) out.push(snap);
|
|
254
|
+
}
|
|
255
|
+
return out;
|
|
256
|
+
}
|
|
257
|
+
get_job(job_id) {
|
|
258
|
+
return this.jobs.get(job_id)?.get_snapshot() ?? null;
|
|
259
|
+
}
|
|
260
|
+
get_active_jobs() {
|
|
261
|
+
const out = [];
|
|
262
|
+
for (const job of this.jobs.values()) {
|
|
263
|
+
const snap = job.get_snapshot();
|
|
264
|
+
if (snap.status !== "done" && snap.status !== "error") out.push(snap);
|
|
265
|
+
}
|
|
266
|
+
return out;
|
|
267
|
+
}
|
|
268
|
+
resolve_confirmation(job_id, result) {
|
|
269
|
+
const job = this.jobs.get(job_id);
|
|
270
|
+
if (job) job.resolve_confirmation(result);
|
|
271
|
+
}
|
|
272
|
+
destroy() {
|
|
273
|
+
this.destroyed = true;
|
|
274
|
+
this.emitter.removeAllListeners();
|
|
275
|
+
this.jobs.clear();
|
|
276
|
+
this.batches.clear();
|
|
277
|
+
this.queue = [];
|
|
278
|
+
}
|
|
279
|
+
process_queue() {
|
|
280
|
+
while (!this.destroyed && this.queue.length > 0 && this.running < this.config.max_concurrent) {
|
|
281
|
+
const job_id = this.queue.shift();
|
|
282
|
+
const job = this.jobs.get(job_id);
|
|
283
|
+
if (!job) continue;
|
|
284
|
+
this.running++;
|
|
285
|
+
void this.executor.execute(job, this.emitter).finally(() => {
|
|
286
|
+
this.running--;
|
|
287
|
+
this.process_queue();
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
on_job_settled(job) {
|
|
292
|
+
const batch = this.batches.get(job.batch_id);
|
|
293
|
+
if (!batch) return;
|
|
294
|
+
let completed = 0, failed = 0;
|
|
295
|
+
for (const jid of batch.job_ids) {
|
|
296
|
+
const s = this.jobs.get(jid)?.get_snapshot().status;
|
|
297
|
+
if (s === "done") completed++;
|
|
298
|
+
else if (s === "error") failed++;
|
|
299
|
+
}
|
|
300
|
+
batch.completed = completed;
|
|
301
|
+
batch.failed = failed;
|
|
302
|
+
this.emitter.emit("batch:progress", { batch: { ...batch } });
|
|
303
|
+
if (!batch.emitted_complete && completed + failed === batch.total) {
|
|
304
|
+
batch.emitted_complete = true;
|
|
305
|
+
this.emitter.emit("batch:completed", { batch: { ...batch } });
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
// src/background_upload/react/context.ts
|
|
311
|
+
var import_react = require("react");
|
|
312
|
+
var FileUploadContext = (0, import_react.createContext)(null);
|
|
313
|
+
|
|
314
|
+
// src/background_upload/react/use-file-upload-toasts.ts
|
|
315
|
+
var import_react2 = require("react");
|
|
316
|
+
var toast_promise = null;
|
|
317
|
+
function get_toast() {
|
|
318
|
+
if (!toast_promise) {
|
|
319
|
+
toast_promise = import("sonner").then((mod) => mod.toast).catch(() => null);
|
|
320
|
+
}
|
|
321
|
+
return toast_promise;
|
|
322
|
+
}
|
|
323
|
+
function useFileUploadToasts(manager) {
|
|
324
|
+
(0, import_react2.useEffect)(() => {
|
|
325
|
+
const unsubs = [];
|
|
326
|
+
unsubs.push(manager.on("job:completed", ({ job }) => {
|
|
327
|
+
void get_toast().then((t) => {
|
|
328
|
+
if (!t) return;
|
|
329
|
+
const label = job.group_label || job.group_id;
|
|
330
|
+
const n = job.files.length;
|
|
331
|
+
t.success(`${n} file${n > 1 ? "s" : ""} processed for ${label}`);
|
|
332
|
+
});
|
|
333
|
+
}));
|
|
334
|
+
unsubs.push(manager.on("job:error", ({ job, error }) => {
|
|
335
|
+
void get_toast().then((t) => {
|
|
336
|
+
if (!t) return;
|
|
337
|
+
const label = job.group_label || job.group_id;
|
|
338
|
+
t.error(`Upload failed for ${label}: ${error}`);
|
|
339
|
+
});
|
|
340
|
+
}));
|
|
341
|
+
unsubs.push(manager.on("job:confirmation_needed", ({ job }) => {
|
|
342
|
+
void get_toast().then((t) => {
|
|
343
|
+
if (!t) return;
|
|
344
|
+
const label = job.group_label || job.group_id;
|
|
345
|
+
t.info(`Action required for ${label}`, {
|
|
346
|
+
description: "Review and confirm data conflicts",
|
|
347
|
+
duration: 1e4
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
}));
|
|
351
|
+
unsubs.push(manager.on("batch:completed", ({ batch }) => {
|
|
352
|
+
void get_toast().then((t) => {
|
|
353
|
+
if (!t) return;
|
|
354
|
+
if (batch.failed > 0) {
|
|
355
|
+
t.warning(`Batch complete: ${batch.completed}/${batch.total} succeeded`);
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
}));
|
|
359
|
+
return () => unsubs.forEach((u) => u());
|
|
360
|
+
}, [manager]);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// src/background_upload/react/toast-bridge.tsx
|
|
364
|
+
function ToastBridge({ manager }) {
|
|
365
|
+
useFileUploadToasts(manager);
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// src/background_upload/react/provider.tsx
|
|
370
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
371
|
+
function HazoFileUploadProvider({
|
|
372
|
+
children,
|
|
373
|
+
config,
|
|
374
|
+
enable_toasts = true
|
|
375
|
+
}) {
|
|
376
|
+
const manager_ref = (0, import_react3.useRef)(null);
|
|
377
|
+
if (!manager_ref.current) {
|
|
378
|
+
manager_ref.current = new UploadManager(config);
|
|
379
|
+
}
|
|
380
|
+
(0, import_react3.useEffect)(() => {
|
|
381
|
+
const m = manager_ref.current;
|
|
382
|
+
return () => {
|
|
383
|
+
m.destroy();
|
|
384
|
+
};
|
|
385
|
+
}, []);
|
|
386
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FileUploadContext.Provider, { value: manager_ref.current, children: [
|
|
387
|
+
enable_toasts && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToastBridge, { manager: manager_ref.current }),
|
|
388
|
+
children
|
|
389
|
+
] });
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// src/background_upload/react/use-file-upload.ts
|
|
393
|
+
var import_react4 = require("react");
|
|
394
|
+
var EMPTY_ACTIVE_JOBS = Object.freeze([]);
|
|
395
|
+
function useFileUpload() {
|
|
396
|
+
const manager = (0, import_react4.useContext)(FileUploadContext);
|
|
397
|
+
if (!manager) {
|
|
398
|
+
throw new Error("useFileUpload must be used within HazoFileUploadProvider");
|
|
399
|
+
}
|
|
400
|
+
const snapshot_ref = (0, import_react4.useRef)([]);
|
|
401
|
+
const active_jobs = (0, import_react4.useSyncExternalStore)(
|
|
402
|
+
(callback) => {
|
|
403
|
+
const unsubs = [
|
|
404
|
+
manager.on("job:created", callback),
|
|
405
|
+
manager.on("job:status_changed", callback),
|
|
406
|
+
manager.on("job:progress", callback),
|
|
407
|
+
manager.on("job:completed", callback),
|
|
408
|
+
manager.on("job:error", callback)
|
|
409
|
+
];
|
|
410
|
+
return () => unsubs.forEach((u) => u());
|
|
411
|
+
},
|
|
412
|
+
() => {
|
|
413
|
+
const next = manager.get_active_jobs();
|
|
414
|
+
const prev = snapshot_ref.current;
|
|
415
|
+
if (prev.length === next.length && next.every((j, i) => j.job_id === prev[i]?.job_id && j.updated_at === prev[i]?.updated_at)) {
|
|
416
|
+
return prev;
|
|
417
|
+
}
|
|
418
|
+
snapshot_ref.current = next;
|
|
419
|
+
return next;
|
|
420
|
+
},
|
|
421
|
+
() => EMPTY_ACTIVE_JOBS
|
|
422
|
+
);
|
|
423
|
+
const submit_batch = (0, import_react4.useCallback)(
|
|
424
|
+
(options) => manager.submit_batch(options),
|
|
425
|
+
[manager]
|
|
426
|
+
);
|
|
427
|
+
const get_job = (0, import_react4.useCallback)((id) => manager.get_job(id), [manager]);
|
|
428
|
+
const get_jobs_for_group = (0, import_react4.useCallback)(
|
|
429
|
+
(id) => manager.get_jobs_for_group(id),
|
|
430
|
+
[manager]
|
|
431
|
+
);
|
|
432
|
+
const resolve_confirmation = (0, import_react4.useCallback)(
|
|
433
|
+
(id, r) => manager.resolve_confirmation(id, r),
|
|
434
|
+
[manager]
|
|
435
|
+
);
|
|
436
|
+
return { manager, active_jobs, submit_batch, get_job, get_jobs_for_group, resolve_confirmation };
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// src/background_upload/react/use-job-status.ts
|
|
440
|
+
var import_react5 = require("react");
|
|
441
|
+
function useJobStatus(job_id) {
|
|
442
|
+
const manager = (0, import_react5.useContext)(FileUploadContext);
|
|
443
|
+
return (0, import_react5.useSyncExternalStore)(
|
|
444
|
+
(callback) => {
|
|
445
|
+
if (!manager || !job_id) return () => {
|
|
446
|
+
};
|
|
447
|
+
const unsubs = [
|
|
448
|
+
manager.on("job:status_changed", ({ job }) => {
|
|
449
|
+
if (job.job_id === job_id) callback();
|
|
450
|
+
}),
|
|
451
|
+
manager.on("job:progress", ({ job }) => {
|
|
452
|
+
if (job.job_id === job_id) callback();
|
|
453
|
+
}),
|
|
454
|
+
manager.on("job:completed", ({ job }) => {
|
|
455
|
+
if (job.job_id === job_id) callback();
|
|
456
|
+
}),
|
|
457
|
+
manager.on("job:error", ({ job }) => {
|
|
458
|
+
if (job.job_id === job_id) callback();
|
|
459
|
+
})
|
|
460
|
+
];
|
|
461
|
+
return () => unsubs.forEach((u) => u());
|
|
462
|
+
},
|
|
463
|
+
() => manager && job_id ? manager.get_job(job_id) : null,
|
|
464
|
+
() => null
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
468
|
+
0 && (module.exports = {
|
|
469
|
+
FileUploadContext,
|
|
470
|
+
HazoFileUploadProvider,
|
|
471
|
+
useFileUpload,
|
|
472
|
+
useFileUploadToasts,
|
|
473
|
+
useJobStatus
|
|
474
|
+
});
|