@vef-framework-react/core 2.3.0 → 2.4.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/dist/cjs/api/client.cjs +1 -1
- package/dist/cjs/api/constants.cjs +1 -1
- package/dist/cjs/api/helpers.cjs +1 -1
- package/dist/cjs/api/index.cjs +1 -1
- package/dist/cjs/auth/helpers.cjs +1 -1
- package/dist/cjs/auth/index.cjs +1 -1
- package/dist/cjs/context/api-client.cjs +1 -1
- package/dist/cjs/context/app.cjs +1 -1
- package/dist/cjs/context/context-selector.cjs +1 -1
- package/dist/cjs/context/disabled.cjs +1 -1
- package/dist/cjs/context/index.cjs +1 -1
- package/dist/cjs/dnd/index.cjs +1 -1
- package/dist/cjs/http/client.cjs +1 -1
- package/dist/cjs/http/helpers.cjs +1 -1
- package/dist/cjs/http/index.cjs +1 -1
- package/dist/cjs/immer/index.cjs +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/motion/features.cjs +1 -1
- package/dist/cjs/motion/index.cjs +1 -1
- package/dist/cjs/motion/motion-provider.cjs +1 -1
- package/dist/cjs/query/helpers.cjs +1 -1
- package/dist/cjs/query/hooks.cjs +1 -1
- package/dist/cjs/query/index.cjs +1 -1
- package/dist/cjs/sse/client.cjs +1 -1
- package/dist/cjs/sse/helpers.cjs +1 -1
- package/dist/cjs/sse/index.cjs +1 -1
- package/dist/cjs/sse/stream-machine.cjs +1 -0
- package/dist/cjs/state/index.cjs +1 -1
- package/dist/cjs/state-machine/index.cjs +1 -1
- package/dist/cjs/storage/index.cjs +1 -1
- package/dist/cjs/storage/protocol.cjs +1 -1
- package/dist/cjs/storage/resumable/index.cjs +1 -1
- package/dist/cjs/storage/resumable/plan.cjs +1 -1
- package/dist/cjs/storage/uploader-machine.cjs +1 -0
- package/dist/cjs/storage/uploader.cjs +1 -1
- package/dist/cjs/store/bound.cjs +1 -1
- package/dist/cjs/store/index.cjs +1 -1
- package/dist/cjs/store/unbound.cjs +1 -1
- package/dist/cjs/store/use-deep.cjs +1 -1
- package/dist/es/api/client.js +1 -1
- package/dist/es/api/constants.js +1 -1
- package/dist/es/api/helpers.js +1 -1
- package/dist/es/api/index.js +1 -1
- package/dist/es/auth/helpers.js +1 -1
- package/dist/es/auth/index.js +1 -1
- package/dist/es/context/api-client.js +1 -1
- package/dist/es/context/app.js +1 -1
- package/dist/es/context/context-selector.js +1 -1
- package/dist/es/context/disabled.js +1 -1
- package/dist/es/context/index.js +1 -1
- package/dist/es/dnd/index.js +11 -10
- package/dist/es/http/client.js +1 -1
- package/dist/es/http/constants.js +1 -1
- package/dist/es/http/errors.js +1 -1
- package/dist/es/http/helpers.js +1 -1
- package/dist/es/http/index.js +1 -1
- package/dist/es/immer/index.js +1 -1
- package/dist/es/index.js +22 -22
- package/dist/es/motion/features.js +1 -1
- package/dist/es/motion/index.js +1 -1
- package/dist/es/motion/motion-provider.js +1 -1
- package/dist/es/query/constants.js +1 -1
- package/dist/es/query/helpers.js +1 -1
- package/dist/es/query/hooks.js +1 -1
- package/dist/es/query/index.js +1 -1
- package/dist/es/sse/client.js +61 -55
- package/dist/es/sse/helpers.js +1 -1
- package/dist/es/sse/index.js +1 -1
- package/dist/es/sse/stream-machine.js +102 -0
- package/dist/es/state/index.js +1 -1
- package/dist/es/state-machine/index.js +9 -9
- package/dist/es/storage/errors.js +1 -1
- package/dist/es/storage/index.js +1 -1
- package/dist/es/storage/protocol.js +1 -1
- package/dist/es/storage/resumable/fingerprint.js +1 -1
- package/dist/es/storage/resumable/index.js +1 -1
- package/dist/es/storage/resumable/persistence.js +1 -1
- package/dist/es/storage/resumable/plan.js +1 -1
- package/dist/es/storage/types.js +1 -1
- package/dist/es/storage/uploader-machine.js +88 -0
- package/dist/es/storage/uploader.js +135 -89
- package/dist/es/store/bound.js +1 -1
- package/dist/es/store/index.js +1 -1
- package/dist/es/store/unbound.js +1 -1
- package/dist/es/store/use-deep.js +1 -1
- package/dist/types/{dnd → src/dnd}/index.d.ts +3 -2
- package/dist/types/{index.d.ts → src/index.d.ts} +1 -1
- package/dist/types/{query → src/query}/hooks.d.ts +1 -1
- package/dist/types/src/sse/client.d.ts +24 -0
- package/dist/types/src/sse/stream-machine.d.ts +104 -0
- package/dist/types/src/storage/uploader-machine.d.ts +108 -0
- package/dist/types/{storage → src/storage}/uploader.d.ts +8 -2
- package/package.json +8 -8
- package/dist/types/sse/client.d.ts +0 -16
- /package/dist/types/{api → src/api}/client.d.ts +0 -0
- /package/dist/types/{api → src/api}/constants.d.ts +0 -0
- /package/dist/types/{api → src/api}/helpers.d.ts +0 -0
- /package/dist/types/{api → src/api}/index.d.ts +0 -0
- /package/dist/types/{api → src/api}/types.d.ts +0 -0
- /package/dist/types/{auth → src/auth}/helpers.d.ts +0 -0
- /package/dist/types/{auth → src/auth}/index.d.ts +0 -0
- /package/dist/types/{auth → src/auth}/types.d.ts +0 -0
- /package/dist/types/{common → src/common}/index.d.ts +0 -0
- /package/dist/types/{common → src/common}/types.d.ts +0 -0
- /package/dist/types/{context → src/context}/api-client.d.ts +0 -0
- /package/dist/types/{context → src/context}/app.d.ts +0 -0
- /package/dist/types/{context → src/context}/context-selector.d.ts +0 -0
- /package/dist/types/{context → src/context}/disabled.d.ts +0 -0
- /package/dist/types/{context → src/context}/index.d.ts +0 -0
- /package/dist/types/{context → src/context}/types.d.ts +0 -0
- /package/dist/types/{http → src/http}/client.d.ts +0 -0
- /package/dist/types/{http → src/http}/constants.d.ts +0 -0
- /package/dist/types/{http → src/http}/errors.d.ts +0 -0
- /package/dist/types/{http → src/http}/helpers.d.ts +0 -0
- /package/dist/types/{http → src/http}/index.d.ts +0 -0
- /package/dist/types/{http → src/http}/types.d.ts +0 -0
- /package/dist/types/{immer → src/immer}/index.d.ts +0 -0
- /package/dist/types/{motion → src/motion}/features.d.ts +0 -0
- /package/dist/types/{motion → src/motion}/index.d.ts +0 -0
- /package/dist/types/{motion → src/motion}/motion-provider.d.ts +0 -0
- /package/dist/types/{query → src/query}/constants.d.ts +0 -0
- /package/dist/types/{query → src/query}/helpers.d.ts +0 -0
- /package/dist/types/{query → src/query}/index.d.ts +0 -0
- /package/dist/types/{query → src/query}/types.d.ts +0 -0
- /package/dist/types/{sse → src/sse}/helpers.d.ts +0 -0
- /package/dist/types/{sse → src/sse}/index.d.ts +0 -0
- /package/dist/types/{sse → src/sse}/types.d.ts +0 -0
- /package/dist/types/{state → src/state}/index.d.ts +0 -0
- /package/dist/types/{state-machine → src/state-machine}/index.d.ts +0 -0
- /package/dist/types/{storage → src/storage}/errors.d.ts +0 -0
- /package/dist/types/{storage → src/storage}/index.d.ts +0 -0
- /package/dist/types/{storage → src/storage}/protocol.d.ts +0 -0
- /package/dist/types/{storage → src/storage}/resumable/fingerprint.d.ts +0 -0
- /package/dist/types/{storage → src/storage}/resumable/index.d.ts +0 -0
- /package/dist/types/{storage → src/storage}/resumable/persistence.d.ts +0 -0
- /package/dist/types/{storage → src/storage}/resumable/plan.d.ts +0 -0
- /package/dist/types/{storage → src/storage}/types.d.ts +0 -0
- /package/dist/types/{store → src/store}/bound.d.ts +0 -0
- /package/dist/types/{store → src/store}/index.d.ts +0 -0
- /package/dist/types/{store → src/store}/types.d.ts +0 -0
- /package/dist/types/{store → src/store}/unbound.d.ts +0 -0
- /package/dist/types/{store → src/store}/use-deep.d.ts +0 -0
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
/*! @vef-framework-react/core v2.
|
|
1
|
+
/*! @vef-framework-react/core v2.4.0 made by Venus | 2026-06-15T15:10:07.347Z */
|
|
2
2
|
import { UploadAbortedError as e, UploadError as t, UploadPartError as n, UploadProtocolError as r } from "./errors.js";
|
|
3
3
|
import { abortUpload as i, completeUpload as a, initUpload as o, uploadPart as s } from "./protocol.js";
|
|
4
|
+
import { createUploaderMachine as c } from "./uploader-machine.js";
|
|
5
|
+
import { createActor as l } from "xstate";
|
|
4
6
|
//#region src/storage/uploader.ts
|
|
5
|
-
var
|
|
6
|
-
function
|
|
7
|
+
var u = 3, d = 3, f = 500, p = 8e3;
|
|
8
|
+
function m(e, t, n, r) {
|
|
7
9
|
return n < r ? t : e - t * (r - 1);
|
|
8
10
|
}
|
|
9
|
-
function
|
|
11
|
+
function h(t, n) {
|
|
10
12
|
return new Promise((r, i) => {
|
|
11
13
|
if (n.aborted) {
|
|
12
14
|
i(new e());
|
|
@@ -20,7 +22,7 @@ function p(t, n) {
|
|
|
20
22
|
n.addEventListener("abort", o, { once: !0 });
|
|
21
23
|
});
|
|
22
24
|
}
|
|
23
|
-
var
|
|
25
|
+
var g = class {
|
|
24
26
|
#e;
|
|
25
27
|
#t;
|
|
26
28
|
#n;
|
|
@@ -35,13 +37,18 @@ var m = class {
|
|
|
35
37
|
#d;
|
|
36
38
|
#f;
|
|
37
39
|
#p;
|
|
38
|
-
#m
|
|
39
|
-
#h;
|
|
40
|
+
#m;
|
|
41
|
+
#h = "idle";
|
|
40
42
|
#g;
|
|
41
|
-
#_
|
|
42
|
-
#v
|
|
43
|
-
#y
|
|
44
|
-
#b
|
|
43
|
+
#_;
|
|
44
|
+
#v;
|
|
45
|
+
#y;
|
|
46
|
+
#b;
|
|
47
|
+
#x;
|
|
48
|
+
#S = 0;
|
|
49
|
+
#C = /* @__PURE__ */ new Map();
|
|
50
|
+
#w = 1;
|
|
51
|
+
#T = /* @__PURE__ */ new Set();
|
|
45
52
|
constructor(e, n, r = {}) {
|
|
46
53
|
let i = r.init?.filename ?? (n instanceof File ? n.name : "");
|
|
47
54
|
if (!i) throw new t("Uploader requires a filename (set options.init.filename for Blob input)");
|
|
@@ -50,57 +57,114 @@ var m = class {
|
|
|
50
57
|
apiPath: r.apiPath ?? "/api",
|
|
51
58
|
resource: r.resource ?? "sys/storage",
|
|
52
59
|
version: r.version ?? "v1"
|
|
53
|
-
}, this.#t = n, this.#n = i, this.#r = r.init?.contentType ?? (n instanceof File && n.type || void 0), this.#i = r.init?.public, this.#a = Math.max(1, r.partConcurrency ??
|
|
60
|
+
}, this.#t = n, this.#n = i, this.#r = r.init?.contentType ?? (n instanceof File && n.type || void 0), this.#i = r.init?.public, this.#a = Math.max(1, r.partConcurrency ?? u), this.#o = Math.max(1, r.maxPartRetries ?? d), this.#s = Math.max(0, r.retryBaseDelay ?? f), this.#c = Math.max(this.#s, r.retryMaxDelay ?? p), this.#l = r.onProgress, this.#u = r.onStatusChange, this.#d = r.onSessionOpened, this.#f = new AbortController(), this.#p = this.#D(r.signal), this.#g = {
|
|
54
61
|
loaded: 0,
|
|
55
62
|
total: n.size,
|
|
56
63
|
partsCompleted: 0,
|
|
57
64
|
partsTotal: 0,
|
|
58
65
|
percent: 0
|
|
59
|
-
}
|
|
66
|
+
}, this.#m = l(c({
|
|
67
|
+
prepareSession: (e) => this.#N(e),
|
|
68
|
+
uploadParts: () => this.#L(this.#A()),
|
|
69
|
+
completeSession: () => this.#F(),
|
|
70
|
+
abortSession: () => this.#I(),
|
|
71
|
+
killTransport: () => {
|
|
72
|
+
this.#f.abort();
|
|
73
|
+
},
|
|
74
|
+
recordFailure: (e) => {
|
|
75
|
+
this.#b = e;
|
|
76
|
+
},
|
|
77
|
+
abortRequested: () => this.#f.signal.aborted
|
|
78
|
+
})), this.#m.subscribe((e) => {
|
|
79
|
+
this.#O(e.value), e.status === "done" && this.#k(e.value);
|
|
80
|
+
}), this.#m.start();
|
|
60
81
|
}
|
|
61
82
|
get status() {
|
|
62
|
-
return this.#
|
|
83
|
+
return this.#h;
|
|
63
84
|
}
|
|
64
85
|
get progress() {
|
|
65
|
-
return this.#
|
|
86
|
+
return this.#g;
|
|
66
87
|
}
|
|
67
88
|
start(e) {
|
|
68
|
-
return this.#
|
|
89
|
+
return this.#_ ? this.#_ : (this.#_ = new Promise((e, t) => {
|
|
90
|
+
this.#v = {
|
|
91
|
+
resolve: e,
|
|
92
|
+
reject: t
|
|
93
|
+
};
|
|
94
|
+
}), this.#m.send({
|
|
95
|
+
type: "START",
|
|
96
|
+
plan: e ?? { kind: "fresh" }
|
|
97
|
+
}), this.#_);
|
|
69
98
|
}
|
|
70
99
|
async abort() {
|
|
71
|
-
if (this.#
|
|
72
|
-
this.#
|
|
73
|
-
let e = this.#
|
|
100
|
+
if (this.#m.getSnapshot().status === "done") return;
|
|
101
|
+
this.#E();
|
|
102
|
+
let e = this.#_;
|
|
74
103
|
if (e) try {
|
|
75
104
|
await e;
|
|
76
105
|
} catch {}
|
|
77
106
|
}
|
|
78
|
-
#
|
|
107
|
+
#E() {
|
|
108
|
+
this.#m.send({ type: "ABORT" }), this.#f.abort();
|
|
109
|
+
}
|
|
110
|
+
#D(e) {
|
|
79
111
|
if (!e) return;
|
|
80
112
|
if (e.aborted) {
|
|
81
113
|
this.#f.abort();
|
|
82
114
|
return;
|
|
83
115
|
}
|
|
84
|
-
let t = () => this.#
|
|
116
|
+
let t = () => this.#E();
|
|
85
117
|
return e.addEventListener("abort", t, { once: !0 }), () => e.removeEventListener("abort", t);
|
|
86
118
|
}
|
|
87
|
-
#
|
|
88
|
-
|
|
119
|
+
#O(e) {
|
|
120
|
+
this.#h !== e && (this.#h = e, this.#u?.(e));
|
|
121
|
+
}
|
|
122
|
+
#k(t) {
|
|
123
|
+
this.#p?.();
|
|
124
|
+
let n = this.#v;
|
|
125
|
+
if (n) switch (t) {
|
|
126
|
+
case "succeeded":
|
|
127
|
+
n.resolve(this.#j());
|
|
128
|
+
return;
|
|
129
|
+
case "aborted":
|
|
130
|
+
n.reject(new e());
|
|
131
|
+
return;
|
|
132
|
+
default: n.reject(this.#V(this.#b));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
#A() {
|
|
136
|
+
if (!this.#y) throw new t("upload session is not open");
|
|
137
|
+
return this.#y;
|
|
89
138
|
}
|
|
90
|
-
#
|
|
91
|
-
this.#
|
|
139
|
+
#j() {
|
|
140
|
+
if (!this.#x) throw new t("upload result missing after completion");
|
|
141
|
+
return this.#x;
|
|
92
142
|
}
|
|
93
|
-
#
|
|
143
|
+
#M() {
|
|
94
144
|
let e = 0;
|
|
95
|
-
for (let t of this.#
|
|
96
|
-
let t = Math.min(this.#
|
|
97
|
-
this.#
|
|
98
|
-
...this.#
|
|
145
|
+
for (let t of this.#C.values()) e += t;
|
|
146
|
+
let t = Math.min(this.#g.total, this.#S + e), n = this.#g.total === 0 ? 0 : Math.floor(t / this.#g.total * 100);
|
|
147
|
+
this.#g = {
|
|
148
|
+
...this.#g,
|
|
99
149
|
loaded: t,
|
|
100
150
|
percent: n
|
|
101
|
-
}, this.#l?.(this.#
|
|
151
|
+
}, this.#l?.(this.#g);
|
|
102
152
|
}
|
|
103
|
-
async #
|
|
153
|
+
async #N(e) {
|
|
154
|
+
let { session: t, skipParts: n, completedBytes: r } = await this.#P(e);
|
|
155
|
+
this.#y = t, this.#T = n, this.#S = r, this.#d?.({
|
|
156
|
+
claimId: t.claimId,
|
|
157
|
+
key: t.key,
|
|
158
|
+
partSize: t.partSize,
|
|
159
|
+
partCount: t.partCount,
|
|
160
|
+
expiresAt: t.expiresAt
|
|
161
|
+
}), this.#g = {
|
|
162
|
+
...this.#g,
|
|
163
|
+
partsTotal: t.partCount,
|
|
164
|
+
partsCompleted: n.size
|
|
165
|
+
}, this.#M();
|
|
166
|
+
}
|
|
167
|
+
async #P(e) {
|
|
104
168
|
if (e.kind === "fresh") return {
|
|
105
169
|
session: await o(this.#e, {
|
|
106
170
|
filename: this.#n,
|
|
@@ -128,96 +192,78 @@ var m = class {
|
|
|
128
192
|
completedBytes: a
|
|
129
193
|
};
|
|
130
194
|
}
|
|
131
|
-
async #
|
|
132
|
-
let
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}, this.#w(), this.#C("uploading"), await this.#D(r), this.#C("completing");
|
|
148
|
-
let s = await a(this.#e, r.claimId, this.#f.signal);
|
|
149
|
-
return this.#C("succeeded"), {
|
|
150
|
-
bucket: s.bucket,
|
|
151
|
-
key: s.key,
|
|
152
|
-
eTag: s.eTag,
|
|
153
|
-
size: s.size,
|
|
154
|
-
contentType: s.contentType,
|
|
155
|
-
lastModified: s.lastModified,
|
|
156
|
-
originalFilename: s.originalFilename,
|
|
157
|
-
metadata: s.metadata
|
|
158
|
-
};
|
|
159
|
-
} catch (t) {
|
|
160
|
-
let r = t instanceof e;
|
|
161
|
-
throw r && this.#C("aborting"), r && n !== void 0 && await i(this.#e, n), this.#C(r ? "aborted" : "failed"), this.#j(t);
|
|
162
|
-
} finally {
|
|
163
|
-
this.#p?.();
|
|
164
|
-
}
|
|
195
|
+
async #F() {
|
|
196
|
+
let e = this.#A(), t = await a(this.#e, e.claimId, this.#f.signal);
|
|
197
|
+
this.#x = {
|
|
198
|
+
bucket: t.bucket,
|
|
199
|
+
key: t.key,
|
|
200
|
+
eTag: t.eTag,
|
|
201
|
+
size: t.size,
|
|
202
|
+
contentType: t.contentType,
|
|
203
|
+
lastModified: t.lastModified,
|
|
204
|
+
originalFilename: t.originalFilename,
|
|
205
|
+
metadata: t.metadata
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
async #I() {
|
|
209
|
+
let e = this.#y?.claimId;
|
|
210
|
+
e !== void 0 && await i(this.#e, e);
|
|
165
211
|
}
|
|
166
|
-
async #
|
|
212
|
+
async #L(e) {
|
|
167
213
|
let t = Math.min(this.#a, e.partCount), n = [];
|
|
168
|
-
for (let r = 0; r < t; r++) n.push(this.#
|
|
214
|
+
for (let r = 0; r < t; r++) n.push(this.#R(e));
|
|
169
215
|
try {
|
|
170
216
|
await Promise.all(n);
|
|
171
217
|
} catch (e) {
|
|
172
218
|
throw this.#f.abort(), e;
|
|
173
219
|
}
|
|
174
220
|
}
|
|
175
|
-
async #
|
|
221
|
+
async #R(e) {
|
|
176
222
|
for (; !this.#f.signal.aborted;) {
|
|
177
|
-
let t = this.#
|
|
223
|
+
let t = this.#z(e.partCount);
|
|
178
224
|
if (t === null) return;
|
|
179
|
-
await this.#
|
|
225
|
+
await this.#B(e, t);
|
|
180
226
|
}
|
|
181
227
|
}
|
|
182
|
-
#
|
|
183
|
-
for (; this.#
|
|
184
|
-
let e = this.#
|
|
185
|
-
if (!this.#
|
|
228
|
+
#z(e) {
|
|
229
|
+
for (; this.#w <= e;) {
|
|
230
|
+
let e = this.#w++;
|
|
231
|
+
if (!this.#T.has(e)) return e;
|
|
186
232
|
}
|
|
187
233
|
return null;
|
|
188
234
|
}
|
|
189
|
-
async #
|
|
190
|
-
let i =
|
|
235
|
+
async #B(t, r) {
|
|
236
|
+
let i = m(this.#t.size, t.partSize, r, t.partCount), a = (r - 1) * t.partSize, o = this.#t.slice(a, a + i), c = 0, l;
|
|
191
237
|
for (; c < this.#o;) {
|
|
192
238
|
if (c++, this.#f.signal.aborted) throw new e();
|
|
193
239
|
try {
|
|
194
|
-
this.#
|
|
240
|
+
this.#C.set(r, 0), await s(this.#e, {
|
|
195
241
|
claimId: t.claimId,
|
|
196
242
|
partNumber: r,
|
|
197
243
|
blob: o,
|
|
198
244
|
onProgress: (e) => {
|
|
199
|
-
this.#
|
|
245
|
+
this.#C.set(r, Math.min(i, e.loaded)), this.#M();
|
|
200
246
|
},
|
|
201
247
|
signal: this.#f.signal
|
|
202
|
-
}), this.#
|
|
203
|
-
...this.#
|
|
204
|
-
partsCompleted: this.#
|
|
205
|
-
}, this.#
|
|
248
|
+
}), this.#C.delete(r), this.#S += i, this.#g = {
|
|
249
|
+
...this.#g,
|
|
250
|
+
partsCompleted: this.#g.partsCompleted + 1
|
|
251
|
+
}, this.#M();
|
|
206
252
|
return;
|
|
207
253
|
} catch (t) {
|
|
208
|
-
if (this.#
|
|
254
|
+
if (this.#C.delete(r), l = t, this.#f.signal.aborted) throw new e();
|
|
209
255
|
if (c >= this.#o) break;
|
|
210
|
-
await
|
|
256
|
+
await h(Math.min(this.#c, this.#s * 2 ** (c - 1)), this.#f.signal);
|
|
211
257
|
}
|
|
212
258
|
}
|
|
213
259
|
throw new n(r, c, { cause: l });
|
|
214
260
|
}
|
|
215
|
-
#
|
|
261
|
+
#V(e) {
|
|
216
262
|
return e instanceof t ? e : e instanceof Error ? new r("unknown", e.message, { cause: e }) : new r("unknown", String(e));
|
|
217
263
|
}
|
|
218
264
|
};
|
|
219
|
-
function
|
|
220
|
-
return new
|
|
265
|
+
function _(e, t, n) {
|
|
266
|
+
return new g(e, t, n).start();
|
|
221
267
|
}
|
|
222
268
|
//#endregion
|
|
223
|
-
export {
|
|
269
|
+
export { g as Uploader, _ as uploadFile };
|
package/dist/es/store/bound.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @vef-framework-react/core v2.
|
|
1
|
+
/*! @vef-framework-react/core v2.4.0 made by Venus | 2026-06-15T15:10:07.347Z */
|
|
2
2
|
import { constantCase as e, identity as t } from "@vef-framework-react/shared";
|
|
3
3
|
import { create as n } from "zustand";
|
|
4
4
|
import { createJSONStorage as r, persist as i, subscribeWithSelector as a } from "zustand/middleware";
|
package/dist/es/store/index.js
CHANGED
package/dist/es/store/unbound.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @vef-framework-react/core v2.
|
|
1
|
+
/*! @vef-framework-react/core v2.4.0 made by Venus | 2026-06-15T15:10:07.347Z */
|
|
2
2
|
import { constantCase as e, identity as t, isPlainObject as n, mergeWith as r } from "@vef-framework-react/shared";
|
|
3
3
|
import { createContext as i, use as a, useRef as o } from "react";
|
|
4
4
|
import { jsx as s } from "@emotion/react/jsx-runtime";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @vef-framework-react/core v2.
|
|
1
|
+
/*! @vef-framework-react/core v2.4.0 made by Venus | 2026-06-15T15:10:07.347Z */
|
|
2
2
|
import { isDeepEqual as e } from "@vef-framework-react/shared";
|
|
3
3
|
import { useRef as t } from "react";
|
|
4
4
|
//#region src/store/use-deep.ts
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
export { CollisionPriority } from '@dnd-kit/abstract';
|
|
1
2
|
export { AxisModifier, restrictShapeToBoundingRectangle, RestrictToHorizontalAxis, RestrictToVerticalAxis, SnapModifier } from '@dnd-kit/abstract/modifiers';
|
|
2
3
|
export { closestCenter, closestCorners, defaultCollisionDetection, directionBiased, pointerDistance, pointerIntersection, shapeIntersection } from '@dnd-kit/collision';
|
|
3
4
|
export type { CollisionDetector } from '@dnd-kit/collision';
|
|
4
|
-
export { defaultPreset, Feedback } from '@dnd-kit/dom';
|
|
5
|
+
export { defaultPreset, Feedback, PointerActivationConstraints } from '@dnd-kit/dom';
|
|
5
6
|
export type { FeedbackInput, FeedbackOptions, FeedbackType } from '@dnd-kit/dom';
|
|
6
7
|
export { RestrictToElement, RestrictToWindow } from '@dnd-kit/dom/modifiers';
|
|
7
8
|
export { arrayMove as moveArrayItem, move as moveDragItem, arraySwap as swapArrayItem, swap as swapDragItem } from '@dnd-kit/helpers';
|
|
8
9
|
export type { BeforeDragStartEvent, CollisionEvent, DragDropEventHandlers, DragEndEvent, DragMoveEvent, DragOverEvent, DragStartEvent } from '@dnd-kit/react';
|
|
9
|
-
export { DragDropProvider, DragOverlay, KeyboardSensor, PointerSensor, useDragDropMonitor, useDraggable, useDroppable } from '@dnd-kit/react';
|
|
10
|
+
export { DragDropProvider, DragOverlay, KeyboardSensor, PointerSensor, useDragDropMonitor, useDraggable, useDragOperation, useDroppable } from '@dnd-kit/react';
|
|
10
11
|
export { useSortable } from '@dnd-kit/react/sortable';
|
|
11
12
|
export type { DragDropContextProps, DraggableChildrenFn, DraggableId, DraggableLocation, DraggableProps, DraggableProvided, DraggableProvidedDraggableProps, DraggableProvidedDragHandleProps, DraggableRubric, DraggableStateSnapshot, DroppableId, DroppableProps, DroppableProvided, DroppableProvidedProps, DroppableStateSnapshot, DropResult, OnBeforeCaptureResponder, OnBeforeDragStartResponder, OnDragEndResponder, OnDragStartResponder, OnDragUpdateResponder } from '@hello-pangea/dnd';
|
|
12
13
|
export { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd';
|
|
@@ -2,7 +2,7 @@ export { ApiClient, createApiClient, createApiRequest, HTTP_CLIENT, QUERY_CLIENT
|
|
|
2
2
|
export { checkPermission, type PermissionCheckMode } from './auth';
|
|
3
3
|
export { type DataOption, type DataOptionWithPinyin, type PaginationParams, type PaginationResult } from './common';
|
|
4
4
|
export { ApiClientProvider, AppContextProvider, createContextWithSelector, DisabledProvider, useApiClient, useAppContext, useDisabled, type AppContext, type SelectorContextProviderProps, type SelectorContextResult, type UseSelectorContext } from './context';
|
|
5
|
-
export { AxisModifier, closestCenter, closestCorners, defaultCollisionDetection, defaultPreset, directionBiased, DragDropContext, DragDropProvider, Draggable, DragOverlay, Droppable, Feedback, KeyboardSensor, moveArrayItem, moveDragItem, pointerDistance, pointerIntersection, PointerSensor, restrictShapeToBoundingRectangle, RestrictToElement, RestrictToHorizontalAxis, RestrictToVerticalAxis, RestrictToWindow, shapeIntersection, SnapModifier, swapArrayItem, swapDragItem, useDragDropMonitor, useDraggable, useDroppable, useSortable, type BeforeDragStartEvent, type CollisionDetector, type CollisionEvent, type DragDropContextProps, type DragDropEventHandlers, type DragEndEvent, type DraggableChildrenFn, type DraggableId, type DraggableLocation, type DraggableProps, type DraggableProvided, type DraggableProvidedDraggableProps, type DraggableProvidedDragHandleProps, type DraggableRubric, type DraggableStateSnapshot, type DragMoveEvent, type DragOverEvent, type DragStartEvent, type DroppableId, type DroppableProps, type DroppableProvided, type DroppableProvidedProps, type DroppableStateSnapshot, type DropResult, type FeedbackInput, type FeedbackOptions, type FeedbackType, type OnBeforeCaptureResponder, type OnBeforeDragStartResponder, type OnDragEndResponder, type OnDragStartResponder, type OnDragUpdateResponder } from './dnd';
|
|
5
|
+
export { AxisModifier, closestCenter, closestCorners, CollisionPriority, defaultCollisionDetection, defaultPreset, directionBiased, DragDropContext, DragDropProvider, Draggable, DragOverlay, Droppable, Feedback, KeyboardSensor, moveArrayItem, moveDragItem, PointerActivationConstraints, pointerDistance, pointerIntersection, PointerSensor, restrictShapeToBoundingRectangle, RestrictToElement, RestrictToHorizontalAxis, RestrictToVerticalAxis, RestrictToWindow, shapeIntersection, SnapModifier, swapArrayItem, swapDragItem, useDragDropMonitor, useDraggable, useDragOperation, useDroppable, useSortable, type BeforeDragStartEvent, type CollisionDetector, type CollisionEvent, type DragDropContextProps, type DragDropEventHandlers, type DragEndEvent, type DraggableChildrenFn, type DraggableId, type DraggableLocation, type DraggableProps, type DraggableProvided, type DraggableProvidedDraggableProps, type DraggableProvidedDragHandleProps, type DraggableRubric, type DraggableStateSnapshot, type DragMoveEvent, type DragOverEvent, type DragStartEvent, type DroppableId, type DroppableProps, type DroppableProvided, type DroppableProvidedProps, type DroppableStateSnapshot, type DropResult, type FeedbackInput, type FeedbackOptions, type FeedbackType, type OnBeforeCaptureResponder, type OnBeforeDragStartResponder, type OnDragEndResponder, type OnDragStartResponder, type OnDragUpdateResponder } from './dnd';
|
|
6
6
|
export type { ApiResult, AuthTokens, BusinessError, HttpClient, HttpClientOptions, isBusinessError, ProgressEvent, RequestOptions } from './http';
|
|
7
7
|
export { skipAuthenticationHeader, skipAuthenticationValue } from './http';
|
|
8
8
|
export { applyPatches, currentState, originalState, produce, produceWithPatches, useImmer, useImmerReducer } from './immer';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DefinedInitialDataInfiniteOptions, DefinedInitialDataOptions, DefinedUseInfiniteQueryResult, DefinedUseQueryResult, InfiniteData, MutationFilters, MutationState,
|
|
1
|
+
import { DefinedInitialDataInfiniteOptions, DefinedInitialDataOptions, DefinedUseInfiniteQueryResult, DefinedUseQueryResult, InfiniteData, MutationFilters, MutationState, QueriesResults, QueryFilters, UndefinedInitialDataInfiniteOptions, UndefinedInitialDataOptions, UseInfiniteQueryResult, UseMutationOptions, UseMutationResult, UseQueryOptions, UseQueryResult, useMutationState as useMutationStateInternal, useQueries as useQueriesInternal } from '@tanstack/react-query';
|
|
2
2
|
import { QueryKey } from '../api';
|
|
3
3
|
export declare function useQuery<TQueryFnData = unknown, TData = TQueryFnData, TParams = never>(options: DefinedInitialDataOptions<TQueryFnData, Error, TData, QueryKey<TParams>>): DefinedUseQueryResult<NoInfer<TData>, Error>;
|
|
4
4
|
export declare function useQuery<TQueryFnData = unknown, TData = TQueryFnData, TParams = never>(options: UndefinedInitialDataOptions<TQueryFnData, Error, TData, QueryKey<TParams>> | UseQueryOptions<TQueryFnData, Error, TData, QueryKey<TParams>>): UseQueryResult<NoInfer<TData>, Error>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SseClientOptions, SseEventHandlers, SseRequestConfig } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* SSE client wrapper around @microsoft/fetch-event-source.
|
|
4
|
+
*
|
|
5
|
+
* Each `stream()` call runs the session statechart in `./stream-machine.ts`
|
|
6
|
+
* (attempt → token refresh → one retry); this class supplies the connection
|
|
7
|
+
* attempt itself and the token-refresh callback. Reconnects *within* an
|
|
8
|
+
* attempt stay inside `fetch-event-source`, which owns `Last-Event-ID`
|
|
9
|
+
* continuity and server-driven retry intervals.
|
|
10
|
+
*/
|
|
11
|
+
export declare class SseClient {
|
|
12
|
+
#private;
|
|
13
|
+
constructor(options?: SseClientOptions);
|
|
14
|
+
/**
|
|
15
|
+
* Start an SSE stream request. Resolves when the stream ends — normally,
|
|
16
|
+
* by abort, or after a reported auth failure; rejects with the original
|
|
17
|
+
* error when the stream fails past its retry budget.
|
|
18
|
+
*/
|
|
19
|
+
stream(config: SseRequestConfig, handlers: SseEventHandlers): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Abort all active stream requests.
|
|
22
|
+
*/
|
|
23
|
+
abort(): void;
|
|
24
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { StateMachine, MachineContext, AnyEventObject, ActorRefFromLogic, PromiseActorLogic, NonReducibleUnknown, EventObject, MetaObject } from 'xstate';
|
|
2
|
+
/**
|
|
3
|
+
* Internal signal: the backend answered 401, so the attempt must stop and
|
|
4
|
+
* the session may retry once after a token refresh. Thrown by the client's
|
|
5
|
+
* `onopen` handler; routed (never surfaced) by the session statechart.
|
|
6
|
+
*/
|
|
7
|
+
export declare class TokenExpiredError extends Error {
|
|
8
|
+
constructor();
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Side-effect surface the stream-session statechart drives. Every dep
|
|
12
|
+
* closes over one `stream()` call's config and handlers.
|
|
13
|
+
*/
|
|
14
|
+
export interface StreamMachineDeps {
|
|
15
|
+
/**
|
|
16
|
+
* One full connection attempt: prepare headers, open the event source,
|
|
17
|
+
* pump events until the stream ends. In-connection reconnects stay
|
|
18
|
+
* delegated to `fetch-event-source` (it owns `Last-Event-ID` continuity
|
|
19
|
+
* and server-driven retry intervals); a rejection here means the attempt
|
|
20
|
+
* is over — `TokenExpiredError` asks for the refresh path.
|
|
21
|
+
*/
|
|
22
|
+
runAttempt: () => Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Ask the host app to refresh the token. Total by contract: resolves
|
|
25
|
+
* `false` instead of rejecting when the refresh fails.
|
|
26
|
+
*/
|
|
27
|
+
refreshToken: () => Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* Deliver the "authentication failed" outcome to the caller's handlers.
|
|
30
|
+
* The session still ends as `completed` — auth failure is reported, not
|
|
31
|
+
* thrown (the caller already got the error through `onError`).
|
|
32
|
+
*/
|
|
33
|
+
reportAuthFailure: () => void;
|
|
34
|
+
/**
|
|
35
|
+
* Record the error the `stream()` promise rejects with (the original
|
|
36
|
+
* instance, untouched) once the machine reaches `failed`.
|
|
37
|
+
*/
|
|
38
|
+
recordFailure: (error: unknown) => void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Session statechart behind `SseClient.stream()`: at most two connection
|
|
42
|
+
* attempts bridged by a single token refresh.
|
|
43
|
+
*
|
|
44
|
+
* ```
|
|
45
|
+
* streaming ──ok/abort──▶ completed
|
|
46
|
+
* │ token expired
|
|
47
|
+
* ▼
|
|
48
|
+
* refreshingToken ──refresh failed──▶ completed (auth failure reported)
|
|
49
|
+
* │ refreshed
|
|
50
|
+
* ▼
|
|
51
|
+
* retrying ──ok/abort──▶ completed
|
|
52
|
+
* │ any error (including a second 401)
|
|
53
|
+
* ▼
|
|
54
|
+
* failed
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* The chart replaces the previous recursion (`#executeStream` calling
|
|
58
|
+
* itself) and its scattered closure flags (`tokenRefreshAttempted`,
|
|
59
|
+
* `cleanedUp`): "the refresh has been spent" is now the `retrying` state
|
|
60
|
+
* itself, not a boolean threaded through call frames.
|
|
61
|
+
*/
|
|
62
|
+
export declare function createStreamMachine(deps: StreamMachineDeps): StateMachine<MachineContext, AnyEventObject, {
|
|
63
|
+
[x: string]: ActorRefFromLogic<PromiseActorLogic<boolean, NonReducibleUnknown, EventObject>> | ActorRefFromLogic<PromiseActorLogic<void, NonReducibleUnknown, EventObject>> | undefined;
|
|
64
|
+
}, {
|
|
65
|
+
src: "refreshToken";
|
|
66
|
+
logic: PromiseActorLogic<boolean, NonReducibleUnknown, EventObject>;
|
|
67
|
+
id: string | undefined;
|
|
68
|
+
} | {
|
|
69
|
+
src: "runAttempt";
|
|
70
|
+
logic: PromiseActorLogic<void, NonReducibleUnknown, EventObject>;
|
|
71
|
+
id: string | undefined;
|
|
72
|
+
}, {
|
|
73
|
+
type: "recordFailure";
|
|
74
|
+
params: {
|
|
75
|
+
error: unknown;
|
|
76
|
+
};
|
|
77
|
+
} | {
|
|
78
|
+
type: "reportAuthFailure";
|
|
79
|
+
params: unknown;
|
|
80
|
+
}, {
|
|
81
|
+
type: "wasAborted";
|
|
82
|
+
params: {
|
|
83
|
+
error: unknown;
|
|
84
|
+
};
|
|
85
|
+
} | {
|
|
86
|
+
type: "wasTokenExpired";
|
|
87
|
+
params: {
|
|
88
|
+
error: unknown;
|
|
89
|
+
};
|
|
90
|
+
} | {
|
|
91
|
+
type: "refreshSucceeded";
|
|
92
|
+
params: {
|
|
93
|
+
refreshed: boolean;
|
|
94
|
+
};
|
|
95
|
+
}, never, "streaming" | "completed" | "refreshingToken" | "failed" | "retrying", string, NonReducibleUnknown, NonReducibleUnknown, EventObject, MetaObject, {
|
|
96
|
+
id: "sseStream";
|
|
97
|
+
states: {
|
|
98
|
+
readonly streaming: {};
|
|
99
|
+
readonly refreshingToken: {};
|
|
100
|
+
readonly retrying: {};
|
|
101
|
+
readonly completed: {};
|
|
102
|
+
readonly failed: {};
|
|
103
|
+
};
|
|
104
|
+
}>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { ResumePlan } from './resumable/plan';
|
|
2
|
+
import { StateMachine, MachineContext, ActorRefFromLogic, PromiseActorLogic, NonReducibleUnknown, EventObject, MetaObject } from 'xstate';
|
|
3
|
+
/**
|
|
4
|
+
* Side-effect surface the uploader statechart drives. The machine owns the
|
|
5
|
+
* lifecycle only — every phase runner closes over the `Uploader` instance
|
|
6
|
+
* that supplies it, so the chart stays a pure, domain-free transition table.
|
|
7
|
+
*/
|
|
8
|
+
export interface UploaderMachineDeps {
|
|
9
|
+
/**
|
|
10
|
+
* Open (fresh) or synthesise (resume) the multipart session and seed the
|
|
11
|
+
* uploader's bookkeeping. Rejection means the session never opened.
|
|
12
|
+
*/
|
|
13
|
+
prepareSession: (plan: ResumePlan) => Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Stream every pending part through the worker pool. Rejection carries the
|
|
16
|
+
* first terminal worker error.
|
|
17
|
+
*/
|
|
18
|
+
uploadParts: () => Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Finalize the multipart session and capture the upload result.
|
|
21
|
+
*/
|
|
22
|
+
completeSession: () => Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Best-effort backend `abort_upload`. Must never reject for control flow —
|
|
25
|
+
* the machine lands in `aborted` either way.
|
|
26
|
+
*/
|
|
27
|
+
abortSession: () => Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Abort the shared transport controller so in-flight HTTP requests and
|
|
30
|
+
* pending retry backoffs unwind immediately.
|
|
31
|
+
*/
|
|
32
|
+
killTransport: () => void;
|
|
33
|
+
/**
|
|
34
|
+
* Record the error a phase rejected with; `start()` rejects with it once
|
|
35
|
+
* the machine reaches `failed`.
|
|
36
|
+
*/
|
|
37
|
+
recordFailure: (error: unknown) => void;
|
|
38
|
+
/**
|
|
39
|
+
* Whether an abort was latched before the run started (external signal
|
|
40
|
+
* already aborted, or `abort()` called while still idle).
|
|
41
|
+
*/
|
|
42
|
+
abortRequested: () => boolean;
|
|
43
|
+
}
|
|
44
|
+
export type UploaderEvent = {
|
|
45
|
+
type: "START";
|
|
46
|
+
plan: ResumePlan;
|
|
47
|
+
} | {
|
|
48
|
+
type: "ABORT";
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Lifecycle statechart behind `Uploader`. State names are exactly the public
|
|
52
|
+
* `UploadStatus` values — the chart IS the documented contract in
|
|
53
|
+
* `./types.ts`, and `Uploader` maps snapshots to statuses by name.
|
|
54
|
+
*
|
|
55
|
+
* Cancellation is an *event channel* (`ABORT`), not an error-instance check:
|
|
56
|
+
* a phase rejection always means failure (`onError` → `failed`, session kept
|
|
57
|
+
* alive for resume), while a caller abort always transitions to `aborting`
|
|
58
|
+
* (backend session torn down). The two can no longer be confused, even when
|
|
59
|
+
* the worker pool trips the shared controller itself to stop sibling workers
|
|
60
|
+
* after a terminal part failure.
|
|
61
|
+
*/
|
|
62
|
+
export declare function createUploaderMachine(deps: UploaderMachineDeps): StateMachine<MachineContext, {
|
|
63
|
+
type: "START";
|
|
64
|
+
plan: ResumePlan;
|
|
65
|
+
} | {
|
|
66
|
+
type: "ABORT";
|
|
67
|
+
}, {
|
|
68
|
+
[x: string]: ActorRefFromLogic<PromiseActorLogic<void, NonReducibleUnknown, EventObject>> | ActorRefFromLogic<PromiseActorLogic<void, ResumePlan, EventObject>> | undefined;
|
|
69
|
+
}, {
|
|
70
|
+
src: "prepareSession";
|
|
71
|
+
logic: PromiseActorLogic<void, ResumePlan, EventObject>;
|
|
72
|
+
id: string | undefined;
|
|
73
|
+
} | {
|
|
74
|
+
src: "uploadParts";
|
|
75
|
+
logic: PromiseActorLogic<void, NonReducibleUnknown, EventObject>;
|
|
76
|
+
id: string | undefined;
|
|
77
|
+
} | {
|
|
78
|
+
src: "completeSession";
|
|
79
|
+
logic: PromiseActorLogic<void, NonReducibleUnknown, EventObject>;
|
|
80
|
+
id: string | undefined;
|
|
81
|
+
} | {
|
|
82
|
+
src: "abortSession";
|
|
83
|
+
logic: PromiseActorLogic<void, NonReducibleUnknown, EventObject>;
|
|
84
|
+
id: string | undefined;
|
|
85
|
+
}, {
|
|
86
|
+
type: "recordFailure";
|
|
87
|
+
params: {
|
|
88
|
+
error: unknown;
|
|
89
|
+
};
|
|
90
|
+
} | {
|
|
91
|
+
type: "killTransport";
|
|
92
|
+
params: unknown;
|
|
93
|
+
}, {
|
|
94
|
+
type: "abortRequested";
|
|
95
|
+
params: unknown;
|
|
96
|
+
}, never, "idle" | "failed" | "aborted" | "initializing" | "uploading" | "completing" | "aborting" | "succeeded", string, NonReducibleUnknown, NonReducibleUnknown, EventObject, MetaObject, {
|
|
97
|
+
id: "uploader";
|
|
98
|
+
states: {
|
|
99
|
+
readonly idle: {};
|
|
100
|
+
readonly initializing: {};
|
|
101
|
+
readonly uploading: {};
|
|
102
|
+
readonly completing: {};
|
|
103
|
+
readonly aborting: {};
|
|
104
|
+
readonly succeeded: {};
|
|
105
|
+
readonly failed: {};
|
|
106
|
+
readonly aborted: {};
|
|
107
|
+
};
|
|
108
|
+
}>;
|
|
@@ -4,8 +4,14 @@ import { UploaderOptions, UploadProgress, UploadResult, UploadStatus } from './t
|
|
|
4
4
|
/**
|
|
5
5
|
* Drives a single file through the four-step chunked upload protocol
|
|
6
6
|
* (`init_upload → upload_part* → complete_upload`) exposed by the framework's
|
|
7
|
-
* `sys/storage` resource.
|
|
8
|
-
*
|
|
7
|
+
* `sys/storage` resource. A caller abort triggers a best-effort
|
|
8
|
+
* `abort_upload`; non-abort failures leave the session intact so the upload
|
|
9
|
+
* can resume.
|
|
10
|
+
*
|
|
11
|
+
* The lifecycle is governed by the statechart in `./uploader-machine.ts`:
|
|
12
|
+
* this class supplies the phase runners (session prep, worker pool,
|
|
13
|
+
* completion, backend abort) and bridges actor snapshots onto the public
|
|
14
|
+
* `status` / `onStatusChange` / `start()`-promise surface.
|
|
9
15
|
*
|
|
10
16
|
* The instance is one-shot: a successful or failed run cannot be restarted.
|
|
11
17
|
* Create a fresh `Uploader` for each file.
|