use-tus 0.7.3 → 0.8.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/README.md +46 -8
- package/dist/TusClientProvider/store/tucClientActions.d.ts +7 -24
- package/dist/TusClientProvider/store/tusClientReducer.d.ts +2 -8
- package/dist/TusClientProvider/types.d.ts +3 -2
- package/dist/__stories__/Basic.stories.d.ts +1 -2
- package/dist/__stories__/CacheKey.stories.d.ts +6 -0
- package/dist/__stories__/DefaultOptions.stories.d.ts +6 -0
- package/dist/__tests__/createUpload.test.d.ts +1 -0
- package/dist/__tests__/utils/createMock.d.ts +1 -0
- package/dist/__tests__/utils/getDefaultOptions.d.ts +2 -2
- package/dist/__tests__/utils/mock.d.ts +3 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +243 -153
- package/dist/types.d.ts +41 -0
- package/dist/useTus/index.d.ts +0 -2
- package/dist/useTus/useTus.d.ts +2 -2
- package/dist/useTusClient/useTusClient.d.ts +1 -1
- package/dist/useTusStore/index.d.ts +1 -0
- package/dist/useTusStore/useTusStore.d.ts +2 -0
- package/dist/utils/core/createUpload.d.ts +16 -0
- package/dist/utils/core/index.d.ts +3 -0
- package/dist/utils/core/splitTusHooksUploadOptions.d.ts +6 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/options/index.d.ts +2 -0
- package/dist/utils/options/mergeUseTusOptions.d.ts +8 -0
- package/dist/utils/options/useAutoAbort.d.ts +8 -0
- package/package.json +1 -1
- package/dist/useTus/types.d.ts +0 -14
- package/dist/useTus/useTusStore.d.ts +0 -2
- package/dist/useTus/utils/createUpload.d.ts +0 -7
- package/dist/useTus/utils/useAutoAbort.d.ts +0 -2
- package/dist/useTus/utils/useMergeTusOptions.d.ts +0 -6
- /package/dist/{useTus/utils → utils/core}/startOrResumeUpload.d.ts +0 -0
package/README.md
CHANGED
|
@@ -86,7 +86,7 @@ const Uploader = () => {
|
|
|
86
86
|
### `useTus` hooks
|
|
87
87
|
|
|
88
88
|
```tsx
|
|
89
|
-
const { upload, setUpload, isSuccess, isAborted, error, remove } = useTus({ autoAbort, autoStart, uploadOptions });
|
|
89
|
+
const { upload, setUpload, isSuccess, isAborted, isUploading, error, remove } = useTus({ autoAbort, autoStart, uploadOptions, Upload });
|
|
90
90
|
```
|
|
91
91
|
|
|
92
92
|
`useTus` is a hooks that creates an object to perform Resumable file upload.
|
|
@@ -98,9 +98,33 @@ const { upload, setUpload, isSuccess, isAborted, error, remove } = useTus({ auto
|
|
|
98
98
|
- `autoStart` (type: `boolean | undefined`) (default: false)
|
|
99
99
|
- Whether or not to start upload the file after `setUpload` function.
|
|
100
100
|
|
|
101
|
-
- `uploadOptions` (type: `
|
|
101
|
+
- `uploadOptions` (type: `TusHooksUploadFnOptions | undefined`) (default: undefined)
|
|
102
102
|
- Option to used by upload object that generated by that hooks.
|
|
103
|
-
|
|
103
|
+
|
|
104
|
+
- `Upload` (type: `Upload | undefined`) (default: undefined)
|
|
105
|
+
- Option to specify customized own Upload class with this hooks.
|
|
106
|
+
|
|
107
|
+
#### About `uploadOptions`
|
|
108
|
+
This option extends the UploadOptions provided by `tus-js-client`, but it has been extended so that every callback can receive the upload instance as the final argument.
|
|
109
|
+
|
|
110
|
+
For detail type information of `UploadOptions`, please see [here](https://github.com/tus/tus-js-client/blob/master/lib/index.d.ts#L22).
|
|
111
|
+
|
|
112
|
+
e.g.
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
setUplaod(file, {
|
|
116
|
+
onSuccess: (upload) => {
|
|
117
|
+
console.log(upload.url)
|
|
118
|
+
},
|
|
119
|
+
onError: (error, upload) => {
|
|
120
|
+
console.log(error)
|
|
121
|
+
|
|
122
|
+
setTimeout(() => {
|
|
123
|
+
upload.start()
|
|
124
|
+
}, 1000)
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
```
|
|
104
128
|
|
|
105
129
|
### Returns
|
|
106
130
|
- `upload` (type: `tus.Upload | undefined`)
|
|
@@ -108,7 +132,7 @@ const { upload, setUpload, isSuccess, isAborted, error, remove } = useTus({ auto
|
|
|
108
132
|
- This value is undefined unless the `setUpload` function called.
|
|
109
133
|
- For detail usage, please see [here](https://github.com/tus/tus-js-client#example)
|
|
110
134
|
|
|
111
|
-
- `setUpload` (type: `(file: tus.Upload['file'], options?:
|
|
135
|
+
- `setUpload` (type: `(file: tus.Upload['file'], options?: TusHooksUploadFnOptions) => void`)
|
|
112
136
|
- Function to create an `Upload`.
|
|
113
137
|
- The property specified in `uploadOptions` will be overwritten if property of `options` are speicified.
|
|
114
138
|
|
|
@@ -118,6 +142,9 @@ const { upload, setUpload, isSuccess, isAborted, error, remove } = useTus({ auto
|
|
|
118
142
|
- `isAborted` (type: `boolean`)
|
|
119
143
|
- Whether the upload was aborted or not.
|
|
120
144
|
|
|
145
|
+
- `isUploading` (type: `boolean`)
|
|
146
|
+
- Indicates if an uploading is in progress or not.
|
|
147
|
+
|
|
121
148
|
- `error` (type: `Error | undefined`)
|
|
122
149
|
- Error when upload fails.
|
|
123
150
|
|
|
@@ -127,7 +154,7 @@ const { upload, setUpload, isSuccess, isAborted, error, remove } = useTus({ auto
|
|
|
127
154
|
### `useTusStore` hooks
|
|
128
155
|
|
|
129
156
|
```tsx
|
|
130
|
-
const { upload, setUpload, isSuccess, isAborted, error, remove } = useTusStore(cacheKey, { autoAbort, autoStart, uploadOptions });
|
|
157
|
+
const { upload, setUpload, isSuccess, isAborted, isUploading, error, remove } = useTusStore(cacheKey, { autoAbort, autoStart, uploadOptions, Upload });
|
|
131
158
|
```
|
|
132
159
|
|
|
133
160
|
`useTusStore` is a hooks that creates an object for resumable file upload and stores it in a context.
|
|
@@ -146,9 +173,17 @@ This hooks is useful when you want to handle uploads across pages or components.
|
|
|
146
173
|
- `autoStart` (type: `boolean | undefined`) (default: false)
|
|
147
174
|
- Whether or not to start upload the file after `setUpload` function.
|
|
148
175
|
|
|
149
|
-
- `uploadOptions` (type: `
|
|
176
|
+
- `uploadOptions` (type: `TusHooksUploadFnOptions | undefined`) (default: undefined)
|
|
150
177
|
- Option to used by upload object that generated by that hooks.
|
|
151
|
-
- For detail type information of `
|
|
178
|
+
- For detail type information of `TusHooksUploadFnOptions`, please see [here](https://github.com/tus/tus-js-client/blob/master/lib/index.d.ts#L22).
|
|
179
|
+
|
|
180
|
+
- `Upload` (type: `Upload | undefined`) (default: undefined)
|
|
181
|
+
- Option to specify customized own Upload class with this hooks.
|
|
182
|
+
|
|
183
|
+
### Returns
|
|
184
|
+
- `upload` (type: `tus.Upload | undefined`)
|
|
185
|
+
- Object to be used when performing Resumable file upload.
|
|
186
|
+
- This value is undefined unless the `setUpload` function called.
|
|
152
187
|
|
|
153
188
|
### Returns
|
|
154
189
|
- `upload` (type: `tus.Upload | undefined`)
|
|
@@ -166,6 +201,9 @@ This hooks is useful when you want to handle uploads across pages or components.
|
|
|
166
201
|
- `isAborted` (type: `boolean`)
|
|
167
202
|
- Whether the upload was aborted or not.
|
|
168
203
|
|
|
204
|
+
- `isUploading` (type: `boolean`)
|
|
205
|
+
- Indicates if an uploading is in progress or not.
|
|
206
|
+
|
|
169
207
|
- `error` (type: `Error | undefined`)
|
|
170
208
|
- Error when upload fails.
|
|
171
209
|
|
|
@@ -185,7 +223,7 @@ This hooks is useful when you want to handle uploads across pages or components.
|
|
|
185
223
|
`TusClientProvider` is the provider that stores the `Upload` with `useTusStore` hooks.
|
|
186
224
|
|
|
187
225
|
### Props
|
|
188
|
-
- `defaultOptions` (type: `(file: tus.Upload['file']) =>
|
|
226
|
+
- `defaultOptions` (type: `(file: tus.Upload['file']) => TusHooksUploadFnOptions | undefined`)
|
|
189
227
|
- An object containing the default options used when creating a new upload. [detail](https://github.com/tus/tus-js-client/blob/master/docs/api.md#tusdefaultoptions)
|
|
190
228
|
|
|
191
229
|
### `useTusClient`
|
|
@@ -1,35 +1,18 @@
|
|
|
1
|
-
import type { Upload } from "tus-js-client";
|
|
2
1
|
import { DefaultOptions } from "../types";
|
|
3
|
-
|
|
4
|
-
export
|
|
2
|
+
import { TusTruthlyContext } from "../../types";
|
|
3
|
+
export type TusClientActions = ReturnType<typeof insertUploadInstance | typeof removeUploadInstance | typeof updateUploadContext | typeof resetClient | typeof updateDefaultOptions>;
|
|
4
|
+
export declare const insertUploadInstance: (cacheKey: string, state: TusTruthlyContext) => {
|
|
5
5
|
readonly type: "INSERT_UPLOAD_INSTANCE";
|
|
6
6
|
readonly payload: {
|
|
7
7
|
readonly cacheKey: string;
|
|
8
|
-
readonly uploadState:
|
|
9
|
-
readonly upload: Upload;
|
|
10
|
-
readonly isSuccess: false;
|
|
11
|
-
readonly isAborted: false;
|
|
12
|
-
};
|
|
8
|
+
readonly uploadState: TusTruthlyContext;
|
|
13
9
|
};
|
|
14
10
|
};
|
|
15
|
-
export declare const
|
|
16
|
-
readonly type: "
|
|
11
|
+
export declare const updateUploadContext: (cacheKey: string, context: Partial<TusTruthlyContext>) => {
|
|
12
|
+
readonly type: "UPDATE_UPLOAD_CONTEXT";
|
|
17
13
|
readonly payload: {
|
|
18
14
|
readonly cacheKey: string;
|
|
19
|
-
|
|
20
|
-
};
|
|
21
|
-
export declare const updateErrorUpload: (cacheKey: string, error?: Error) => {
|
|
22
|
-
readonly type: "UPDATE_ERROR_UPLOAD";
|
|
23
|
-
readonly payload: {
|
|
24
|
-
readonly cacheKey: string;
|
|
25
|
-
readonly error: Error | undefined;
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
export declare const updateIsAbortedUpload: (cacheKey: string, isAborted: boolean) => {
|
|
29
|
-
readonly type: "UPDATE_IS_ABORTED_UPLOAD";
|
|
30
|
-
readonly payload: {
|
|
31
|
-
readonly cacheKey: string;
|
|
32
|
-
readonly isAborted: boolean;
|
|
15
|
+
readonly context: Partial<TusTruthlyContext>;
|
|
33
16
|
};
|
|
34
17
|
};
|
|
35
18
|
export declare const removeUploadInstance: (cacheKey: string) => {
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import type { Reducer } from "react";
|
|
2
|
-
import type { Upload } from "tus-js-client";
|
|
3
2
|
import { DefaultOptions } from "../types";
|
|
4
3
|
import { TusClientActions } from "./tucClientActions";
|
|
5
|
-
|
|
6
|
-
upload: Upload | undefined;
|
|
7
|
-
isSuccess: boolean;
|
|
8
|
-
isAborted: boolean;
|
|
9
|
-
error?: Error;
|
|
10
|
-
};
|
|
4
|
+
import { TusTruthlyContext } from "../../types";
|
|
11
5
|
export type TusClientState = {
|
|
12
6
|
uploads: {
|
|
13
|
-
[cacheKey: string]:
|
|
7
|
+
[cacheKey: string]: TusTruthlyContext | undefined;
|
|
14
8
|
};
|
|
15
9
|
defaultOptions: DefaultOptions | undefined;
|
|
16
10
|
};
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import { Upload
|
|
2
|
-
|
|
1
|
+
import { Upload } from "tus-js-client";
|
|
2
|
+
import { TusHooksUploadOptions } from "../types";
|
|
3
|
+
export type DefaultOptions = (file: Upload["file"]) => TusHooksUploadOptions;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createMock<T>(value?: unknown): T;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const getDefaultOptions: () =>
|
|
1
|
+
import { TusHooksUploadOptions } from "../../types";
|
|
2
|
+
export declare const getDefaultOptions: () => TusHooksUploadOptions;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/// <reference types="jest" />
|
|
2
|
+
import type { Upload } from "tus-js-client";
|
|
3
|
+
export declare const createUploadMock: (start: jest.Mock, abort: jest.Mock) => typeof Upload;
|
|
2
4
|
export declare const createConsoleErrorMock: () => jest.SpyInstance<void, [message?: any, ...optionalParams: any[]], any>;
|
|
3
5
|
export declare const insertEnvValue: (value: NodeJS.Process["env"]) => void;
|
|
4
|
-
export declare const startOrResumeUploadMock: jest.SpyInstance<void, [upload:
|
|
6
|
+
export declare const startOrResumeUploadMock: jest.SpyInstance<void, [upload: Upload], any>;
|
package/dist/index.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var r=require("react"),h=require("tus-js-client");const V=Object.freeze({autoAbort:!0,autoStart:!1,uploadOptions:void 0,Upload:h.Upload}),D=o=>({...V,...o}),m=({upload:o,abort:t,autoAbort:e})=>{r.useEffect(()=>{const s=async()=>{!o||!t||await t()};return()=>{e&&s()}},[e,o])},q=(o,t,e)=>{let s=o[e];const a=Object.getOwnPropertyDescriptor(o,e);Object.defineProperty(o,e,{get(){return a?.get?.()??s},set(n){a?.set?a.set.call(o,n):s=n,t(this)}})},I=({Upload:o,file:t,uploadOptions:e,uploadFnOptions:s,onChange:a,onStart:n,onAbort:d})=>{const u=new o(t,e),i=u.start.bind(u),l=u.abort.bind(u),U=()=>{i(),n()},E=async()=>{l(),d()};return u.start=U,u.abort=E,q(u,a,"url"),Object.entries(s).forEach(([A,p])=>{if(typeof p!="function")return;const c=(...O)=>p(...O,u);u.options[A]=c}),{upload:u,originalStart:i,originalAbort:l}};function R(o){const t=Object.entries(o).reduce((s,[a,n])=>({...s,[a]:typeof n!="function"?n:void 0}),{}),e=Object.entries(o).reduce((s,[a,n])=>({...s,[a]:typeof n=="function"?n:void 0}),{});return{uploadOptions:t,uploadFnOptions:e}}const F=o=>{o.findPreviousUploads().then(t=>{t.length&&o.resumeFromPreviousUpload(t[0]),o.start()})},w=Object.freeze({upload:void 0,isSuccess:!1,isAborted:!1,isUploading:!1,error:void 0}),z=(o={})=>{const{autoAbort:t,autoStart:e,uploadOptions:s,Upload:a}=D(o),[n,d]=r.useState(w),[u,i]=r.useState({originalAbort:void 0}),l=p=>{d(c=>c.upload===void 0?c:{...c,...p})},U=r.useCallback((p,c={})=>{const O={...s,...c};function T(){l({isSuccess:!0,isUploading:!1}),O?.onSuccess?.(b)}const v={...O,onSuccess:T,onError:f=>{l({error:f,isUploading:!1}),O?.onError?.(f,b)}},g=f=>{d(K=>({...K,upload:f}))},y=()=>{l({isUploading:!0,isAborted:!1})},N=()=>{l({isUploading:!1,isAborted:!0})},{uploadOptions:_,uploadFnOptions:S}=R(v),{upload:b,originalAbort:H}=I({Upload:a,file:p,uploadOptions:_,uploadFnOptions:S,onChange:g,onStart:y,onAbort:N});e&&F(b),d({upload:b,error:void 0,isSuccess:!1,isAborted:!1,isUploading:!1}),i({originalAbort:H})},[a,e,s]),E=r.useCallback(()=>{u?.originalAbort?.(),d(w),i({originalAbort:void 0})},[u]),A={...n,setUpload:U,remove:E};return m({upload:A.upload,abort:u.originalAbort,autoAbort:t??!1}),A},P={tusClientHasNotFounded:"No TusClient set, use TusClientProvider to set one",tusIsNotSupported:"This browser does not support uploads. Please use a modern browser instead."},x=r.createContext(void 0),L=r.createContext(void 0),k=()=>{const o=r.useContext(x);if(!o&&process.env.NODE_ENV!=="production")throw new Error(P.tusClientHasNotFounded);return r.useMemo(()=>o,[o])},j=()=>{const o=r.useContext(L);if(!o&&process.env.NODE_ENV!=="production")throw new Error(P.tusClientHasNotFounded);return r.useMemo(()=>o,[o])},X=(o,t)=>({type:"INSERT_UPLOAD_INSTANCE",payload:{cacheKey:o,uploadState:t}}),C=(o,t)=>({type:"UPDATE_UPLOAD_CONTEXT",payload:{cacheKey:o,context:t}}),M=o=>({type:"REMOVE_UPLOAD_INSTANCE",payload:{cacheKey:o}}),G=()=>({type:"RESET_CLIENT"}),J=o=>({type:"UPDATE_DEFAULT_OPTIONS",payload:{defaultOptions:o}}),B=(o,t={})=>{const{autoAbort:e,autoStart:s,uploadOptions:a,Upload:n}=D(t),{defaultOptions:d,uploads:u}=k(),i=j(),l=r.useCallback((p,c={})=>{const O={...d?.(p),...a,...c},T={...O,onSuccess:()=>{i(C(o,{isSuccess:!0,isUploading:!1})),O?.onSuccess?.(S)},onError:b=>{i(C(o,{error:b,isUploading:!1})),O?.onError?.(b,S)}},v=b=>{i(C(o,{upload:b}))},g=()=>{i(C(o,{isAborted:!1,isUploading:!0}))},y=()=>{i(C(o,{isAborted:!0,isUploading:!1}))},{uploadOptions:N,uploadFnOptions:_}=R(T),{upload:S}=I({Upload:n,file:p,uploadOptions:N,uploadFnOptions:_,onChange:v,onStart:g,onAbort:y});s&&F(S),i(X(o,{upload:S,error:void 0,isSuccess:!1,isAborted:!1,isUploading:!1}))},[n,s,o,d,a,i]),U=r.useMemo(()=>u[o],[o,u]),E=r.useCallback(()=>{U?.upload?.abort(),i(M(o))},[U,i,o]),A=U?{...U,setUpload:l,remove:E}:{upload:void 0,error:void 0,isSuccess:!1,isAborted:!1,isUploading:!1,setUpload:l,remove:E};return m({upload:A.upload,abort:A.upload?.abort,autoAbort:e??!1}),A},Q=()=>{const o=k(),t=j(),e=o.uploads,s=r.useCallback(n=>{t(M(n))},[t]),a=r.useCallback(()=>t(G()),[t]);return{state:e,removeUpload:s,reset:a}},W=(o,t)=>{switch(t.type){case"INSERT_UPLOAD_INSTANCE":{const{cacheKey:e,uploadState:s}=t.payload;return{...o,uploads:{...o.uploads,[e]:s}}}case"UPDATE_UPLOAD_CONTEXT":{const{cacheKey:e,context:s}=t.payload,a=o.uploads[e];return a?{...o,uploads:{...o.uploads,[e]:{...a,...s}}}:o}case"REMOVE_UPLOAD_INSTANCE":{const{cacheKey:e}=t.payload,s=o.uploads;return delete s[e],{...o,uploads:s}}case"UPDATE_DEFAULT_OPTIONS":{const{defaultOptions:e}=t.payload;return{...o,defaultOptions:e}}case"RESET_CLIENT":return{...o,uploads:{}};default:return o}},Y={uploads:{},defaultOptions:void 0},Z=({defaultOptions:o,children:t})=>{const[e,s]=r.useReducer(W,{...Y,defaultOptions:o});r.useEffect(()=>{h.isSupported||process.env.NODE_ENV==="production"||console.error(P.tusIsNotSupported)},[]),r.useEffect(()=>{e.defaultOptions!==o&&s(J(o))},[o,e.defaultOptions]);const a=r.createElement(L.Provider,{value:s},t);return r.createElement(x.Provider,{value:e},a)};exports.TusClientProvider=Z,exports.useTus=z,exports.useTusClient=Q,exports.useTusStore=B;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export * from "./useTus";
|
|
2
|
+
export * from "./useTusStore";
|
|
3
|
+
export * from "./useTusClient";
|
|
2
4
|
export * from "./TusClientProvider";
|
|
3
|
-
export type {
|
|
5
|
+
export type { TusHooksResult, TusHooksOptions, TusHooksUploadFnOptions, TusHooksUploadOptions, } from "./types";
|
package/dist/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useEffect as
|
|
1
|
+
import{useEffect as D,useState as R,useCallback as T,createContext as F,useContext as w,useMemo as m,useReducer as B,createElement as L}from"react";import{Upload as J,isSupported as Q}from"tus-js-client";const W=Object.freeze({autoAbort:!0,autoStart:!1,uploadOptions:void 0,Upload:J}),x=o=>({...W,...o}),j=({upload:o,abort:t,autoAbort:e})=>{D(()=>{const s=async()=>{!o||!t||await t()};return()=>{e&&s()}},[e,o])},Y=(o,t,e)=>{let s=o[e];const n=Object.getOwnPropertyDescriptor(o,e);Object.defineProperty(o,e,{get(){var r,d;return(d=(r=n==null?void 0:n.get)==null?void 0:r.call(n))!=null?d:s},set(r){n!=null&&n.set?n.set.call(o,r):s=r,t(this)}})},K=({Upload:o,file:t,uploadOptions:e,uploadFnOptions:s,onChange:n,onStart:r,onAbort:d})=>{const a=new o(t,e),E=a.start.bind(a),l=a.abort.bind(a),S=()=>{E(),r()},O=async()=>{l(),d()};return a.start=S,a.abort=O,Y(a,n,"url"),Object.entries(s).forEach(([A,u])=>{if(typeof u!="function")return;const i=(...p)=>u(...p,a);a.options[A]=i}),{upload:a,originalStart:E,originalAbort:l}};function H(o){const t=Object.entries(o).reduce((s,[n,r])=>({...s,[n]:typeof r!="function"?r:void 0}),{}),e=Object.entries(o).reduce((s,[n,r])=>({...s,[n]:typeof r=="function"?r:void 0}),{});return{uploadOptions:t,uploadFnOptions:e}}const V=o=>{o.findPreviousUploads().then(t=>{t.length&&o.resumeFromPreviousUpload(t[0]),o.start()})},k=Object.freeze({upload:void 0,isSuccess:!1,isAborted:!1,isUploading:!1,error:void 0}),Z=(o={})=>{const{autoAbort:t,autoStart:e,uploadOptions:s,Upload:n}=x(o),[r,d]=R(k),[a,E]=R({originalAbort:void 0}),l=u=>{d(i=>i.upload===void 0?i:{...i,...u})},S=T((u,i={})=>{const p={...s,...i};function v(){var c;l({isSuccess:!0,isUploading:!1}),(c=p==null?void 0:p.onSuccess)==null||c.call(p,b)}const g={...p,onSuccess:v,onError:c=>{var C;l({error:c,isUploading:!1}),(C=p==null?void 0:p.onError)==null||C.call(p,c,b)}},y=c=>{d(C=>({...C,upload:c}))},N=()=>{l({isUploading:!0,isAborted:!1})},_=()=>{l({isUploading:!1,isAborted:!0})},{uploadOptions:h,uploadFnOptions:P}=H(g),{upload:b,originalAbort:U}=K({Upload:n,file:u,uploadOptions:h,uploadFnOptions:P,onChange:y,onStart:N,onAbort:_});e&&V(b),d({upload:b,error:void 0,isSuccess:!1,isAborted:!1,isUploading:!1}),E({originalAbort:U})},[n,e,s]),O=T(()=>{var u;(u=a==null?void 0:a.originalAbort)==null||u.call(a),d(k),E({originalAbort:void 0})},[a]),A={...r,setUpload:S,remove:O};return j({upload:A.upload,abort:a.originalAbort,autoAbort:t!=null?t:!1}),A},I={tusClientHasNotFounded:"No TusClient set, use TusClientProvider to set one",tusIsNotSupported:"This browser does not support uploads. Please use a modern browser instead."},M=F(void 0),z=F(void 0),X=()=>{const o=w(M);if(!o&&process.env.NODE_ENV!=="production")throw new Error(I.tusClientHasNotFounded);return m(()=>o,[o])},G=()=>{const o=w(z);if(!o&&process.env.NODE_ENV!=="production")throw new Error(I.tusClientHasNotFounded);return m(()=>o,[o])},$=(o,t)=>({type:"INSERT_UPLOAD_INSTANCE",payload:{cacheKey:o,uploadState:t}}),f=(o,t)=>({type:"UPDATE_UPLOAD_CONTEXT",payload:{cacheKey:o,context:t}}),q=o=>({type:"REMOVE_UPLOAD_INSTANCE",payload:{cacheKey:o}}),oo=()=>({type:"RESET_CLIENT"}),to=o=>({type:"UPDATE_DEFAULT_OPTIONS",payload:{defaultOptions:o}}),eo=(o,t={})=>{var e;const{autoAbort:s,autoStart:n,uploadOptions:r,Upload:d}=x(t),{defaultOptions:a,uploads:E}=X(),l=G(),S=T((i,p={})=>{const v={...a==null?void 0:a(i),...r,...p},g={...v,onSuccess:()=>{var U;l(f(o,{isSuccess:!0,isUploading:!1})),(U=v==null?void 0:v.onSuccess)==null||U.call(v,b)},onError:U=>{var c;l(f(o,{error:U,isUploading:!1})),(c=v==null?void 0:v.onError)==null||c.call(v,U,b)}},y=U=>{l(f(o,{upload:U}))},N=()=>{l(f(o,{isAborted:!1,isUploading:!0}))},_=()=>{l(f(o,{isAborted:!0,isUploading:!1}))},{uploadOptions:h,uploadFnOptions:P}=H(g),{upload:b}=K({Upload:d,file:i,uploadOptions:h,uploadFnOptions:P,onChange:y,onStart:N,onAbort:_});n&&V(b),l($(o,{upload:b,error:void 0,isSuccess:!1,isAborted:!1,isUploading:!1}))},[d,n,o,a,r,l]),O=m(()=>E[o],[o,E]),A=T(()=>{var i;(i=O==null?void 0:O.upload)==null||i.abort(),l(q(o))},[O,l,o]),u=O?{...O,setUpload:S,remove:A}:{upload:void 0,error:void 0,isSuccess:!1,isAborted:!1,isUploading:!1,setUpload:S,remove:A};return j({upload:u.upload,abort:(e=u.upload)==null?void 0:e.abort,autoAbort:s!=null?s:!1}),u},so=()=>{const o=X(),t=G(),e=o.uploads,s=T(r=>{t(q(r))},[t]),n=T(()=>t(oo()),[t]);return{state:e,removeUpload:s,reset:n}},no=(o,t)=>{switch(t.type){case"INSERT_UPLOAD_INSTANCE":{const{cacheKey:e,uploadState:s}=t.payload;return{...o,uploads:{...o.uploads,[e]:s}}}case"UPDATE_UPLOAD_CONTEXT":{const{cacheKey:e,context:s}=t.payload,n=o.uploads[e];return n?{...o,uploads:{...o.uploads,[e]:{...n,...s}}}:o}case"REMOVE_UPLOAD_INSTANCE":{const{cacheKey:e}=t.payload,s=o.uploads;return delete s[e],{...o,uploads:s}}case"UPDATE_DEFAULT_OPTIONS":{const{defaultOptions:e}=t.payload;return{...o,defaultOptions:e}}case"RESET_CLIENT":return{...o,uploads:{}};default:return o}},ro={uploads:{},defaultOptions:void 0},ao=({defaultOptions:o,children:t})=>{const[e,s]=B(no,{...ro,defaultOptions:o});D(()=>{Q||process.env.NODE_ENV==="production"||console.error(I.tusIsNotSupported)},[]),D(()=>{e.defaultOptions!==o&&s(to(o))},[o,e.defaultOptions]);const n=L(z.Provider,{value:s},t);return L(M.Provider,{value:e},n)};export{ao as TusClientProvider,Z as useTus,so as useTusClient,eo as useTusStore};
|
package/dist/index.js
CHANGED
|
@@ -1,23 +1,93 @@
|
|
|
1
|
-
import { useEffect,
|
|
1
|
+
import { useEffect, useState, useCallback, createContext, useContext, useMemo, useReducer, createElement } from 'react';
|
|
2
2
|
import { Upload, isSupported } from 'tus-js-client';
|
|
3
3
|
|
|
4
|
-
const
|
|
5
|
-
|
|
4
|
+
const defaultUseTusOptionsValue = Object.freeze({
|
|
5
|
+
autoAbort: true,
|
|
6
|
+
autoStart: false,
|
|
7
|
+
uploadOptions: undefined,
|
|
8
|
+
Upload,
|
|
9
|
+
});
|
|
10
|
+
const mergeUseTusOptions = (options) => ({
|
|
11
|
+
...defaultUseTusOptionsValue,
|
|
12
|
+
...options,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const useAutoAbort = ({ upload, abort, autoAbort, }) => {
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const abortUploading = async () => {
|
|
18
|
+
if (!upload || !abort) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
await abort();
|
|
22
|
+
};
|
|
23
|
+
return () => {
|
|
24
|
+
if (!autoAbort) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
abortUploading();
|
|
28
|
+
};
|
|
29
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
30
|
+
}, [autoAbort, upload]);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const bindOnChange = (upload, onChange, key) => {
|
|
34
|
+
let property = upload[key];
|
|
35
|
+
const originalUrlDescriptor = Object.getOwnPropertyDescriptor(upload, key);
|
|
36
|
+
Object.defineProperty(upload, key, {
|
|
37
|
+
get() {
|
|
38
|
+
return originalUrlDescriptor?.get?.() ?? property;
|
|
39
|
+
},
|
|
40
|
+
set(value) {
|
|
41
|
+
if (originalUrlDescriptor?.set) {
|
|
42
|
+
originalUrlDescriptor.set.call(upload, value);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
property = value;
|
|
46
|
+
}
|
|
47
|
+
onChange(this);
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
const createUpload = ({ Upload, file, uploadOptions, uploadFnOptions, onChange, onStart, onAbort, }) => {
|
|
52
|
+
const upload = new Upload(file, uploadOptions);
|
|
6
53
|
const originalStart = upload.start.bind(upload);
|
|
7
54
|
const originalAbort = upload.abort.bind(upload);
|
|
8
55
|
const start = () => {
|
|
9
56
|
originalStart();
|
|
10
|
-
|
|
57
|
+
onStart();
|
|
11
58
|
};
|
|
12
59
|
const abort = async () => {
|
|
13
60
|
originalAbort();
|
|
14
|
-
|
|
61
|
+
onAbort();
|
|
15
62
|
};
|
|
16
63
|
upload.start = start;
|
|
17
64
|
upload.abort = abort;
|
|
65
|
+
bindOnChange(upload, onChange, "url");
|
|
66
|
+
Object.entries(uploadFnOptions).forEach(([key, value]) => {
|
|
67
|
+
if (typeof value !== "function") {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const bindedFn = (...args) => value(...args, upload);
|
|
71
|
+
upload.options[key] = bindedFn;
|
|
72
|
+
});
|
|
18
73
|
return { upload, originalStart, originalAbort };
|
|
19
74
|
};
|
|
20
75
|
|
|
76
|
+
function splitTusHooksUploadOptions(options) {
|
|
77
|
+
const uploadOptions = Object.entries(options).reduce((acc, [key, value]) => ({
|
|
78
|
+
...acc,
|
|
79
|
+
[key]: typeof value !== "function" ? value : undefined,
|
|
80
|
+
}), {});
|
|
81
|
+
const uploadFnOptions = Object.entries(options).reduce((acc, [key, value]) => ({
|
|
82
|
+
...acc,
|
|
83
|
+
[key]: typeof value === "function" ? value : undefined,
|
|
84
|
+
}), {});
|
|
85
|
+
return {
|
|
86
|
+
uploadOptions,
|
|
87
|
+
uploadFnOptions,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
21
91
|
const startOrResumeUpload = (upload) => {
|
|
22
92
|
upload.findPreviousUploads().then((previousUploads) => {
|
|
23
93
|
if (previousUploads.length) {
|
|
@@ -27,91 +97,97 @@ const startOrResumeUpload = (upload) => {
|
|
|
27
97
|
});
|
|
28
98
|
};
|
|
29
99
|
|
|
30
|
-
const
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
const abortUploading = async () => {
|
|
33
|
-
if (!upload || !abort) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
await abort();
|
|
37
|
-
};
|
|
38
|
-
return () => {
|
|
39
|
-
if (!autoAbort) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
abortUploading();
|
|
43
|
-
};
|
|
44
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
45
|
-
}, [autoAbort, upload]);
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const defaultUseTusOptionsValue = Object.freeze({
|
|
49
|
-
autoAbort: true,
|
|
50
|
-
autoStart: false,
|
|
51
|
-
});
|
|
52
|
-
const useMergeTusOptions = (options) => useMemo(() => ({
|
|
53
|
-
...defaultUseTusOptionsValue,
|
|
54
|
-
...(options || {}),
|
|
55
|
-
}), [options]);
|
|
56
|
-
|
|
57
|
-
const initialUseTusState = Object.freeze({
|
|
100
|
+
const initialTusContext = Object.freeze({
|
|
58
101
|
upload: undefined,
|
|
59
102
|
isSuccess: false,
|
|
60
103
|
isAborted: false,
|
|
104
|
+
isUploading: false,
|
|
61
105
|
error: undefined,
|
|
62
|
-
originalAbort: undefined,
|
|
63
106
|
});
|
|
64
|
-
const useTus = (baseOption) => {
|
|
65
|
-
const { autoAbort, autoStart, uploadOptions } =
|
|
66
|
-
const [
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
107
|
+
const useTus = (baseOption = {}) => {
|
|
108
|
+
const { autoAbort, autoStart, uploadOptions: baseUploadOptions, Upload, } = mergeUseTusOptions(baseOption);
|
|
109
|
+
const [tusContext, setTusContext] = useState(initialTusContext);
|
|
110
|
+
const [tusInternalState, setTusInternalState] = useState({
|
|
111
|
+
originalAbort: undefined,
|
|
112
|
+
});
|
|
113
|
+
const updateTusTruthlyContext = (context) => {
|
|
114
|
+
setTusContext((prev) => {
|
|
115
|
+
if (prev.upload === undefined) {
|
|
116
|
+
return prev; // TODO: Add appriopriate error handling
|
|
117
|
+
}
|
|
118
|
+
return { ...prev, ...context };
|
|
119
|
+
});
|
|
120
|
+
};
|
|
73
121
|
const setUpload = useCallback((file, options = {}) => {
|
|
74
122
|
const targetOptions = {
|
|
75
|
-
...
|
|
123
|
+
...baseUploadOptions,
|
|
76
124
|
...options,
|
|
77
125
|
};
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
targetOptions?.onSuccess?.();
|
|
81
|
-
}
|
|
126
|
+
function onSuccess() {
|
|
127
|
+
updateTusTruthlyContext({ isSuccess: true, isUploading: false });
|
|
128
|
+
targetOptions?.onSuccess?.(upload);
|
|
129
|
+
}
|
|
82
130
|
const onError = (error) => {
|
|
83
|
-
|
|
84
|
-
|
|
131
|
+
updateTusTruthlyContext({
|
|
132
|
+
error,
|
|
133
|
+
isUploading: false,
|
|
134
|
+
});
|
|
135
|
+
targetOptions?.onError?.(error, upload);
|
|
85
136
|
};
|
|
86
137
|
const mergedUploadOptions = {
|
|
87
138
|
...targetOptions,
|
|
88
139
|
onSuccess,
|
|
89
140
|
onError,
|
|
90
141
|
};
|
|
91
|
-
const
|
|
92
|
-
|
|
142
|
+
const onChange = (newUpload) => {
|
|
143
|
+
// For re-rendering when `upload` object is changed.
|
|
144
|
+
setTusContext((prev) => ({ ...prev, upload: newUpload }));
|
|
145
|
+
};
|
|
146
|
+
const onStart = () => {
|
|
147
|
+
updateTusTruthlyContext({ isUploading: true, isAborted: false });
|
|
93
148
|
};
|
|
94
|
-
const
|
|
149
|
+
const onAbort = () => {
|
|
150
|
+
updateTusTruthlyContext({ isUploading: false, isAborted: true });
|
|
151
|
+
};
|
|
152
|
+
const { uploadOptions, uploadFnOptions } = splitTusHooksUploadOptions(mergedUploadOptions);
|
|
153
|
+
const { upload, originalAbort } = createUpload({
|
|
154
|
+
Upload,
|
|
155
|
+
file,
|
|
156
|
+
uploadOptions,
|
|
157
|
+
uploadFnOptions,
|
|
158
|
+
onChange,
|
|
159
|
+
onStart,
|
|
160
|
+
onAbort,
|
|
161
|
+
});
|
|
95
162
|
if (autoStart) {
|
|
96
163
|
startOrResumeUpload(upload);
|
|
97
164
|
}
|
|
98
|
-
|
|
99
|
-
|
|
165
|
+
setTusContext({
|
|
166
|
+
upload,
|
|
167
|
+
error: undefined,
|
|
168
|
+
isSuccess: false,
|
|
169
|
+
isAborted: false,
|
|
170
|
+
isUploading: false,
|
|
171
|
+
});
|
|
172
|
+
setTusInternalState({ originalAbort });
|
|
173
|
+
}, [Upload, autoStart, baseUploadOptions]);
|
|
100
174
|
const remove = useCallback(() => {
|
|
101
175
|
// `upload.abort` function will set `isAborted` state.
|
|
102
176
|
// So call the original function for restore state.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
error: tusState?.error,
|
|
110
|
-
isAborted: tusState?.isAborted ?? false,
|
|
177
|
+
tusInternalState?.originalAbort?.();
|
|
178
|
+
setTusContext(initialTusContext);
|
|
179
|
+
setTusInternalState({ originalAbort: undefined });
|
|
180
|
+
}, [tusInternalState]);
|
|
181
|
+
const tusResult = {
|
|
182
|
+
...tusContext,
|
|
111
183
|
setUpload,
|
|
112
184
|
remove,
|
|
113
|
-
}
|
|
114
|
-
useAutoAbort(
|
|
185
|
+
};
|
|
186
|
+
useAutoAbort({
|
|
187
|
+
upload: tusResult.upload,
|
|
188
|
+
abort: tusInternalState.originalAbort,
|
|
189
|
+
autoAbort: autoAbort ?? false,
|
|
190
|
+
});
|
|
115
191
|
return tusResult;
|
|
116
192
|
};
|
|
117
193
|
|
|
@@ -137,35 +213,18 @@ const useTusClientDispatch = () => {
|
|
|
137
213
|
return useMemo(() => tusClientDispatch, [tusClientDispatch]);
|
|
138
214
|
};
|
|
139
215
|
|
|
140
|
-
const insertUploadInstance = (cacheKey,
|
|
216
|
+
const insertUploadInstance = (cacheKey, state) => ({
|
|
141
217
|
type: "INSERT_UPLOAD_INSTANCE",
|
|
142
218
|
payload: {
|
|
143
219
|
cacheKey,
|
|
144
|
-
uploadState:
|
|
145
|
-
upload,
|
|
146
|
-
isSuccess: false,
|
|
147
|
-
isAborted: false,
|
|
148
|
-
},
|
|
220
|
+
uploadState: state,
|
|
149
221
|
},
|
|
150
222
|
});
|
|
151
|
-
const
|
|
152
|
-
type: "
|
|
223
|
+
const updateUploadContext = (cacheKey, context) => ({
|
|
224
|
+
type: "UPDATE_UPLOAD_CONTEXT",
|
|
153
225
|
payload: {
|
|
154
226
|
cacheKey,
|
|
155
|
-
|
|
156
|
-
});
|
|
157
|
-
const updateErrorUpload = (cacheKey, error) => ({
|
|
158
|
-
type: "UPDATE_ERROR_UPLOAD",
|
|
159
|
-
payload: {
|
|
160
|
-
cacheKey,
|
|
161
|
-
error,
|
|
162
|
-
},
|
|
163
|
-
});
|
|
164
|
-
const updateIsAbortedUpload = (cacheKey, isAborted) => ({
|
|
165
|
-
type: "UPDATE_IS_ABORTED_UPLOAD",
|
|
166
|
-
payload: {
|
|
167
|
-
cacheKey,
|
|
168
|
-
isAborted,
|
|
227
|
+
context,
|
|
169
228
|
},
|
|
170
229
|
});
|
|
171
230
|
const removeUploadInstance = (cacheKey) => ({
|
|
@@ -174,6 +233,9 @@ const removeUploadInstance = (cacheKey) => ({
|
|
|
174
233
|
cacheKey,
|
|
175
234
|
},
|
|
176
235
|
});
|
|
236
|
+
const resetClient = () => ({
|
|
237
|
+
type: "RESET_CLIENT",
|
|
238
|
+
});
|
|
177
239
|
const updateDefaultOptions = (defaultOptions) => ({
|
|
178
240
|
type: "UPDATE_DEFAULT_OPTIONS",
|
|
179
241
|
payload: {
|
|
@@ -181,55 +243,116 @@ const updateDefaultOptions = (defaultOptions) => ({
|
|
|
181
243
|
},
|
|
182
244
|
});
|
|
183
245
|
|
|
184
|
-
const useTusStore = (cacheKey, baseOption) => {
|
|
185
|
-
const { autoAbort, autoStart, uploadOptions } =
|
|
246
|
+
const useTusStore = (cacheKey, baseOption = {}) => {
|
|
247
|
+
const { autoAbort, autoStart, uploadOptions: defaultUploadOptions, Upload, } = mergeUseTusOptions(baseOption);
|
|
186
248
|
const { defaultOptions, uploads } = useTusClientState();
|
|
187
249
|
const tusClientDispatch = useTusClientDispatch();
|
|
188
250
|
const setUpload = useCallback((file, options = {}) => {
|
|
189
251
|
const targetOptions = {
|
|
190
252
|
...defaultOptions?.(file),
|
|
191
|
-
...
|
|
253
|
+
...defaultUploadOptions,
|
|
192
254
|
...options,
|
|
193
255
|
};
|
|
194
256
|
const onSuccess = () => {
|
|
195
|
-
tusClientDispatch(
|
|
196
|
-
targetOptions?.onSuccess?.();
|
|
257
|
+
tusClientDispatch(updateUploadContext(cacheKey, { isSuccess: true, isUploading: false }));
|
|
258
|
+
targetOptions?.onSuccess?.(upload);
|
|
197
259
|
};
|
|
198
260
|
const onError = (error) => {
|
|
199
|
-
tusClientDispatch(
|
|
200
|
-
targetOptions?.onError?.(error);
|
|
261
|
+
tusClientDispatch(updateUploadContext(cacheKey, { error, isUploading: false }));
|
|
262
|
+
targetOptions?.onError?.(error, upload);
|
|
201
263
|
};
|
|
202
264
|
const mergedUploadOptions = {
|
|
203
265
|
...targetOptions,
|
|
204
266
|
onSuccess,
|
|
205
267
|
onError,
|
|
206
268
|
};
|
|
207
|
-
const
|
|
208
|
-
|
|
269
|
+
const onChange = (newUpload) => {
|
|
270
|
+
// For re-rendering when `upload` object is changed.
|
|
271
|
+
tusClientDispatch(updateUploadContext(cacheKey, { upload: newUpload }));
|
|
209
272
|
};
|
|
210
|
-
const
|
|
273
|
+
const onStart = () => {
|
|
274
|
+
tusClientDispatch(updateUploadContext(cacheKey, {
|
|
275
|
+
isAborted: false,
|
|
276
|
+
isUploading: true,
|
|
277
|
+
}));
|
|
278
|
+
};
|
|
279
|
+
const onAbort = () => {
|
|
280
|
+
tusClientDispatch(updateUploadContext(cacheKey, {
|
|
281
|
+
isAborted: true,
|
|
282
|
+
isUploading: false,
|
|
283
|
+
}));
|
|
284
|
+
};
|
|
285
|
+
const { uploadOptions, uploadFnOptions } = splitTusHooksUploadOptions(mergedUploadOptions);
|
|
286
|
+
const { upload } = createUpload({
|
|
287
|
+
Upload,
|
|
288
|
+
file,
|
|
289
|
+
uploadOptions,
|
|
290
|
+
uploadFnOptions,
|
|
291
|
+
onChange,
|
|
292
|
+
onStart,
|
|
293
|
+
onAbort,
|
|
294
|
+
});
|
|
211
295
|
if (autoStart) {
|
|
212
296
|
startOrResumeUpload(upload);
|
|
213
297
|
}
|
|
214
|
-
tusClientDispatch(insertUploadInstance(cacheKey,
|
|
215
|
-
|
|
298
|
+
tusClientDispatch(insertUploadInstance(cacheKey, {
|
|
299
|
+
upload,
|
|
300
|
+
error: undefined,
|
|
301
|
+
isSuccess: false,
|
|
302
|
+
isAborted: false,
|
|
303
|
+
isUploading: false,
|
|
304
|
+
}));
|
|
305
|
+
}, [
|
|
306
|
+
Upload,
|
|
307
|
+
autoStart,
|
|
308
|
+
cacheKey,
|
|
309
|
+
defaultOptions,
|
|
310
|
+
defaultUploadOptions,
|
|
311
|
+
tusClientDispatch,
|
|
312
|
+
]);
|
|
216
313
|
const targetTusState = useMemo(() => uploads[cacheKey], [cacheKey, uploads]);
|
|
217
314
|
const remove = useCallback(() => {
|
|
218
315
|
targetTusState?.upload?.abort();
|
|
219
316
|
tusClientDispatch(removeUploadInstance(cacheKey));
|
|
220
317
|
}, [targetTusState, tusClientDispatch, cacheKey]);
|
|
221
|
-
const tusResult =
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
318
|
+
const tusResult = targetTusState
|
|
319
|
+
? {
|
|
320
|
+
...targetTusState,
|
|
321
|
+
setUpload,
|
|
322
|
+
remove,
|
|
323
|
+
}
|
|
324
|
+
: {
|
|
325
|
+
upload: undefined,
|
|
326
|
+
error: undefined,
|
|
327
|
+
isSuccess: false,
|
|
328
|
+
isAborted: false,
|
|
329
|
+
isUploading: false,
|
|
330
|
+
setUpload,
|
|
331
|
+
remove,
|
|
332
|
+
};
|
|
333
|
+
useAutoAbort({
|
|
334
|
+
upload: tusResult.upload,
|
|
335
|
+
abort: tusResult.upload?.abort,
|
|
336
|
+
autoAbort: autoAbort ?? false,
|
|
337
|
+
});
|
|
230
338
|
return tusResult;
|
|
231
339
|
};
|
|
232
340
|
|
|
341
|
+
const useTusClient = () => {
|
|
342
|
+
const tusClientState = useTusClientState();
|
|
343
|
+
const tusClientDispatch = useTusClientDispatch();
|
|
344
|
+
const state = tusClientState.uploads;
|
|
345
|
+
const removeUpload = useCallback((cacheKey) => {
|
|
346
|
+
tusClientDispatch(removeUploadInstance(cacheKey));
|
|
347
|
+
}, [tusClientDispatch]);
|
|
348
|
+
const reset = useCallback(() => tusClientDispatch(resetClient()), [tusClientDispatch]);
|
|
349
|
+
return {
|
|
350
|
+
state,
|
|
351
|
+
removeUpload,
|
|
352
|
+
reset,
|
|
353
|
+
};
|
|
354
|
+
};
|
|
355
|
+
|
|
233
356
|
const tusClientReducer = (state, actions) => {
|
|
234
357
|
switch (actions.type) {
|
|
235
358
|
case "INSERT_UPLOAD_INSTANCE": {
|
|
@@ -242,55 +365,15 @@ const tusClientReducer = (state, actions) => {
|
|
|
242
365
|
},
|
|
243
366
|
};
|
|
244
367
|
}
|
|
245
|
-
case "
|
|
246
|
-
const { cacheKey } = actions.payload;
|
|
247
|
-
const target = state.uploads[cacheKey];
|
|
248
|
-
if (!target) {
|
|
249
|
-
return state;
|
|
250
|
-
}
|
|
251
|
-
return {
|
|
252
|
-
...state,
|
|
253
|
-
uploads: {
|
|
254
|
-
...state.uploads,
|
|
255
|
-
[cacheKey]: {
|
|
256
|
-
...(target || {}),
|
|
257
|
-
isSuccess: true,
|
|
258
|
-
},
|
|
259
|
-
},
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
case "UPDATE_ERROR_UPLOAD": {
|
|
263
|
-
const { cacheKey, error } = actions.payload;
|
|
264
|
-
const target = state.uploads[cacheKey];
|
|
265
|
-
if (!target) {
|
|
266
|
-
return state;
|
|
267
|
-
}
|
|
268
|
-
return {
|
|
269
|
-
...state,
|
|
270
|
-
uploads: {
|
|
271
|
-
...state.uploads,
|
|
272
|
-
[cacheKey]: {
|
|
273
|
-
...target,
|
|
274
|
-
error,
|
|
275
|
-
},
|
|
276
|
-
},
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
case "UPDATE_IS_ABORTED_UPLOAD": {
|
|
280
|
-
const { cacheKey, isAborted } = actions.payload;
|
|
368
|
+
case "UPDATE_UPLOAD_CONTEXT": {
|
|
369
|
+
const { cacheKey, context } = actions.payload;
|
|
281
370
|
const target = state.uploads[cacheKey];
|
|
282
371
|
if (!target) {
|
|
283
372
|
return state;
|
|
284
373
|
}
|
|
285
374
|
return {
|
|
286
375
|
...state,
|
|
287
|
-
uploads: {
|
|
288
|
-
...state.uploads,
|
|
289
|
-
[cacheKey]: {
|
|
290
|
-
...target,
|
|
291
|
-
isAborted,
|
|
292
|
-
},
|
|
293
|
-
},
|
|
376
|
+
uploads: { ...state.uploads, [cacheKey]: { ...target, ...context } },
|
|
294
377
|
};
|
|
295
378
|
}
|
|
296
379
|
case "REMOVE_UPLOAD_INSTANCE": {
|
|
@@ -309,8 +392,15 @@ const tusClientReducer = (state, actions) => {
|
|
|
309
392
|
defaultOptions,
|
|
310
393
|
};
|
|
311
394
|
}
|
|
312
|
-
|
|
395
|
+
case "RESET_CLIENT": {
|
|
396
|
+
return {
|
|
397
|
+
...state,
|
|
398
|
+
uploads: {},
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
default: {
|
|
313
402
|
return state;
|
|
403
|
+
}
|
|
314
404
|
}
|
|
315
405
|
};
|
|
316
406
|
const tusClientInitialState = {
|
|
@@ -344,4 +434,4 @@ const TusClientProvider = ({ defaultOptions, children, }) => {
|
|
|
344
434
|
}, tusClientDispatchContextProviderElement);
|
|
345
435
|
};
|
|
346
436
|
|
|
347
|
-
export { TusClientProvider, useTus, useTusStore };
|
|
437
|
+
export { TusClientProvider, useTus, useTusClient, useTusStore };
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Upload, UploadOptions } from "tus-js-client";
|
|
2
|
+
export interface TusHooksOptions {
|
|
3
|
+
autoAbort?: boolean;
|
|
4
|
+
autoStart?: boolean;
|
|
5
|
+
uploadOptions?: TusHooksUploadOptions;
|
|
6
|
+
Upload?: typeof Upload;
|
|
7
|
+
}
|
|
8
|
+
export type Merge<T extends Record<PropertyKey, any>, R extends Record<PropertyKey, any>> = {
|
|
9
|
+
[P in keyof Omit<T, keyof R>]: T[P];
|
|
10
|
+
} & R;
|
|
11
|
+
type AddUploadParamater<F> = F extends (...args: infer A) => infer R ? (...args: [...A, ...[upload: Upload]]) => R : never;
|
|
12
|
+
type Callbacks<T> = {
|
|
13
|
+
[P in keyof T as P extends `on${string}` ? NonNullable<T[P]> extends Function ? P : never : never]: T[P];
|
|
14
|
+
};
|
|
15
|
+
export type TusHooksUploadFnOptions = {
|
|
16
|
+
[K in keyof Callbacks<UploadOptions>]: AddUploadParamater<Callbacks<UploadOptions>[K]>;
|
|
17
|
+
};
|
|
18
|
+
export type TusHooksUploadOptions = Merge<UploadOptions, TusHooksUploadFnOptions>;
|
|
19
|
+
export type UploadFile = Upload["file"];
|
|
20
|
+
export type SetUpload = (file: Upload["file"], options?: TusHooksUploadOptions) => void;
|
|
21
|
+
export type TusHooksResultFn = {
|
|
22
|
+
setUpload: SetUpload;
|
|
23
|
+
remove: () => void;
|
|
24
|
+
};
|
|
25
|
+
export type TusFalselyContext = {
|
|
26
|
+
upload: undefined;
|
|
27
|
+
error: undefined;
|
|
28
|
+
isSuccess: false;
|
|
29
|
+
isAborted: false;
|
|
30
|
+
isUploading: false;
|
|
31
|
+
};
|
|
32
|
+
export type TusTruthlyContext = {
|
|
33
|
+
upload: Upload;
|
|
34
|
+
error?: Error;
|
|
35
|
+
isSuccess: boolean;
|
|
36
|
+
isAborted: boolean;
|
|
37
|
+
isUploading: boolean;
|
|
38
|
+
};
|
|
39
|
+
export type TusContext = TusFalselyContext | TusTruthlyContext;
|
|
40
|
+
export type TusHooksResult = TusContext & TusHooksResultFn;
|
|
41
|
+
export {};
|
package/dist/useTus/index.d.ts
CHANGED
package/dist/useTus/useTus.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const useTus: (baseOption?:
|
|
1
|
+
import { TusHooksOptions, TusHooksResult } from "../types";
|
|
2
|
+
export declare const useTus: (baseOption?: TusHooksOptions) => TusHooksResult;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const useTusClient: () => {
|
|
2
2
|
state: {
|
|
3
|
-
[cacheKey: string]: import("../
|
|
3
|
+
[cacheKey: string]: import("../types").TusTruthlyContext | undefined;
|
|
4
4
|
};
|
|
5
5
|
removeUpload: (cacheKey: string) => void;
|
|
6
6
|
reset: () => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useTusStore } from "./useTusStore";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { UploadOptions, type Upload as UploadType } from "tus-js-client";
|
|
2
|
+
import { TusHooksUploadFnOptions, UploadFile } from "../../types";
|
|
3
|
+
export type CreateUploadParams = {
|
|
4
|
+
Upload: typeof UploadType;
|
|
5
|
+
file: UploadFile;
|
|
6
|
+
uploadOptions: UploadOptions;
|
|
7
|
+
uploadFnOptions: TusHooksUploadFnOptions;
|
|
8
|
+
onChange: (upload: UploadType) => void;
|
|
9
|
+
onStart: () => void;
|
|
10
|
+
onAbort: () => void;
|
|
11
|
+
};
|
|
12
|
+
export declare const createUpload: ({ Upload, file, uploadOptions, uploadFnOptions, onChange, onStart, onAbort, }: CreateUploadParams) => {
|
|
13
|
+
upload: UploadType;
|
|
14
|
+
originalStart: () => void;
|
|
15
|
+
originalAbort: (shouldTerminate?: boolean | undefined) => Promise<void>;
|
|
16
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UploadOptions } from "tus-js-client";
|
|
2
|
+
import { TusHooksUploadFnOptions, TusHooksUploadOptions } from "../../types";
|
|
3
|
+
export declare function splitTusHooksUploadOptions(options: TusHooksUploadOptions): {
|
|
4
|
+
uploadOptions: UploadOptions;
|
|
5
|
+
uploadFnOptions: TusHooksUploadFnOptions;
|
|
6
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Upload } from "tus-js-client";
|
|
2
|
+
import { TusHooksOptions } from "../../types";
|
|
3
|
+
export declare const mergeUseTusOptions: (options: TusHooksOptions) => {
|
|
4
|
+
autoAbort: boolean;
|
|
5
|
+
autoStart: boolean;
|
|
6
|
+
uploadOptions: import("../../types").TusHooksUploadOptions | undefined;
|
|
7
|
+
Upload: typeof Upload;
|
|
8
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Upload } from "tus-js-client";
|
|
2
|
+
type UseAutoAbortParams = {
|
|
3
|
+
upload: Upload | undefined;
|
|
4
|
+
abort: (() => Promise<void>) | undefined;
|
|
5
|
+
autoAbort: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare const useAutoAbort: ({ upload, abort, autoAbort, }: UseAutoAbortParams) => void;
|
|
8
|
+
export {};
|
package/package.json
CHANGED
package/dist/useTus/types.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { Upload, UploadOptions } from "tus-js-client";
|
|
2
|
-
export interface UseTusOptions {
|
|
3
|
-
autoAbort?: boolean;
|
|
4
|
-
autoStart?: boolean;
|
|
5
|
-
uploadOptions?: UploadOptions;
|
|
6
|
-
}
|
|
7
|
-
export interface UseTusResult {
|
|
8
|
-
upload?: Upload;
|
|
9
|
-
setUpload: (file: Upload["file"], options?: Upload["options"]) => void;
|
|
10
|
-
isSuccess: boolean;
|
|
11
|
-
isAborted: boolean;
|
|
12
|
-
error?: Error;
|
|
13
|
-
remove: () => void;
|
|
14
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Upload } from "tus-js-client";
|
|
2
|
-
export type DispatchIsAborted = (isAborted: boolean) => void;
|
|
3
|
-
export declare const createUpload: (file: Upload["file"], options: Upload["options"], dispatchIsAborted: DispatchIsAborted) => {
|
|
4
|
-
upload: Upload;
|
|
5
|
-
originalStart: () => void;
|
|
6
|
-
originalAbort: (shouldTerminate?: boolean | undefined) => Promise<void>;
|
|
7
|
-
};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { UseTusOptions } from "../types";
|
|
2
|
-
export declare const useMergeTusOptions: (options: UseTusOptions | undefined) => {
|
|
3
|
-
autoAbort?: boolean | undefined;
|
|
4
|
-
autoStart?: boolean | undefined;
|
|
5
|
-
uploadOptions?: import("tus-js-client").UploadOptions | undefined;
|
|
6
|
-
};
|
|
File without changes
|