@beignet/react-uploads 0.0.3 → 0.0.4
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/CHANGELOG.md +25 -0
- package/README.md +54 -7
- package/dist/index.d.ts +25 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +110 -39
- package/dist/index.js.map +1 -1
- package/package.json +2 -4
- package/src/index.ts +183 -48
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @beignet/react-uploads
|
|
2
2
|
|
|
3
|
+
## 0.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8bcb31f: Mark package READMEs with Beignet's experimental alpha status and 0.0.x stability expectations.
|
|
8
|
+
- df4673f: Add TanStack Query filter helpers for Beignet contract cache invalidation and update generated UI examples to use them.
|
|
9
|
+
- 89390fe: Split upload hook methods into fire-and-forget and promise-returning variants, mirroring TanStack Query's `mutate`/`mutateAsync`. `upload(...)`, `uploadFile(...)`, and `useUploadMany`'s `upload(files, ...)` now return `void` and never reject; failures land in hook state and `onError`, so event-handler calls no longer produce unhandled promise rejections. Callers that awaited `upload(...)` must switch to the new `uploadAsync(...)`, `uploadFileAsync(...)`, or `uploadAsync(files, ...)` methods, which return the completion result and reject on failure or abort. Lifecycle callbacks now run after the upload settles, so a throwing `onSuccess` no longer flips a succeeded upload to `status: "error"`; `uploadAsync(...)` rejects with the callback error and `upload(...)` reports it through `console.error`. Upload hook methods also keep stable identities across renders.
|
|
10
|
+
- d137044: Declare `@beignet/core` as a peer dependency with a lockstep version range in
|
|
11
|
+
every integration and provider package instead of a regular `"*"` dependency.
|
|
12
|
+
Installs now always resolve a single shared copy of core, so `instanceof`
|
|
13
|
+
checks such as `isContractError` and upload error identity keep working, and
|
|
14
|
+
mixed Beignet versions fail loudly at install time instead of at runtime.
|
|
15
|
+
|
|
16
|
+
If your package manager does not install peer dependencies automatically, add
|
|
17
|
+
`@beignet/core` to your app alongside these packages. `@beignet/nuqs` now also
|
|
18
|
+
declares `@beignet/react-query` as a peer dependency, and
|
|
19
|
+
`@beignet/provider-storage-s3` now expects you to install
|
|
20
|
+
`@aws-sdk/client-s3` and `@aws-sdk/s3-request-presigner` yourself, matching
|
|
21
|
+
how other providers treat their SDKs.
|
|
22
|
+
|
|
23
|
+
- 1a79090: Emit Node-compatible ESM: all relative imports in published packages now carry explicit .js extensions, fixing ERR_MODULE_NOT_FOUND when running the CLI or importing package dist files under plain Node.
|
|
24
|
+
- d6ad8bb: Standardize generated client helpers around `client/index.ts`, add a typed
|
|
25
|
+
React Query invalidation helper, and align package docs with the canonical app
|
|
26
|
+
client entrypoint.
|
|
27
|
+
|
|
3
28
|
## 0.0.3
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# @beignet/react-uploads
|
|
2
2
|
|
|
3
|
+
> [!CAUTION]
|
|
4
|
+
> Beignet is experimental alpha software. The `0.0.x` package line is for early
|
|
5
|
+
> evaluation, and APIs may change between releases while the framework settles.
|
|
6
|
+
|
|
3
7
|
React upload hooks for Beignet upload clients.
|
|
4
8
|
|
|
5
9
|
## Install
|
|
6
10
|
|
|
7
11
|
```bash
|
|
8
|
-
bun add @beignet/react-uploads react
|
|
12
|
+
bun add @beignet/react-uploads @beignet/core react
|
|
9
13
|
```
|
|
10
14
|
|
|
11
15
|
## Usage
|
|
@@ -60,25 +64,68 @@ export function AttachmentPicker({ postSlug }: { postSlug: string }) {
|
|
|
60
64
|
```
|
|
61
65
|
|
|
62
66
|
The hook exposes `status`, `progress`, `error`, `result`, `reset`, and `abort`.
|
|
63
|
-
|
|
64
|
-
`
|
|
67
|
+
`upload(...)` is fire-and-forget: it never rejects, so the `onChange` handler
|
|
68
|
+
above is safe without `await` or `.catch(...)`. Failures land in hook state and
|
|
69
|
+
the `onError` callback.
|
|
70
|
+
|
|
71
|
+
Use `uploadAsync(...)` when the caller needs to sequence work after the upload
|
|
72
|
+
and handle the failure itself. It returns the completion result and rejects
|
|
73
|
+
when the upload fails:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
try {
|
|
77
|
+
const result = await attachment.uploadAsync({
|
|
78
|
+
metadata: { postSlug },
|
|
79
|
+
files,
|
|
80
|
+
});
|
|
81
|
+
console.log(result.result);
|
|
82
|
+
} catch {
|
|
83
|
+
// Failure is also stored in hook state and passed to onError.
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The adapter keeps uploads imperative and does not hide React Query; invalidate
|
|
88
|
+
queries in `onSuccess` when an upload changes visible app state.
|
|
65
89
|
|
|
66
90
|
```typescript
|
|
67
91
|
const attachment = reactUploads.useUpload("posts.attachment", {
|
|
68
92
|
onSuccess() {
|
|
69
|
-
|
|
93
|
+
rq(getPost).invalidate(queryClient);
|
|
70
94
|
},
|
|
71
95
|
});
|
|
72
96
|
```
|
|
73
97
|
|
|
98
|
+
Lifecycle callbacks run after the upload settles and never change upload state.
|
|
99
|
+
When a callback throws, `uploadAsync(...)` rejects with the callback error and
|
|
100
|
+
`upload(...)` reports it through `console.error`; a succeeded upload stays
|
|
101
|
+
`status: "success"` either way.
|
|
102
|
+
|
|
103
|
+
## Progress reporting
|
|
104
|
+
|
|
105
|
+
Progress depends on the upload transport selected by the core upload client:
|
|
106
|
+
|
|
107
|
+
- Direct uploads report real per-file progress from the browser's `XMLHttpRequest`
|
|
108
|
+
upload events.
|
|
109
|
+
- Server-strategy uploads stream the whole multipart request through the app
|
|
110
|
+
server and only report request completion, so `progress` jumps from `0` to
|
|
111
|
+
`100` in one step when the request finishes.
|
|
112
|
+
|
|
113
|
+
Treat progress bars as an enhancement for direct uploads and prefer
|
|
114
|
+
indeterminate pending UI when forcing `strategy: "server"`.
|
|
115
|
+
|
|
74
116
|
## API
|
|
75
117
|
|
|
76
118
|
- `createReactUploads({ uploads })` creates an adapter bound to a typed upload
|
|
77
119
|
client.
|
|
78
120
|
- `adapter.useUpload(name, options?)` returns state and methods for one upload
|
|
79
|
-
workflow
|
|
80
|
-
- `
|
|
81
|
-
`
|
|
121
|
+
workflow:
|
|
122
|
+
- `upload(options)` starts an upload and never rejects.
|
|
123
|
+
- `uploadAsync(options)` starts an upload and rejects on failure.
|
|
124
|
+
- `uploadFile(file, options)` / `uploadFileAsync(file, options)` are
|
|
125
|
+
single-file conveniences with the same semantics.
|
|
126
|
+
- `adapter.useUploadMany(name, options?)` returns the same state with
|
|
127
|
+
file-first `upload(files, options)` and `uploadAsync(files, options)`
|
|
128
|
+
convenience methods.
|
|
82
129
|
|
|
83
130
|
## Related
|
|
84
131
|
|
package/dist/index.d.ts
CHANGED
|
@@ -140,13 +140,25 @@ export interface ReactUploadController<Upload extends UploadDef> extends ReactUp
|
|
|
140
140
|
*/
|
|
141
141
|
isError: boolean;
|
|
142
142
|
/**
|
|
143
|
-
* Start an upload through the wrapped upload client.
|
|
143
|
+
* Start an upload through the wrapped upload client. Never rejects; failures
|
|
144
|
+
* land in hook state and `onError`.
|
|
144
145
|
*/
|
|
145
|
-
upload(options: ReactUploadStartOptions<Upload>):
|
|
146
|
+
upload(options: ReactUploadStartOptions<Upload>): void;
|
|
146
147
|
/**
|
|
147
|
-
*
|
|
148
|
+
* Start an upload and return its result. Rejects when the upload fails or a
|
|
149
|
+
* lifecycle callback throws.
|
|
148
150
|
*/
|
|
149
|
-
|
|
151
|
+
uploadAsync(options: ReactUploadStartOptions<Upload>): Promise<CompleteUploadResult<InferUploadResult<Upload>>>;
|
|
152
|
+
/**
|
|
153
|
+
* Convenience helper for uploading exactly one file. Never rejects; failures
|
|
154
|
+
* land in hook state and `onError`.
|
|
155
|
+
*/
|
|
156
|
+
uploadFile(file: File, options: ReactUploadFileStartOptions<Upload>): void;
|
|
157
|
+
/**
|
|
158
|
+
* Convenience helper for uploading exactly one file and returning its
|
|
159
|
+
* result. Rejects when the upload fails or a lifecycle callback throws.
|
|
160
|
+
*/
|
|
161
|
+
uploadFileAsync(file: File, options: ReactUploadFileStartOptions<Upload>): Promise<CompleteUploadResult<InferUploadResult<Upload>>>;
|
|
150
162
|
/**
|
|
151
163
|
* Abort the active upload request, when one exists.
|
|
152
164
|
*/
|
|
@@ -159,11 +171,17 @@ export interface ReactUploadController<Upload extends UploadDef> extends ReactUp
|
|
|
159
171
|
/**
|
|
160
172
|
* React hook controller for many-file upload ergonomics.
|
|
161
173
|
*/
|
|
162
|
-
export interface ReactUploadManyController<Upload extends UploadDef> extends Omit<ReactUploadController<Upload>, "upload" | "uploadFile"> {
|
|
174
|
+
export interface ReactUploadManyController<Upload extends UploadDef> extends Omit<ReactUploadController<Upload>, "upload" | "uploadAsync" | "uploadFile" | "uploadFileAsync"> {
|
|
175
|
+
/**
|
|
176
|
+
* Start an upload with an explicit file array. Never rejects; failures land
|
|
177
|
+
* in hook state and `onError`.
|
|
178
|
+
*/
|
|
179
|
+
upload(files: readonly File[], options: ReactUploadManyStartOptions<Upload>): void;
|
|
163
180
|
/**
|
|
164
|
-
* Start an upload with an explicit file array.
|
|
181
|
+
* Start an upload with an explicit file array and return its result. Rejects
|
|
182
|
+
* when the upload fails or a lifecycle callback throws.
|
|
165
183
|
*/
|
|
166
|
-
|
|
184
|
+
uploadAsync(files: readonly File[], options: ReactUploadManyStartOptions<Upload>): Promise<CompleteUploadResult<InferUploadResult<Upload>>>;
|
|
167
185
|
}
|
|
168
186
|
/**
|
|
169
187
|
* Options for `createReactUploads(...)`.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,SAAS,EACT,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EAC1B,MAAM,8BAA8B,CAAC;AAGtC;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,MAAM,GACN,WAAW,GACX,WAAW,GACX,YAAY,GACZ,SAAS,GACT,OAAO,CAAC;AAEZ;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,MAAM,SAAS,SAAS;IACxD;;OAEG;IACH,MAAM,EAAE,iBAAiB,CAAC;IAC1B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACtB;;OAEG;IACH,MAAM,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;IAC/D;;OAEG;IACH,KAAK,EAAE,SAAS,oBAAoB,EAAE,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B,CAAC,MAAM,SAAS,SAAS;IACnE;;OAEG;IACH,WAAW,CAAC,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACjD;;OAEG;IACH,UAAU,CAAC,CAAC,KAAK,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACpD;;OAEG;IACH,SAAS,CAAC,CACR,MAAM,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,GACtD,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB;;OAEG;IACH,OAAO,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C;;OAEG;IACH,SAAS,CAAC,CACR,MAAM,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,EACnE,KAAK,EAAE,OAAO,GAAG,SAAS,GACzB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,CAAC,MAAM,SAAS,SAAS,IAAI,IAAI,CACjE,yBAAyB,CAAC,MAAM,CAAC,EACjC,UAAU,GAAG,OAAO,GAAG,aAAa,GAAG,YAAY,CACpD,GACC,2BAA2B,CAAC,MAAM,CAAC,CAAC;AAEtC;;GAEG;AACH,MAAM,MAAM,uBAAuB,CAAC,MAAM,SAAS,SAAS,IAC1D,yBAAyB,CAAC,MAAM,CAAC,GAAG,2BAA2B,CAAC,MAAM,CAAC,CAAC;AAE1E;;GAEG;AACH,MAAM,MAAM,2BAA2B,CAAC,MAAM,SAAS,SAAS,IAAI,IAAI,CACtE,uBAAuB,CAAC,MAAM,CAAC,EAC/B,OAAO,CACR,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,2BAA2B,CAAC,MAAM,SAAS,SAAS,IAAI,IAAI,CACtE,uBAAuB,CAAC,MAAM,CAAC,EAC/B,OAAO,CACR,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,qBAAqB,CAAC,MAAM,SAAS,SAAS,CAC7D,SAAQ,gBAAgB,CAAC,MAAM,CAAC;IAChC;;OAEG;IACH,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B;;OAEG;IACH,WAAW,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAC/C;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,uBAAuB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IACvD;;;OAGG;IACH,WAAW,CACT,OAAO,EAAE,uBAAuB,CAAC,MAAM,CAAC,GACvC,OAAO,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC5D;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,2BAA2B,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC3E;;;OAGG;IACH,eAAe,CACb,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,2BAA2B,CAAC,MAAM,CAAC,GAC3C,OAAO,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC5D;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;IACd;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB,CAAC,MAAM,SAAS,SAAS,CACjE,SAAQ,IAAI,CACV,qBAAqB,CAAC,MAAM,CAAC,EAC7B,QAAQ,GAAG,aAAa,GAAG,YAAY,GAAG,iBAAiB,CAC5D;IACD;;;OAGG;IACH,MAAM,CACJ,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,OAAO,EAAE,2BAA2B,CAAC,MAAM,CAAC,GAC3C,IAAI,CAAC;IACR;;;OAGG;IACH,WAAW,CACT,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,OAAO,EAAE,2BAA2B,CAAC,MAAM,CAAC,GAC3C,OAAO,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;CAC7D;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB,CACxC,QAAQ,SAAS,oBAAoB;IAErC;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB,CAAC,QAAQ,SAAS,oBAAoB;IACxE;;OAEG;IACH,SAAS,CAAC,IAAI,SAAS,gBAAgB,CAAC,QAAQ,CAAC,EAC/C,UAAU,EAAE,IAAI,EAChB,OAAO,CAAC,EAAE,sBAAsB,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,GAC7D,qBAAqB,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;IACvD;;OAEG;IACH,aAAa,CAAC,IAAI,SAAS,gBAAgB,CAAC,QAAQ,CAAC,EACnD,UAAU,EAAE,IAAI,EAChB,OAAO,CAAC,EAAE,sBAAsB,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,GAC7D,yBAAyB,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;CAC5D;AAqCD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,SAAS,oBAAoB,EACtE,OAAO,EAAE,yBAAyB,CAAC,QAAQ,CAAC,GAC3C,mBAAmB,CAAC,QAAQ,CAAC,CAoT/B;AAgFD;;GAEG;AACH,MAAM,MAAM,wBAAwB,CAClC,QAAQ,SAAS,oBAAoB,EACrC,IAAI,SAAS,gBAAgB,CAAC,QAAQ,CAAC,IACrC,mBAAmB,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;AAEtD;;GAEG;AACH,MAAM,MAAM,sBAAsB,CAChC,QAAQ,SAAS,oBAAoB,EACrC,IAAI,SAAS,gBAAgB,CAAC,QAAQ,CAAC,IACrC,iBAAiB,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,9 @@ const INITIAL_STATE = {
|
|
|
7
7
|
result: null,
|
|
8
8
|
files: [],
|
|
9
9
|
};
|
|
10
|
+
function reportCallbackError(uploadName, error) {
|
|
11
|
+
console.error(`An upload lifecycle callback threw after the "${uploadName}" upload settled. Upload state was not changed.`, error);
|
|
12
|
+
}
|
|
10
13
|
/**
|
|
11
14
|
* Create React hooks for a typed Beignet upload client.
|
|
12
15
|
*/
|
|
@@ -15,6 +18,8 @@ export function createReactUploads(options) {
|
|
|
15
18
|
function useUpload(uploadName, hookOptions = {}) {
|
|
16
19
|
const abortRef = useRef(null);
|
|
17
20
|
const progressRef = useRef(new Map());
|
|
21
|
+
const hookOptionsRef = useRef(hookOptions);
|
|
22
|
+
hookOptionsRef.current = hookOptions;
|
|
18
23
|
const [state, setState] = useState(INITIAL_STATE);
|
|
19
24
|
const reset = useCallback(() => {
|
|
20
25
|
progressRef.current.clear();
|
|
@@ -23,11 +28,11 @@ export function createReactUploads(options) {
|
|
|
23
28
|
const abort = useCallback(() => {
|
|
24
29
|
abortRef.current?.abort();
|
|
25
30
|
}, []);
|
|
26
|
-
const
|
|
31
|
+
const runUpload = useCallback(async (startOptions) => {
|
|
27
32
|
abortRef.current?.abort();
|
|
28
33
|
const controller = new AbortController();
|
|
29
34
|
abortRef.current = controller;
|
|
30
|
-
const { onFileBegin: hookOnFileBegin, onProgress: hookOnProgress, onSuccess: hookOnSuccess, onError: hookOnError, onSettled: hookOnSettled, ...hookClientOptions } =
|
|
35
|
+
const { onFileBegin: hookOnFileBegin, onProgress: hookOnProgress, onSuccess: hookOnSuccess, onError: hookOnError, onSettled: hookOnSettled, ...hookClientOptions } = hookOptionsRef.current;
|
|
31
36
|
const { onFileBegin: startOnFileBegin, onProgress: startOnProgress, onSuccess: startOnSuccess, onError: startOnError, onSettled: startOnSettled, ...startClientOptions } = startOptions;
|
|
32
37
|
const isCurrentUpload = () => abortRef.current === controller;
|
|
33
38
|
const externalSignal = startClientOptions.signal ?? hookClientOptions.signal;
|
|
@@ -45,10 +50,13 @@ export function createReactUploads(options) {
|
|
|
45
50
|
...INITIAL_STATE,
|
|
46
51
|
status: "preparing",
|
|
47
52
|
});
|
|
48
|
-
let
|
|
49
|
-
let
|
|
53
|
+
let result;
|
|
54
|
+
let uploadFailure;
|
|
55
|
+
// This try/catch governs hook state only from the upload client
|
|
56
|
+
// outcome. Lifecycle callbacks run after the state transition, so a
|
|
57
|
+
// throwing callback can never flip a settled upload status.
|
|
50
58
|
try {
|
|
51
|
-
|
|
59
|
+
result = (await uploads.upload(uploadName, {
|
|
52
60
|
...hookClientOptions,
|
|
53
61
|
...startClientOptions,
|
|
54
62
|
signal: controller.signal,
|
|
@@ -81,48 +89,90 @@ export function createReactUploads(options) {
|
|
|
81
89
|
hookOnProgress?.(event);
|
|
82
90
|
startOnProgress?.(event);
|
|
83
91
|
},
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
uploadFailure = { error };
|
|
96
|
+
}
|
|
97
|
+
externalSignal?.removeEventListener("abort", abortFromExternalSignal);
|
|
98
|
+
const finishedCurrentUpload = isCurrentUpload();
|
|
99
|
+
if (finishedCurrentUpload) {
|
|
100
|
+
abortRef.current = null;
|
|
101
|
+
}
|
|
102
|
+
const failure = uploadFailure;
|
|
103
|
+
if (finishedCurrentUpload) {
|
|
104
|
+
if (failure) {
|
|
105
|
+
setState((current) => ({
|
|
106
|
+
...current,
|
|
107
|
+
status: "error",
|
|
108
|
+
error: failure.error,
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
const settledResult = result ?? null;
|
|
89
113
|
setState((current) => ({
|
|
90
114
|
...current,
|
|
91
115
|
status: "success",
|
|
92
116
|
progress: 100,
|
|
93
117
|
progressFraction: 1,
|
|
94
118
|
error: null,
|
|
95
|
-
result: settledResult
|
|
119
|
+
result: settledResult,
|
|
96
120
|
}));
|
|
97
121
|
}
|
|
98
|
-
return settledResult;
|
|
99
122
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
status: "error",
|
|
108
|
-
error,
|
|
109
|
-
}));
|
|
123
|
+
let callbackFailure;
|
|
124
|
+
const runCallback = async (callback) => {
|
|
125
|
+
try {
|
|
126
|
+
await callback();
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
callbackFailure ??= { error };
|
|
110
130
|
}
|
|
111
|
-
|
|
131
|
+
};
|
|
132
|
+
if (failure) {
|
|
133
|
+
await runCallback(() => hookOnError?.(failure.error));
|
|
134
|
+
await runCallback(() => startOnError?.(failure.error));
|
|
135
|
+
await runCallback(() => hookOnSettled?.(undefined, failure.error));
|
|
136
|
+
await runCallback(() => startOnSettled?.(undefined, failure.error));
|
|
137
|
+
return { uploadFailure: failure, callbackFailure };
|
|
112
138
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
139
|
+
const settledResult = result;
|
|
140
|
+
await runCallback(() => hookOnSuccess?.(settledResult));
|
|
141
|
+
await runCallback(() => startOnSuccess?.(settledResult));
|
|
142
|
+
await runCallback(() => hookOnSettled?.(settledResult, undefined));
|
|
143
|
+
await runCallback(() => startOnSettled?.(settledResult, undefined));
|
|
144
|
+
return { result: settledResult, callbackFailure };
|
|
145
|
+
}, [uploadName]);
|
|
146
|
+
const uploadAsync = useCallback(async (startOptions) => {
|
|
147
|
+
const outcome = await runUpload(startOptions);
|
|
148
|
+
if (outcome.uploadFailure) {
|
|
149
|
+
if (outcome.callbackFailure) {
|
|
150
|
+
reportCallbackError(uploadName, outcome.callbackFailure.error);
|
|
117
151
|
}
|
|
118
|
-
|
|
119
|
-
|
|
152
|
+
throw outcome.uploadFailure.error;
|
|
153
|
+
}
|
|
154
|
+
if (outcome.callbackFailure) {
|
|
155
|
+
throw outcome.callbackFailure.error;
|
|
120
156
|
}
|
|
121
|
-
|
|
122
|
-
|
|
157
|
+
return outcome.result;
|
|
158
|
+
}, [runUpload, uploadName]);
|
|
159
|
+
const upload = useCallback((startOptions) => {
|
|
160
|
+
void runUpload(startOptions).then((outcome) => {
|
|
161
|
+
if (outcome.callbackFailure) {
|
|
162
|
+
reportCallbackError(uploadName, outcome.callbackFailure.error);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}, [runUpload, uploadName]);
|
|
166
|
+
const uploadFileAsync = useCallback((file, startOptions) => uploadAsync({
|
|
123
167
|
...startOptions,
|
|
124
168
|
files: [file],
|
|
125
|
-
}), [
|
|
169
|
+
}), [uploadAsync]);
|
|
170
|
+
const uploadFile = useCallback((file, startOptions) => {
|
|
171
|
+
upload({
|
|
172
|
+
...startOptions,
|
|
173
|
+
files: [file],
|
|
174
|
+
});
|
|
175
|
+
}, [upload]);
|
|
126
176
|
return useMemo(() => {
|
|
127
177
|
const isIdle = state.status === "idle";
|
|
128
178
|
const isSuccess = state.status === "success";
|
|
@@ -140,22 +190,43 @@ export function createReactUploads(options) {
|
|
|
140
190
|
isSuccess,
|
|
141
191
|
isError,
|
|
142
192
|
upload,
|
|
193
|
+
uploadAsync,
|
|
143
194
|
uploadFile,
|
|
195
|
+
uploadFileAsync,
|
|
144
196
|
abort,
|
|
145
197
|
reset,
|
|
146
198
|
};
|
|
147
|
-
}, [
|
|
199
|
+
}, [
|
|
200
|
+
state,
|
|
201
|
+
uploadName,
|
|
202
|
+
upload,
|
|
203
|
+
uploadAsync,
|
|
204
|
+
uploadFile,
|
|
205
|
+
uploadFileAsync,
|
|
206
|
+
abort,
|
|
207
|
+
reset,
|
|
208
|
+
]);
|
|
148
209
|
}
|
|
149
210
|
function useUploadMany(uploadName, hookOptions = {}) {
|
|
150
211
|
const controller = useUpload(uploadName, hookOptions);
|
|
151
|
-
const uploadMany = useCallback((files, startOptions) =>
|
|
212
|
+
const uploadMany = useCallback((files, startOptions) => {
|
|
213
|
+
controller.upload({
|
|
214
|
+
...startOptions,
|
|
215
|
+
files,
|
|
216
|
+
});
|
|
217
|
+
}, [controller.upload]);
|
|
218
|
+
const uploadManyAsync = useCallback((files, startOptions) => controller.uploadAsync({
|
|
152
219
|
...startOptions,
|
|
153
220
|
files,
|
|
154
|
-
}), [controller.
|
|
155
|
-
return useMemo(() =>
|
|
156
|
-
...controller
|
|
157
|
-
|
|
158
|
-
|
|
221
|
+
}), [controller.uploadAsync]);
|
|
222
|
+
return useMemo(() => {
|
|
223
|
+
const { upload: _upload, uploadAsync: _uploadAsync, uploadFile: _uploadFile, uploadFileAsync: _uploadFileAsync, ...sharedController } = controller;
|
|
224
|
+
return {
|
|
225
|
+
...sharedController,
|
|
226
|
+
upload: uploadMany,
|
|
227
|
+
uploadAsync: uploadManyAsync,
|
|
228
|
+
};
|
|
229
|
+
}, [controller, uploadMany, uploadManyAsync]);
|
|
159
230
|
}
|
|
160
231
|
return { useUpload, useUploadMany };
|
|
161
232
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@beignet/react-uploads",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "React upload hooks for Beignet upload clients",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -52,11 +52,9 @@
|
|
|
52
52
|
"node": ">=18.0.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
+
"@beignet/core": ">=0.0.3 <1.0.0",
|
|
55
56
|
"react": "^18.0.0 || ^19.0.0"
|
|
56
57
|
},
|
|
57
|
-
"dependencies": {
|
|
58
|
-
"@beignet/core": "*"
|
|
59
|
-
},
|
|
60
58
|
"devDependencies": {
|
|
61
59
|
"@testing-library/dom": "^9.3.4",
|
|
62
60
|
"@testing-library/react": "^14.3.1",
|
package/src/index.ts
CHANGED
|
@@ -187,15 +187,27 @@ export interface ReactUploadController<Upload extends UploadDef>
|
|
|
187
187
|
*/
|
|
188
188
|
isError: boolean;
|
|
189
189
|
/**
|
|
190
|
-
* Start an upload through the wrapped upload client.
|
|
190
|
+
* Start an upload through the wrapped upload client. Never rejects; failures
|
|
191
|
+
* land in hook state and `onError`.
|
|
191
192
|
*/
|
|
192
|
-
upload(
|
|
193
|
+
upload(options: ReactUploadStartOptions<Upload>): void;
|
|
194
|
+
/**
|
|
195
|
+
* Start an upload and return its result. Rejects when the upload fails or a
|
|
196
|
+
* lifecycle callback throws.
|
|
197
|
+
*/
|
|
198
|
+
uploadAsync(
|
|
193
199
|
options: ReactUploadStartOptions<Upload>,
|
|
194
200
|
): Promise<CompleteUploadResult<InferUploadResult<Upload>>>;
|
|
195
201
|
/**
|
|
196
|
-
* Convenience helper for uploading exactly one file.
|
|
202
|
+
* Convenience helper for uploading exactly one file. Never rejects; failures
|
|
203
|
+
* land in hook state and `onError`.
|
|
204
|
+
*/
|
|
205
|
+
uploadFile(file: File, options: ReactUploadFileStartOptions<Upload>): void;
|
|
206
|
+
/**
|
|
207
|
+
* Convenience helper for uploading exactly one file and returning its
|
|
208
|
+
* result. Rejects when the upload fails or a lifecycle callback throws.
|
|
197
209
|
*/
|
|
198
|
-
|
|
210
|
+
uploadFileAsync(
|
|
199
211
|
file: File,
|
|
200
212
|
options: ReactUploadFileStartOptions<Upload>,
|
|
201
213
|
): Promise<CompleteUploadResult<InferUploadResult<Upload>>>;
|
|
@@ -213,13 +225,25 @@ export interface ReactUploadController<Upload extends UploadDef>
|
|
|
213
225
|
* React hook controller for many-file upload ergonomics.
|
|
214
226
|
*/
|
|
215
227
|
export interface ReactUploadManyController<Upload extends UploadDef>
|
|
216
|
-
extends Omit<
|
|
228
|
+
extends Omit<
|
|
229
|
+
ReactUploadController<Upload>,
|
|
230
|
+
"upload" | "uploadAsync" | "uploadFile" | "uploadFileAsync"
|
|
231
|
+
> {
|
|
217
232
|
/**
|
|
218
|
-
* Start an upload with an explicit file array.
|
|
233
|
+
* Start an upload with an explicit file array. Never rejects; failures land
|
|
234
|
+
* in hook state and `onError`.
|
|
219
235
|
*/
|
|
220
236
|
upload(
|
|
221
237
|
files: readonly File[],
|
|
222
238
|
options: ReactUploadManyStartOptions<Upload>,
|
|
239
|
+
): void;
|
|
240
|
+
/**
|
|
241
|
+
* Start an upload with an explicit file array and return its result. Rejects
|
|
242
|
+
* when the upload fails or a lifecycle callback throws.
|
|
243
|
+
*/
|
|
244
|
+
uploadAsync(
|
|
245
|
+
files: readonly File[],
|
|
246
|
+
options: ReactUploadManyStartOptions<Upload>,
|
|
223
247
|
): Promise<CompleteUploadResult<InferUploadResult<Upload>>>;
|
|
224
248
|
}
|
|
225
249
|
|
|
@@ -273,6 +297,23 @@ const INITIAL_STATE = {
|
|
|
273
297
|
files: [],
|
|
274
298
|
} satisfies ReactUploadState<UploadDef>;
|
|
275
299
|
|
|
300
|
+
type UploadFailure = {
|
|
301
|
+
error: unknown;
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
type UploadOutcome<Result> = {
|
|
305
|
+
result?: Result;
|
|
306
|
+
uploadFailure?: UploadFailure;
|
|
307
|
+
callbackFailure?: UploadFailure;
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
function reportCallbackError(uploadName: string, error: unknown): void {
|
|
311
|
+
console.error(
|
|
312
|
+
`An upload lifecycle callback threw after the "${uploadName}" upload settled. Upload state was not changed.`,
|
|
313
|
+
error,
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
|
|
276
317
|
/**
|
|
277
318
|
* Create React hooks for a typed Beignet upload client.
|
|
278
319
|
*/
|
|
@@ -290,6 +331,8 @@ export function createReactUploads<Registry extends UploadClientRegistry>(
|
|
|
290
331
|
|
|
291
332
|
const abortRef = useRef<AbortController | null>(null);
|
|
292
333
|
const progressRef = useRef(new Map<number, FileProgress>());
|
|
334
|
+
const hookOptionsRef = useRef(hookOptions);
|
|
335
|
+
hookOptionsRef.current = hookOptions;
|
|
293
336
|
const [state, setState] = useState<ReactUploadState<Upload>>(
|
|
294
337
|
INITIAL_STATE as ReactUploadState<Upload>,
|
|
295
338
|
);
|
|
@@ -303,10 +346,10 @@ export function createReactUploads<Registry extends UploadClientRegistry>(
|
|
|
303
346
|
abortRef.current?.abort();
|
|
304
347
|
}, []);
|
|
305
348
|
|
|
306
|
-
const
|
|
349
|
+
const runUpload = useCallback(
|
|
307
350
|
async (
|
|
308
351
|
startOptions: ReactUploadStartOptions<Upload>,
|
|
309
|
-
): Promise<Result
|
|
352
|
+
): Promise<UploadOutcome<Result>> => {
|
|
310
353
|
abortRef.current?.abort();
|
|
311
354
|
const controller = new AbortController();
|
|
312
355
|
abortRef.current = controller;
|
|
@@ -318,7 +361,7 @@ export function createReactUploads<Registry extends UploadClientRegistry>(
|
|
|
318
361
|
onError: hookOnError,
|
|
319
362
|
onSettled: hookOnSettled,
|
|
320
363
|
...hookClientOptions
|
|
321
|
-
} =
|
|
364
|
+
} = hookOptionsRef.current;
|
|
322
365
|
const {
|
|
323
366
|
onFileBegin: startOnFileBegin,
|
|
324
367
|
onProgress: startOnProgress,
|
|
@@ -346,11 +389,14 @@ export function createReactUploads<Registry extends UploadClientRegistry>(
|
|
|
346
389
|
status: "preparing",
|
|
347
390
|
});
|
|
348
391
|
|
|
349
|
-
let
|
|
350
|
-
let
|
|
392
|
+
let result: Result | undefined;
|
|
393
|
+
let uploadFailure: UploadFailure | undefined;
|
|
351
394
|
|
|
395
|
+
// This try/catch governs hook state only from the upload client
|
|
396
|
+
// outcome. Lifecycle callbacks run after the state transition, so a
|
|
397
|
+
// throwing callback can never flip a settled upload status.
|
|
352
398
|
try {
|
|
353
|
-
|
|
399
|
+
result = (await uploads.upload(uploadName, {
|
|
354
400
|
...hookClientOptions,
|
|
355
401
|
...startClientOptions,
|
|
356
402
|
signal: controller.signal,
|
|
@@ -384,55 +430,114 @@ export function createReactUploads<Registry extends UploadClientRegistry>(
|
|
|
384
430
|
hookOnProgress?.(event);
|
|
385
431
|
startOnProgress?.(event);
|
|
386
432
|
},
|
|
387
|
-
});
|
|
433
|
+
})) as Result;
|
|
434
|
+
} catch (error) {
|
|
435
|
+
uploadFailure = { error };
|
|
436
|
+
}
|
|
388
437
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
438
|
+
externalSignal?.removeEventListener("abort", abortFromExternalSignal);
|
|
439
|
+
const finishedCurrentUpload = isCurrentUpload();
|
|
440
|
+
if (finishedCurrentUpload) {
|
|
441
|
+
abortRef.current = null;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const failure = uploadFailure;
|
|
445
|
+
if (finishedCurrentUpload) {
|
|
446
|
+
if (failure) {
|
|
447
|
+
setState((current) => ({
|
|
448
|
+
...current,
|
|
449
|
+
status: "error",
|
|
450
|
+
error: failure.error,
|
|
451
|
+
}));
|
|
452
|
+
} else {
|
|
453
|
+
const settledResult = result ?? null;
|
|
393
454
|
setState((current) => ({
|
|
394
455
|
...current,
|
|
395
456
|
status: "success",
|
|
396
457
|
progress: 100,
|
|
397
458
|
progressFraction: 1,
|
|
398
459
|
error: null,
|
|
399
|
-
result: settledResult
|
|
460
|
+
result: settledResult,
|
|
400
461
|
}));
|
|
401
462
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
status: "error",
|
|
411
|
-
error,
|
|
412
|
-
}));
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
let callbackFailure: UploadFailure | undefined;
|
|
466
|
+
const runCallback = async (callback: () => void | Promise<void>) => {
|
|
467
|
+
try {
|
|
468
|
+
await callback();
|
|
469
|
+
} catch (error) {
|
|
470
|
+
callbackFailure ??= { error };
|
|
413
471
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
if (failure) {
|
|
475
|
+
await runCallback(() => hookOnError?.(failure.error));
|
|
476
|
+
await runCallback(() => startOnError?.(failure.error));
|
|
477
|
+
await runCallback(() => hookOnSettled?.(undefined, failure.error));
|
|
478
|
+
await runCallback(() => startOnSettled?.(undefined, failure.error));
|
|
479
|
+
return { uploadFailure: failure, callbackFailure };
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const settledResult = result as Result;
|
|
483
|
+
await runCallback(() => hookOnSuccess?.(settledResult));
|
|
484
|
+
await runCallback(() => startOnSuccess?.(settledResult));
|
|
485
|
+
await runCallback(() => hookOnSettled?.(settledResult, undefined));
|
|
486
|
+
await runCallback(() => startOnSettled?.(settledResult, undefined));
|
|
487
|
+
return { result: settledResult, callbackFailure };
|
|
488
|
+
},
|
|
489
|
+
[uploadName],
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
const uploadAsync = useCallback(
|
|
493
|
+
async (
|
|
494
|
+
startOptions: ReactUploadStartOptions<Upload>,
|
|
495
|
+
): Promise<Result> => {
|
|
496
|
+
const outcome = await runUpload(startOptions);
|
|
497
|
+
if (outcome.uploadFailure) {
|
|
498
|
+
if (outcome.callbackFailure) {
|
|
499
|
+
reportCallbackError(uploadName, outcome.callbackFailure.error);
|
|
419
500
|
}
|
|
420
|
-
|
|
421
|
-
|
|
501
|
+
throw outcome.uploadFailure.error;
|
|
502
|
+
}
|
|
503
|
+
if (outcome.callbackFailure) {
|
|
504
|
+
throw outcome.callbackFailure.error;
|
|
422
505
|
}
|
|
506
|
+
return outcome.result as Result;
|
|
423
507
|
},
|
|
424
|
-
[
|
|
508
|
+
[runUpload, uploadName],
|
|
425
509
|
);
|
|
426
510
|
|
|
427
|
-
const
|
|
511
|
+
const upload = useCallback(
|
|
512
|
+
(startOptions: ReactUploadStartOptions<Upload>): void => {
|
|
513
|
+
void runUpload(startOptions).then((outcome) => {
|
|
514
|
+
if (outcome.callbackFailure) {
|
|
515
|
+
reportCallbackError(uploadName, outcome.callbackFailure.error);
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
},
|
|
519
|
+
[runUpload, uploadName],
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
const uploadFileAsync = useCallback(
|
|
428
523
|
(
|
|
429
524
|
file: File,
|
|
430
525
|
startOptions: ReactUploadFileStartOptions<Upload>,
|
|
431
526
|
): Promise<Result> =>
|
|
432
|
-
|
|
527
|
+
uploadAsync({
|
|
433
528
|
...startOptions,
|
|
434
529
|
files: [file],
|
|
435
530
|
}),
|
|
531
|
+
[uploadAsync],
|
|
532
|
+
);
|
|
533
|
+
|
|
534
|
+
const uploadFile = useCallback(
|
|
535
|
+
(file: File, startOptions: ReactUploadFileStartOptions<Upload>): void => {
|
|
536
|
+
upload({
|
|
537
|
+
...startOptions,
|
|
538
|
+
files: [file],
|
|
539
|
+
});
|
|
540
|
+
},
|
|
436
541
|
[upload],
|
|
437
542
|
);
|
|
438
543
|
|
|
@@ -455,11 +560,22 @@ export function createReactUploads<Registry extends UploadClientRegistry>(
|
|
|
455
560
|
isSuccess,
|
|
456
561
|
isError,
|
|
457
562
|
upload,
|
|
563
|
+
uploadAsync,
|
|
458
564
|
uploadFile,
|
|
565
|
+
uploadFileAsync,
|
|
459
566
|
abort,
|
|
460
567
|
reset,
|
|
461
568
|
};
|
|
462
|
-
}, [
|
|
569
|
+
}, [
|
|
570
|
+
state,
|
|
571
|
+
uploadName,
|
|
572
|
+
upload,
|
|
573
|
+
uploadAsync,
|
|
574
|
+
uploadFile,
|
|
575
|
+
uploadFileAsync,
|
|
576
|
+
abort,
|
|
577
|
+
reset,
|
|
578
|
+
]);
|
|
463
579
|
}
|
|
464
580
|
|
|
465
581
|
function useUploadMany<Name extends UploadClientName<Registry>>(
|
|
@@ -474,21 +590,40 @@ export function createReactUploads<Registry extends UploadClientRegistry>(
|
|
|
474
590
|
(
|
|
475
591
|
files: readonly File[],
|
|
476
592
|
startOptions: ReactUploadManyStartOptions<Upload>,
|
|
477
|
-
):
|
|
593
|
+
): void => {
|
|
478
594
|
controller.upload({
|
|
479
595
|
...startOptions,
|
|
480
596
|
files,
|
|
481
|
-
})
|
|
597
|
+
});
|
|
598
|
+
},
|
|
482
599
|
[controller.upload],
|
|
483
600
|
);
|
|
601
|
+
const uploadManyAsync = useCallback(
|
|
602
|
+
(
|
|
603
|
+
files: readonly File[],
|
|
604
|
+
startOptions: ReactUploadManyStartOptions<Upload>,
|
|
605
|
+
): Promise<Result> =>
|
|
606
|
+
controller.uploadAsync({
|
|
607
|
+
...startOptions,
|
|
608
|
+
files,
|
|
609
|
+
}),
|
|
610
|
+
[controller.uploadAsync],
|
|
611
|
+
);
|
|
484
612
|
|
|
485
|
-
return useMemo(
|
|
486
|
-
|
|
487
|
-
|
|
613
|
+
return useMemo(() => {
|
|
614
|
+
const {
|
|
615
|
+
upload: _upload,
|
|
616
|
+
uploadAsync: _uploadAsync,
|
|
617
|
+
uploadFile: _uploadFile,
|
|
618
|
+
uploadFileAsync: _uploadFileAsync,
|
|
619
|
+
...sharedController
|
|
620
|
+
} = controller;
|
|
621
|
+
return {
|
|
622
|
+
...sharedController,
|
|
488
623
|
upload: uploadMany,
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
);
|
|
624
|
+
uploadAsync: uploadManyAsync,
|
|
625
|
+
};
|
|
626
|
+
}, [controller, uploadMany, uploadManyAsync]);
|
|
492
627
|
}
|
|
493
628
|
|
|
494
629
|
return { useUpload, useUploadMany };
|