hazo_files 3.2.0 → 3.3.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.
package/CHANGE_LOG.md CHANGED
@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## 3.3.0 — 2026-08-13
9
+
10
+ ### Fixed
11
+
12
+ `HazoFileUploadProvider` handed the live tree a destroyed `UploadManager` after
13
+ a remount. The provider created the manager in a `useRef` and destroyed it in
14
+ its `useEffect` cleanup, but never rebuilt it. Under React StrictMode (dev
15
+ double-mount) or any real remount, the cleanup ran `manager.destroy()`, then the
16
+ re-run setup reused the same destroyed instance — so every `submit_batch` threw
17
+ `UploadManager is destroyed`. The effect now rebuilds the manager when it finds
18
+ a destroyed one and forces a re-render so the context value points at the fresh
19
+ instance.
20
+
21
+ ### Added
22
+
23
+ - `UploadManager.is_destroyed` getter, so consumers (and the provider) can check
24
+ lifecycle state without touching internals.
25
+
26
+
8
27
  ## 3.2.0 — 2026-08-04
9
28
 
10
29
  ### Fixed
@@ -152,6 +152,7 @@ declare class UploadManager {
152
152
  private destroyed;
153
153
  private readonly config;
154
154
  constructor(config?: UploadManagerConfig);
155
+ get is_destroyed(): boolean;
155
156
  on<K extends keyof UploadManagerEvents>(event: K, listener: (data: UploadManagerEvents[K]) => void): () => void;
156
157
  submit_batch(options: CreateBatchOptions): string;
157
158
  get_jobs_for_group(group_id: string): JobSnapshot[];
@@ -152,6 +152,7 @@ declare class UploadManager {
152
152
  private destroyed;
153
153
  private readonly config;
154
154
  constructor(config?: UploadManagerConfig);
155
+ get is_destroyed(): boolean;
155
156
  on<K extends keyof UploadManagerEvents>(event: K, listener: (data: UploadManagerEvents[K]) => void): () => void;
156
157
  submit_batch(options: CreateBatchOptions): string;
157
158
  get_jobs_for_group(group_id: string): JobSnapshot[];
@@ -201,6 +201,9 @@ var UploadManager = class {
201
201
  this.emitter.on("job:completed", ({ job }) => this.on_job_settled(job));
202
202
  this.emitter.on("job:error", ({ job }) => this.on_job_settled(job));
203
203
  }
204
+ get is_destroyed() {
205
+ return this.destroyed;
206
+ }
204
207
  on(event, listener) {
205
208
  return this.emitter.on(event, listener);
206
209
  }
@@ -172,6 +172,9 @@ var UploadManager = class {
172
172
  this.emitter.on("job:completed", ({ job }) => this.on_job_settled(job));
173
173
  this.emitter.on("job:error", ({ job }) => this.on_job_settled(job));
174
174
  }
175
+ get is_destroyed() {
176
+ return this.destroyed;
177
+ }
175
178
  on(event, listener) {
176
179
  return this.emitter.on(event, listener);
177
180
  }
@@ -118,6 +118,7 @@ declare class UploadManager {
118
118
  private destroyed;
119
119
  private readonly config;
120
120
  constructor(config?: UploadManagerConfig);
121
+ get is_destroyed(): boolean;
121
122
  on<K extends keyof UploadManagerEvents>(event: K, listener: (data: UploadManagerEvents[K]) => void): () => void;
122
123
  submit_batch(options: CreateBatchOptions): string;
123
124
  get_jobs_for_group(group_id: string): JobSnapshot[];
@@ -118,6 +118,7 @@ declare class UploadManager {
118
118
  private destroyed;
119
119
  private readonly config;
120
120
  constructor(config?: UploadManagerConfig);
121
+ get is_destroyed(): boolean;
121
122
  on<K extends keyof UploadManagerEvents>(event: K, listener: (data: UploadManagerEvents[K]) => void): () => void;
122
123
  submit_batch(options: CreateBatchOptions): string;
123
124
  get_jobs_for_group(group_id: string): JobSnapshot[];
@@ -217,6 +217,9 @@ var UploadManager = class {
217
217
  this.emitter.on("job:completed", ({ job }) => this.on_job_settled(job));
218
218
  this.emitter.on("job:error", ({ job }) => this.on_job_settled(job));
219
219
  }
220
+ get is_destroyed() {
221
+ return this.destroyed;
222
+ }
220
223
  on(event, listener) {
221
224
  return this.emitter.on(event, listener);
222
225
  }
@@ -381,7 +384,12 @@ function HazoFileUploadProvider({
381
384
  if (!manager_ref.current) {
382
385
  manager_ref.current = new UploadManager(config);
383
386
  }
387
+ const [, force_render] = (0, import_react3.useReducer)((n) => n + 1, 0);
384
388
  (0, import_react3.useEffect)(() => {
389
+ if (manager_ref.current.is_destroyed) {
390
+ manager_ref.current = new UploadManager(config);
391
+ force_render();
392
+ }
385
393
  const m = manager_ref.current;
386
394
  return () => {
387
395
  m.destroy();
@@ -1,5 +1,5 @@
1
1
  // src/background_upload/react/provider.tsx
2
- import { useRef, useEffect as useEffect2 } from "react";
2
+ import { useRef, useReducer, useEffect as useEffect2 } from "react";
3
3
 
4
4
  // src/background_upload/core/upload-manager.ts
5
5
  import { generateRequestId as generateRequestId2 } from "hazo_core";
@@ -177,6 +177,9 @@ var UploadManager = class {
177
177
  this.emitter.on("job:completed", ({ job }) => this.on_job_settled(job));
178
178
  this.emitter.on("job:error", ({ job }) => this.on_job_settled(job));
179
179
  }
180
+ get is_destroyed() {
181
+ return this.destroyed;
182
+ }
180
183
  on(event, listener) {
181
184
  return this.emitter.on(event, listener);
182
185
  }
@@ -341,7 +344,12 @@ function HazoFileUploadProvider({
341
344
  if (!manager_ref.current) {
342
345
  manager_ref.current = new UploadManager(config);
343
346
  }
347
+ const [, force_render] = useReducer((n) => n + 1, 0);
344
348
  useEffect2(() => {
349
+ if (manager_ref.current.is_destroyed) {
350
+ manager_ref.current = new UploadManager(config);
351
+ force_render();
352
+ }
345
353
  const m = manager_ref.current;
346
354
  return () => {
347
355
  m.destroy();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_files",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "File management including integration to cloud files",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -106,7 +106,7 @@
106
106
  "@types/react-dom": "^18.3.0",
107
107
  "dropbox": "^10.34.0",
108
108
  "hazo_core": "^2.0.0",
109
- "hazo_jobs": "^0.17.0",
109
+ "hazo_jobs": "^0.18.0",
110
110
  "hazo_llm_api": "^2.3.0",
111
111
  "jsdom": "^28.1.0",
112
112
  "react": "^18.2.0",
@@ -120,14 +120,14 @@
120
120
  "peerDependencies": {
121
121
  "dropbox": "^10.0.0",
122
122
  "googleapis": "^140.0.0",
123
- "hazo_connect": "^4.0.0",
123
+ "hazo_connect": "^4.0.2",
124
124
  "hazo_core": "^2.0.0",
125
125
  "hazo_debug": "^3.2.0",
126
- "hazo_jobs": "^0.17.0",
126
+ "hazo_jobs": "^0.18.0",
127
127
  "hazo_llm_api": "^2.3.0",
128
- "hazo_logs": "^2.2.0",
129
- "hazo_secure": "^1.7.1",
130
- "hazo_ui": "^6.8.0",
128
+ "hazo_logs": "^2.2.1",
129
+ "hazo_secure": "^1.7.2",
130
+ "hazo_ui": "^6.9.0",
131
131
  "react": "^18.0.0 || ^19.0.0",
132
132
  "react-dom": "^18.0.0 || ^19.0.0",
133
133
  "server-only": "^0.0.1",