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,433 @@
|
|
|
1
|
+
// src/background_upload/react/provider.tsx
|
|
2
|
+
import { useRef, useEffect as useEffect2 } from "react";
|
|
3
|
+
|
|
4
|
+
// src/background_upload/core/job.ts
|
|
5
|
+
var Job = class {
|
|
6
|
+
constructor(init) {
|
|
7
|
+
this.status = "queued";
|
|
8
|
+
this.progress = null;
|
|
9
|
+
this.error = null;
|
|
10
|
+
this.confirmation_payload = null;
|
|
11
|
+
this.confirmation_resolve = null;
|
|
12
|
+
this.job_id = crypto.randomUUID();
|
|
13
|
+
this.batch_id = init.batch_id;
|
|
14
|
+
this.created_at = Date.now();
|
|
15
|
+
this.updated_at = this.created_at;
|
|
16
|
+
this.pipeline_steps = init.pipeline_steps;
|
|
17
|
+
this.context = {
|
|
18
|
+
files: init.files.map((f) => ({
|
|
19
|
+
file: f,
|
|
20
|
+
file_name: f.name,
|
|
21
|
+
mime_type: f.type
|
|
22
|
+
})),
|
|
23
|
+
group_id: init.group_id,
|
|
24
|
+
group_label: init.group_label,
|
|
25
|
+
extracted_data: {},
|
|
26
|
+
metadata: { ...init.metadata ?? {} }
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
get_snapshot() {
|
|
30
|
+
return {
|
|
31
|
+
job_id: this.job_id,
|
|
32
|
+
batch_id: this.batch_id,
|
|
33
|
+
status: this.status,
|
|
34
|
+
group_id: this.context.group_id,
|
|
35
|
+
group_label: this.context.group_label,
|
|
36
|
+
files: [...this.context.files],
|
|
37
|
+
progress: this.progress ? { ...this.progress } : null,
|
|
38
|
+
extracted_data: { ...this.context.extracted_data },
|
|
39
|
+
error: this.error,
|
|
40
|
+
metadata: { ...this.context.metadata },
|
|
41
|
+
confirmation_payload: this.confirmation_payload,
|
|
42
|
+
created_at: this.created_at,
|
|
43
|
+
updated_at: this.updated_at
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
set_status(status) {
|
|
47
|
+
this.status = status;
|
|
48
|
+
this.updated_at = Date.now();
|
|
49
|
+
}
|
|
50
|
+
set_progress(current, total) {
|
|
51
|
+
this.progress = { current, total };
|
|
52
|
+
this.updated_at = Date.now();
|
|
53
|
+
}
|
|
54
|
+
set_error(message) {
|
|
55
|
+
this.error = message;
|
|
56
|
+
this.updated_at = Date.now();
|
|
57
|
+
}
|
|
58
|
+
request_confirmation(payload) {
|
|
59
|
+
this.confirmation_payload = payload;
|
|
60
|
+
this.set_status("awaiting_confirmation");
|
|
61
|
+
return new Promise((resolve) => {
|
|
62
|
+
this.confirmation_resolve = resolve;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
resolve_confirmation(result) {
|
|
66
|
+
if (this.confirmation_resolve) {
|
|
67
|
+
this.confirmation_resolve(result);
|
|
68
|
+
this.confirmation_resolve = null;
|
|
69
|
+
this.confirmation_payload = null;
|
|
70
|
+
this.updated_at = Date.now();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
get_context() {
|
|
74
|
+
return this.context;
|
|
75
|
+
}
|
|
76
|
+
get_pipeline_steps() {
|
|
77
|
+
return this.pipeline_steps;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// src/background_upload/core/pipeline-executor.ts
|
|
82
|
+
var PipelineExecutor = class {
|
|
83
|
+
async execute(job, emitter) {
|
|
84
|
+
const steps = job.get_pipeline_steps();
|
|
85
|
+
const context = job.get_context();
|
|
86
|
+
const handle = {
|
|
87
|
+
job_id: job.job_id,
|
|
88
|
+
set_status: (status) => {
|
|
89
|
+
const previous_status = job.get_snapshot().status;
|
|
90
|
+
job.set_status(status);
|
|
91
|
+
emitter.emit("job:status_changed", { job: job.get_snapshot(), previous_status });
|
|
92
|
+
},
|
|
93
|
+
set_progress: (current, total) => {
|
|
94
|
+
job.set_progress(current, total);
|
|
95
|
+
emitter.emit("job:progress", { job: job.get_snapshot() });
|
|
96
|
+
},
|
|
97
|
+
request_confirmation: async (payload) => {
|
|
98
|
+
const previous_status = job.get_snapshot().status;
|
|
99
|
+
const result_promise = job.request_confirmation(payload);
|
|
100
|
+
emitter.emit("job:confirmation_needed", { job: job.get_snapshot(), payload });
|
|
101
|
+
emitter.emit("job:status_changed", { job: job.get_snapshot(), previous_status });
|
|
102
|
+
const result = await result_promise;
|
|
103
|
+
emitter.emit("job:confirmation_resolved", { job: job.get_snapshot(), result });
|
|
104
|
+
return result;
|
|
105
|
+
},
|
|
106
|
+
is_cancelled: () => job.get_snapshot().status === "error"
|
|
107
|
+
};
|
|
108
|
+
try {
|
|
109
|
+
for (const step of steps) {
|
|
110
|
+
if (handle.is_cancelled()) break;
|
|
111
|
+
await step.execute(context, handle);
|
|
112
|
+
}
|
|
113
|
+
if (!handle.is_cancelled()) {
|
|
114
|
+
const previous_status = job.get_snapshot().status;
|
|
115
|
+
job.set_status("done");
|
|
116
|
+
emitter.emit("job:status_changed", { job: job.get_snapshot(), previous_status });
|
|
117
|
+
emitter.emit("job:completed", { job: job.get_snapshot() });
|
|
118
|
+
}
|
|
119
|
+
} catch (err) {
|
|
120
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
121
|
+
const previous_status = job.get_snapshot().status;
|
|
122
|
+
job.set_error(message);
|
|
123
|
+
job.set_status("error");
|
|
124
|
+
emitter.emit("job:status_changed", { job: job.get_snapshot(), previous_status });
|
|
125
|
+
emitter.emit("job:error", { job: job.get_snapshot(), error: message });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// src/background_upload/core/event-emitter.ts
|
|
131
|
+
var TypedEventEmitter = class {
|
|
132
|
+
constructor() {
|
|
133
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
134
|
+
}
|
|
135
|
+
on(event, listener) {
|
|
136
|
+
let set = this.listeners.get(event);
|
|
137
|
+
if (!set) {
|
|
138
|
+
set = /* @__PURE__ */ new Set();
|
|
139
|
+
this.listeners.set(event, set);
|
|
140
|
+
}
|
|
141
|
+
set.add(listener);
|
|
142
|
+
return () => this.off(event, listener);
|
|
143
|
+
}
|
|
144
|
+
emit(event, data) {
|
|
145
|
+
const set = this.listeners.get(event);
|
|
146
|
+
if (!set) return;
|
|
147
|
+
for (const listener of set) {
|
|
148
|
+
listener(data);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
off(event, listener) {
|
|
152
|
+
this.listeners.get(event)?.delete(listener);
|
|
153
|
+
}
|
|
154
|
+
removeAllListeners() {
|
|
155
|
+
this.listeners.clear();
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// src/background_upload/core/upload-manager.ts
|
|
160
|
+
var UploadManager = class {
|
|
161
|
+
constructor(config) {
|
|
162
|
+
this.jobs = /* @__PURE__ */ new Map();
|
|
163
|
+
this.batches = /* @__PURE__ */ new Map();
|
|
164
|
+
this.executor = new PipelineExecutor();
|
|
165
|
+
this.emitter = new TypedEventEmitter();
|
|
166
|
+
this.queue = [];
|
|
167
|
+
this.running = 0;
|
|
168
|
+
this.destroyed = false;
|
|
169
|
+
this.config = {
|
|
170
|
+
max_concurrent: config?.max_concurrent ?? 1,
|
|
171
|
+
default_pipeline_steps: config?.default_pipeline_steps ?? []
|
|
172
|
+
};
|
|
173
|
+
this.emitter.on("job:completed", ({ job }) => this.on_job_settled(job));
|
|
174
|
+
this.emitter.on("job:error", ({ job }) => this.on_job_settled(job));
|
|
175
|
+
}
|
|
176
|
+
on(event, listener) {
|
|
177
|
+
return this.emitter.on(event, listener);
|
|
178
|
+
}
|
|
179
|
+
submit_batch(options) {
|
|
180
|
+
if (this.destroyed) throw new Error("UploadManager is destroyed");
|
|
181
|
+
const batch_id = crypto.randomUUID();
|
|
182
|
+
const job_ids = [];
|
|
183
|
+
const pipeline_steps = options.pipeline_steps ?? this.config.default_pipeline_steps;
|
|
184
|
+
for (const file of options.files) {
|
|
185
|
+
const job = new Job({
|
|
186
|
+
batch_id,
|
|
187
|
+
files: [file],
|
|
188
|
+
group_id: options.group_id,
|
|
189
|
+
group_label: options.group_label,
|
|
190
|
+
pipeline_steps,
|
|
191
|
+
metadata: options.metadata
|
|
192
|
+
});
|
|
193
|
+
this.jobs.set(job.job_id, job);
|
|
194
|
+
job_ids.push(job.job_id);
|
|
195
|
+
this.emitter.emit("job:created", { job: job.get_snapshot() });
|
|
196
|
+
this.queue.push(job.job_id);
|
|
197
|
+
}
|
|
198
|
+
this.batches.set(batch_id, {
|
|
199
|
+
batch_id,
|
|
200
|
+
job_ids,
|
|
201
|
+
total: options.files.length,
|
|
202
|
+
completed: 0,
|
|
203
|
+
failed: 0,
|
|
204
|
+
emitted_complete: false
|
|
205
|
+
});
|
|
206
|
+
this.process_queue();
|
|
207
|
+
return batch_id;
|
|
208
|
+
}
|
|
209
|
+
get_jobs_for_group(group_id) {
|
|
210
|
+
const out = [];
|
|
211
|
+
for (const job of this.jobs.values()) {
|
|
212
|
+
const snap = job.get_snapshot();
|
|
213
|
+
if (snap.group_id === group_id) out.push(snap);
|
|
214
|
+
}
|
|
215
|
+
return out;
|
|
216
|
+
}
|
|
217
|
+
get_job(job_id) {
|
|
218
|
+
return this.jobs.get(job_id)?.get_snapshot() ?? null;
|
|
219
|
+
}
|
|
220
|
+
get_active_jobs() {
|
|
221
|
+
const out = [];
|
|
222
|
+
for (const job of this.jobs.values()) {
|
|
223
|
+
const snap = job.get_snapshot();
|
|
224
|
+
if (snap.status !== "done" && snap.status !== "error") out.push(snap);
|
|
225
|
+
}
|
|
226
|
+
return out;
|
|
227
|
+
}
|
|
228
|
+
resolve_confirmation(job_id, result) {
|
|
229
|
+
const job = this.jobs.get(job_id);
|
|
230
|
+
if (job) job.resolve_confirmation(result);
|
|
231
|
+
}
|
|
232
|
+
destroy() {
|
|
233
|
+
this.destroyed = true;
|
|
234
|
+
this.emitter.removeAllListeners();
|
|
235
|
+
this.jobs.clear();
|
|
236
|
+
this.batches.clear();
|
|
237
|
+
this.queue = [];
|
|
238
|
+
}
|
|
239
|
+
process_queue() {
|
|
240
|
+
while (!this.destroyed && this.queue.length > 0 && this.running < this.config.max_concurrent) {
|
|
241
|
+
const job_id = this.queue.shift();
|
|
242
|
+
const job = this.jobs.get(job_id);
|
|
243
|
+
if (!job) continue;
|
|
244
|
+
this.running++;
|
|
245
|
+
void this.executor.execute(job, this.emitter).finally(() => {
|
|
246
|
+
this.running--;
|
|
247
|
+
this.process_queue();
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
on_job_settled(job) {
|
|
252
|
+
const batch = this.batches.get(job.batch_id);
|
|
253
|
+
if (!batch) return;
|
|
254
|
+
let completed = 0, failed = 0;
|
|
255
|
+
for (const jid of batch.job_ids) {
|
|
256
|
+
const s = this.jobs.get(jid)?.get_snapshot().status;
|
|
257
|
+
if (s === "done") completed++;
|
|
258
|
+
else if (s === "error") failed++;
|
|
259
|
+
}
|
|
260
|
+
batch.completed = completed;
|
|
261
|
+
batch.failed = failed;
|
|
262
|
+
this.emitter.emit("batch:progress", { batch: { ...batch } });
|
|
263
|
+
if (!batch.emitted_complete && completed + failed === batch.total) {
|
|
264
|
+
batch.emitted_complete = true;
|
|
265
|
+
this.emitter.emit("batch:completed", { batch: { ...batch } });
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// src/background_upload/react/context.ts
|
|
271
|
+
import { createContext } from "react";
|
|
272
|
+
var FileUploadContext = createContext(null);
|
|
273
|
+
|
|
274
|
+
// src/background_upload/react/use-file-upload-toasts.ts
|
|
275
|
+
import { useEffect } from "react";
|
|
276
|
+
var toast_promise = null;
|
|
277
|
+
function get_toast() {
|
|
278
|
+
if (!toast_promise) {
|
|
279
|
+
toast_promise = import("sonner").then((mod) => mod.toast).catch(() => null);
|
|
280
|
+
}
|
|
281
|
+
return toast_promise;
|
|
282
|
+
}
|
|
283
|
+
function useFileUploadToasts(manager) {
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
const unsubs = [];
|
|
286
|
+
unsubs.push(manager.on("job:completed", ({ job }) => {
|
|
287
|
+
void get_toast().then((t) => {
|
|
288
|
+
if (!t) return;
|
|
289
|
+
const label = job.group_label || job.group_id;
|
|
290
|
+
const n = job.files.length;
|
|
291
|
+
t.success(`${n} file${n > 1 ? "s" : ""} processed for ${label}`);
|
|
292
|
+
});
|
|
293
|
+
}));
|
|
294
|
+
unsubs.push(manager.on("job:error", ({ job, error }) => {
|
|
295
|
+
void get_toast().then((t) => {
|
|
296
|
+
if (!t) return;
|
|
297
|
+
const label = job.group_label || job.group_id;
|
|
298
|
+
t.error(`Upload failed for ${label}: ${error}`);
|
|
299
|
+
});
|
|
300
|
+
}));
|
|
301
|
+
unsubs.push(manager.on("job:confirmation_needed", ({ job }) => {
|
|
302
|
+
void get_toast().then((t) => {
|
|
303
|
+
if (!t) return;
|
|
304
|
+
const label = job.group_label || job.group_id;
|
|
305
|
+
t.info(`Action required for ${label}`, {
|
|
306
|
+
description: "Review and confirm data conflicts",
|
|
307
|
+
duration: 1e4
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
}));
|
|
311
|
+
unsubs.push(manager.on("batch:completed", ({ batch }) => {
|
|
312
|
+
void get_toast().then((t) => {
|
|
313
|
+
if (!t) return;
|
|
314
|
+
if (batch.failed > 0) {
|
|
315
|
+
t.warning(`Batch complete: ${batch.completed}/${batch.total} succeeded`);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
}));
|
|
319
|
+
return () => unsubs.forEach((u) => u());
|
|
320
|
+
}, [manager]);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// src/background_upload/react/toast-bridge.tsx
|
|
324
|
+
function ToastBridge({ manager }) {
|
|
325
|
+
useFileUploadToasts(manager);
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/background_upload/react/provider.tsx
|
|
330
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
331
|
+
function HazoFileUploadProvider({
|
|
332
|
+
children,
|
|
333
|
+
config,
|
|
334
|
+
enable_toasts = true
|
|
335
|
+
}) {
|
|
336
|
+
const manager_ref = useRef(null);
|
|
337
|
+
if (!manager_ref.current) {
|
|
338
|
+
manager_ref.current = new UploadManager(config);
|
|
339
|
+
}
|
|
340
|
+
useEffect2(() => {
|
|
341
|
+
const m = manager_ref.current;
|
|
342
|
+
return () => {
|
|
343
|
+
m.destroy();
|
|
344
|
+
};
|
|
345
|
+
}, []);
|
|
346
|
+
return /* @__PURE__ */ jsxs(FileUploadContext.Provider, { value: manager_ref.current, children: [
|
|
347
|
+
enable_toasts && /* @__PURE__ */ jsx(ToastBridge, { manager: manager_ref.current }),
|
|
348
|
+
children
|
|
349
|
+
] });
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// src/background_upload/react/use-file-upload.ts
|
|
353
|
+
import { useContext, useCallback, useRef as useRef2, useSyncExternalStore } from "react";
|
|
354
|
+
var EMPTY_ACTIVE_JOBS = Object.freeze([]);
|
|
355
|
+
function useFileUpload() {
|
|
356
|
+
const manager = useContext(FileUploadContext);
|
|
357
|
+
if (!manager) {
|
|
358
|
+
throw new Error("useFileUpload must be used within HazoFileUploadProvider");
|
|
359
|
+
}
|
|
360
|
+
const snapshot_ref = useRef2([]);
|
|
361
|
+
const active_jobs = useSyncExternalStore(
|
|
362
|
+
(callback) => {
|
|
363
|
+
const unsubs = [
|
|
364
|
+
manager.on("job:created", callback),
|
|
365
|
+
manager.on("job:status_changed", callback),
|
|
366
|
+
manager.on("job:progress", callback),
|
|
367
|
+
manager.on("job:completed", callback),
|
|
368
|
+
manager.on("job:error", callback)
|
|
369
|
+
];
|
|
370
|
+
return () => unsubs.forEach((u) => u());
|
|
371
|
+
},
|
|
372
|
+
() => {
|
|
373
|
+
const next = manager.get_active_jobs();
|
|
374
|
+
const prev = snapshot_ref.current;
|
|
375
|
+
if (prev.length === next.length && next.every((j, i) => j.job_id === prev[i]?.job_id && j.updated_at === prev[i]?.updated_at)) {
|
|
376
|
+
return prev;
|
|
377
|
+
}
|
|
378
|
+
snapshot_ref.current = next;
|
|
379
|
+
return next;
|
|
380
|
+
},
|
|
381
|
+
() => EMPTY_ACTIVE_JOBS
|
|
382
|
+
);
|
|
383
|
+
const submit_batch = useCallback(
|
|
384
|
+
(options) => manager.submit_batch(options),
|
|
385
|
+
[manager]
|
|
386
|
+
);
|
|
387
|
+
const get_job = useCallback((id) => manager.get_job(id), [manager]);
|
|
388
|
+
const get_jobs_for_group = useCallback(
|
|
389
|
+
(id) => manager.get_jobs_for_group(id),
|
|
390
|
+
[manager]
|
|
391
|
+
);
|
|
392
|
+
const resolve_confirmation = useCallback(
|
|
393
|
+
(id, r) => manager.resolve_confirmation(id, r),
|
|
394
|
+
[manager]
|
|
395
|
+
);
|
|
396
|
+
return { manager, active_jobs, submit_batch, get_job, get_jobs_for_group, resolve_confirmation };
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// src/background_upload/react/use-job-status.ts
|
|
400
|
+
import { useContext as useContext2, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
401
|
+
function useJobStatus(job_id) {
|
|
402
|
+
const manager = useContext2(FileUploadContext);
|
|
403
|
+
return useSyncExternalStore2(
|
|
404
|
+
(callback) => {
|
|
405
|
+
if (!manager || !job_id) return () => {
|
|
406
|
+
};
|
|
407
|
+
const unsubs = [
|
|
408
|
+
manager.on("job:status_changed", ({ job }) => {
|
|
409
|
+
if (job.job_id === job_id) callback();
|
|
410
|
+
}),
|
|
411
|
+
manager.on("job:progress", ({ job }) => {
|
|
412
|
+
if (job.job_id === job_id) callback();
|
|
413
|
+
}),
|
|
414
|
+
manager.on("job:completed", ({ job }) => {
|
|
415
|
+
if (job.job_id === job_id) callback();
|
|
416
|
+
}),
|
|
417
|
+
manager.on("job:error", ({ job }) => {
|
|
418
|
+
if (job.job_id === job_id) callback();
|
|
419
|
+
})
|
|
420
|
+
];
|
|
421
|
+
return () => unsubs.forEach((u) => u());
|
|
422
|
+
},
|
|
423
|
+
() => manager && job_id ? manager.get_job(job_id) : null,
|
|
424
|
+
() => null
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
export {
|
|
428
|
+
FileUploadContext,
|
|
429
|
+
HazoFileUploadProvider,
|
|
430
|
+
useFileUpload,
|
|
431
|
+
useFileUploadToasts,
|
|
432
|
+
useJobStatus
|
|
433
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hazo_files",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"description": "File management including integration to cloud files",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -20,6 +20,16 @@
|
|
|
20
20
|
"types": "./dist/server/index.d.ts",
|
|
21
21
|
"import": "./dist/server/index.mjs",
|
|
22
22
|
"require": "./dist/server/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./background-upload": {
|
|
25
|
+
"types": "./dist/background-upload/index.d.ts",
|
|
26
|
+
"import": "./dist/background-upload/index.mjs",
|
|
27
|
+
"require": "./dist/background-upload/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./background-upload/react": {
|
|
30
|
+
"types": "./dist/background-upload/react/index.d.ts",
|
|
31
|
+
"import": "./dist/background-upload/react/index.mjs",
|
|
32
|
+
"require": "./dist/background-upload/react/index.js"
|
|
23
33
|
}
|
|
24
34
|
},
|
|
25
35
|
"files": [
|
|
@@ -28,6 +38,8 @@
|
|
|
28
38
|
"config",
|
|
29
39
|
"migrations",
|
|
30
40
|
"README.md",
|
|
41
|
+
"SETUP_CHECKLIST.md",
|
|
42
|
+
"CHANGE_LOG.md",
|
|
31
43
|
".env.example"
|
|
32
44
|
],
|
|
33
45
|
"engines": {
|
|
@@ -35,10 +47,12 @@
|
|
|
35
47
|
},
|
|
36
48
|
"sideEffects": false,
|
|
37
49
|
"scripts": {
|
|
38
|
-
"build": "npm run build:main && npm run build:ui && npm run build:server",
|
|
50
|
+
"build": "npm run build:main && npm run build:ui && npm run build:server && npm run build:bg-upload && npm run build:bg-upload-react",
|
|
39
51
|
"build:main": "tsup src/index.ts --dts --format cjs,esm --clean",
|
|
40
52
|
"build:ui": "tsup src/ui/index.ts --outDir dist/ui --dts --format cjs,esm --no-clean --external react --external react-dom --external @dnd-kit/core --external @dnd-kit/sortable --external @dnd-kit/utilities",
|
|
41
53
|
"build:server": "tsup src/server/index.ts --outDir dist/server --dts --format cjs,esm --no-clean",
|
|
54
|
+
"build:bg-upload": "tsup src/background_upload/index.ts --outDir dist/background-upload --dts --format cjs,esm --no-clean",
|
|
55
|
+
"build:bg-upload-react": "tsup src/background_upload/react/index.ts --outDir dist/background-upload/react --dts --format cjs,esm --no-clean --external react --external react-dom --external sonner",
|
|
42
56
|
"dev": "tsup --watch",
|
|
43
57
|
"test": "vitest",
|
|
44
58
|
"lint": "eslint src/",
|
|
@@ -72,6 +86,8 @@
|
|
|
72
86
|
"@dnd-kit/core": "^6.3.1",
|
|
73
87
|
"@dnd-kit/sortable": "^10.0.0",
|
|
74
88
|
"@dnd-kit/utilities": "^3.2.2",
|
|
89
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
90
|
+
"@testing-library/react": "^14.3.1",
|
|
75
91
|
"@types/ini": "^4.1.1",
|
|
76
92
|
"@types/node": "^20.14.10",
|
|
77
93
|
"@types/react": "^18.3.3",
|
|
@@ -79,11 +95,13 @@
|
|
|
79
95
|
"dropbox": "^10.34.0",
|
|
80
96
|
"googleapis": "^140.0.1",
|
|
81
97
|
"hazo_llm_api": "^1.2.7",
|
|
98
|
+
"jsdom": "^28.1.0",
|
|
82
99
|
"react": "^18.2.0",
|
|
83
100
|
"react-dom": "^18.2.0",
|
|
101
|
+
"sonner": "^2.0.7",
|
|
84
102
|
"tsup": "^8.0.1",
|
|
85
103
|
"typescript": "^5.7.2",
|
|
86
|
-
"vitest": "^4.
|
|
104
|
+
"vitest": "^4.1.6",
|
|
87
105
|
"xxhash-wasm": "^1.1.0"
|
|
88
106
|
},
|
|
89
107
|
"peerDependencies": {
|
|
@@ -92,13 +110,14 @@
|
|
|
92
110
|
"@dnd-kit/utilities": "^3.0.0",
|
|
93
111
|
"dropbox": "^10.0.0",
|
|
94
112
|
"googleapis": "^140.0.0",
|
|
95
|
-
"hazo_connect": "^2.
|
|
113
|
+
"hazo_connect": "^2.6.0",
|
|
96
114
|
"hazo_debug": "^2.0.0",
|
|
97
115
|
"hazo_llm_api": "^1.2.0",
|
|
98
116
|
"hazo_logs": "^1.0.13",
|
|
99
117
|
"react": "^18.0.0",
|
|
100
118
|
"react-dom": "^18.0.0",
|
|
101
119
|
"server-only": ">=0.0.1",
|
|
120
|
+
"sonner": ">=1.0.0",
|
|
102
121
|
"xxhash-wasm": "^1.0.0"
|
|
103
122
|
},
|
|
104
123
|
"peerDependenciesMeta": {
|
|
@@ -132,6 +151,9 @@
|
|
|
132
151
|
"server-only": {
|
|
133
152
|
"optional": true
|
|
134
153
|
},
|
|
154
|
+
"sonner": {
|
|
155
|
+
"optional": true
|
|
156
|
+
},
|
|
135
157
|
"xxhash-wasm": {
|
|
136
158
|
"optional": true
|
|
137
159
|
}
|