@cedarjs/uploads 6.0.3-next.227
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 +24 -0
- package/dist/authenticator.d.ts +38 -0
- package/dist/authenticator.d.ts.map +1 -0
- package/dist/authenticator.js +51 -0
- package/dist/cleanupStaleUploads.d.ts +50 -0
- package/dist/cleanupStaleUploads.d.ts.map +1 -0
- package/dist/cleanupStaleUploads.js +80 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +4 -0
- package/dist/deleteFile.d.ts +14 -0
- package/dist/deleteFile.d.ts.map +1 -0
- package/dist/deleteFile.js +18 -0
- package/dist/directives.d.ts +55 -0
- package/dist/directives.d.ts.map +1 -0
- package/dist/directives.js +174 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +33 -0
- package/dist/fastify/plugin.d.ts +49 -0
- package/dist/fastify/plugin.d.ts.map +1 -0
- package/dist/fastify/plugin.js +241 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +88 -0
- package/dist/keys.d.ts +18 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +25 -0
- package/dist/pending.d.ts +39 -0
- package/dist/pending.d.ts.map +1 -0
- package/dist/pending.js +94 -0
- package/dist/profiles.d.ts +49 -0
- package/dist/profiles.d.ts.map +1 -0
- package/dist/profiles.js +68 -0
- package/dist/providers/db.d.ts +9 -0
- package/dist/providers/db.d.ts.map +1 -0
- package/dist/providers/db.js +41 -0
- package/dist/providers/fs.d.ts +34 -0
- package/dist/providers/fs.d.ts.map +1 -0
- package/dist/providers/fs.js +125 -0
- package/dist/providers/s3.d.ts +25 -0
- package/dist/providers/s3.d.ts.map +1 -0
- package/dist/providers/s3.js +117 -0
- package/dist/s3.d.ts +3 -0
- package/dist/s3.d.ts.map +1 -0
- package/dist/s3.js +4 -0
- package/dist/serialize.d.ts +10 -0
- package/dist/serialize.d.ts.map +1 -0
- package/dist/serialize.js +22 -0
- package/dist/serveToken.d.ts +36 -0
- package/dist/serveToken.d.ts.map +1 -0
- package/dist/serveToken.js +45 -0
- package/dist/services.d.ts +70 -0
- package/dist/services.d.ts.map +1 -0
- package/dist/services.js +141 -0
- package/dist/storeFile.d.ts +27 -0
- package/dist/storeFile.d.ts.map +1 -0
- package/dist/storeFile.js +53 -0
- package/dist/targets.d.ts +14 -0
- package/dist/targets.d.ts.map +1 -0
- package/dist/targets.js +21 -0
- package/dist/types.d.ts +212 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +0 -0
- package/dist/uploadLoader.d.ts +11 -0
- package/dist/uploadLoader.d.ts.map +1 -0
- package/dist/uploadLoader.js +47 -0
- package/dist/uploadToken.d.ts +43 -0
- package/dist/uploadToken.d.ts.map +1 -0
- package/dist/uploadToken.js +61 -0
- package/dist/web/components/DbInput.d.ts +18 -0
- package/dist/web/components/DbInput.d.ts.map +1 -0
- package/dist/web/components/DbInput.js +46 -0
- package/dist/web/components/FsUploader.d.ts +6 -0
- package/dist/web/components/FsUploader.d.ts.map +1 -0
- package/dist/web/components/FsUploader.js +21 -0
- package/dist/web/components/S3Uploader.d.ts +6 -0
- package/dist/web/components/S3Uploader.d.ts.map +1 -0
- package/dist/web/components/S3Uploader.js +21 -0
- package/dist/web/components/UppyUploader.d.ts +23 -0
- package/dist/web/components/UppyUploader.d.ts.map +1 -0
- package/dist/web/components/UppyUploader.js +72 -0
- package/dist/web/createUppy.d.ts +62 -0
- package/dist/web/createUppy.d.ts.map +1 -0
- package/dist/web/createUppy.js +82 -0
- package/dist/web/graphql.d.ts +48 -0
- package/dist/web/graphql.d.ts.map +1 -0
- package/dist/web/graphql.js +36 -0
- package/dist/web/hooks/useDbUpload.d.ts +31 -0
- package/dist/web/hooks/useDbUpload.d.ts.map +1 -0
- package/dist/web/hooks/useDbUpload.js +80 -0
- package/dist/web/hooks/useFsUpload.d.ts +20 -0
- package/dist/web/hooks/useFsUpload.d.ts.map +1 -0
- package/dist/web/hooks/useFsUpload.js +58 -0
- package/dist/web/hooks/useS3Upload.d.ts +23 -0
- package/dist/web/hooks/useS3Upload.d.ts.map +1 -0
- package/dist/web/hooks/useS3Upload.js +99 -0
- package/dist/web/hooks/useUploadToken.d.ts +34 -0
- package/dist/web/hooks/useUploadToken.d.ts.map +1 -0
- package/dist/web/hooks/useUploadToken.js +60 -0
- package/dist/web/hooks/useUppyUpload.d.ts +23 -0
- package/dist/web/hooks/useUppyUpload.d.ts.map +1 -0
- package/dist/web/hooks/useUppyUpload.js +76 -0
- package/dist/web/index.d.ts +22 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +36 -0
- package/dist/webhooks/s3.d.ts +52 -0
- package/dist/webhooks/s3.d.ts.map +1 -0
- package/dist/webhooks/s3.js +122 -0
- package/dist/webhooks/sns.d.ts +34 -0
- package/dist/webhooks/sns.d.ts.map +1 -0
- package/dist/webhooks/sns.js +131 -0
- package/package.json +147 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { InputHTMLAttributes } from 'react';
|
|
2
|
+
import type { DbUploadFile } from '../hooks/useDbUpload.js';
|
|
3
|
+
export interface DbInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'onChange' | 'accept' | 'multiple' | 'onError'> {
|
|
4
|
+
allowedMimeTypes: string[];
|
|
5
|
+
maxFileSize: number;
|
|
6
|
+
maxFiles?: number;
|
|
7
|
+
/** Called with every selected file read as base64. */
|
|
8
|
+
onFilesReady?: (files: DbUploadFile[]) => void;
|
|
9
|
+
/** Called when a selected file fails validation or cannot be read. */
|
|
10
|
+
onReadError?: (error: Error) => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A file input for the DB upload path. Selected files are validated against
|
|
14
|
+
* the profile's constraints and read as base64, ready to send through a
|
|
15
|
+
* GraphQL mutation to `storeFile()`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function DbInput({ allowedMimeTypes, maxFileSize, maxFiles, onFilesReady, onReadError, disabled, ...inputProps }: DbInputProps): import("react").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=DbInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DbInput.d.ts","sourceRoot":"","sources":["../../../src/web/components/DbInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAG7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAE3D,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CACxD;IACC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,sDAAsD;IACtD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAA;IAC9C,sEAAsE;IACtE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACrC;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EACtB,gBAAgB,EAChB,WAAW,EACX,QAAY,EACZ,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,GAAG,UAAU,EACd,EAAE,YAAY,+BAqCd"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useDbUpload } from "../hooks/useDbUpload.js";
|
|
3
|
+
function DbInput({
|
|
4
|
+
allowedMimeTypes,
|
|
5
|
+
maxFileSize,
|
|
6
|
+
maxFiles = 1,
|
|
7
|
+
onFilesReady,
|
|
8
|
+
onReadError,
|
|
9
|
+
disabled,
|
|
10
|
+
...inputProps
|
|
11
|
+
}) {
|
|
12
|
+
const { readFiles, isReading } = useDbUpload({
|
|
13
|
+
allowedMimeTypes,
|
|
14
|
+
maxFileSize,
|
|
15
|
+
maxFiles
|
|
16
|
+
});
|
|
17
|
+
const onChange = async (event) => {
|
|
18
|
+
const input = event.target;
|
|
19
|
+
const files = input.files;
|
|
20
|
+
if (!files || files.length === 0) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const ready = await readFiles(files);
|
|
25
|
+
onFilesReady?.(ready);
|
|
26
|
+
} catch (e) {
|
|
27
|
+
onReadError?.(e instanceof Error ? e : new Error(String(e)));
|
|
28
|
+
} finally {
|
|
29
|
+
input.value = "";
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
return /* @__PURE__ */ jsx(
|
|
33
|
+
"input",
|
|
34
|
+
{
|
|
35
|
+
...inputProps,
|
|
36
|
+
type: "file",
|
|
37
|
+
accept: allowedMimeTypes.join(","),
|
|
38
|
+
multiple: maxFiles > 1,
|
|
39
|
+
disabled: disabled || isReading,
|
|
40
|
+
onChange
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
DbInput
|
|
46
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { UseFsUploadOptions } from '../hooks/useFsUpload.js';
|
|
2
|
+
import type { UppyUploaderProps } from './UppyUploader.js';
|
|
3
|
+
export type FsUploaderProps = UseFsUploadOptions & Omit<UppyUploaderProps, 'uppy'>;
|
|
4
|
+
/** Through-the-api uploader for FS targets: `useFsUpload` wired to an Uppy UI. */
|
|
5
|
+
export declare function FsUploader({ profile, endpoint, onUploadComplete, onUploadError, ...uiProps }: FsUploaderProps): import("react").JSX.Element;
|
|
6
|
+
//# sourceMappingURL=FsUploader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FsUploader.d.ts","sourceRoot":"","sources":["../../../src/web/components/FsUploader.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,MAAM,MAAM,eAAe,GAAG,kBAAkB,GAC9C,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAA;AAEjC,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,GAAG,OAAO,EACX,EAAE,eAAe,+BASjB"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useFsUpload } from "../hooks/useFsUpload.js";
|
|
3
|
+
import { UppyUploader } from "./UppyUploader.js";
|
|
4
|
+
function FsUploader({
|
|
5
|
+
profile,
|
|
6
|
+
endpoint,
|
|
7
|
+
onUploadComplete,
|
|
8
|
+
onUploadError,
|
|
9
|
+
...uiProps
|
|
10
|
+
}) {
|
|
11
|
+
const { uppy } = useFsUpload({
|
|
12
|
+
profile,
|
|
13
|
+
endpoint,
|
|
14
|
+
onUploadComplete,
|
|
15
|
+
onUploadError
|
|
16
|
+
});
|
|
17
|
+
return /* @__PURE__ */ jsx(UppyUploader, { uppy, ...uiProps });
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
FsUploader
|
|
21
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { UseS3UploadOptions } from '../hooks/useS3Upload.js';
|
|
2
|
+
import type { UppyUploaderProps } from './UppyUploader.js';
|
|
3
|
+
export type S3UploaderProps = UseS3UploadOptions & Omit<UppyUploaderProps, 'uppy'>;
|
|
4
|
+
/** Direct-to-S3 uploader: `useS3Upload` wired to an Uppy UI. */
|
|
5
|
+
export declare function S3Uploader({ profile, confirm, onUploadComplete, onUploadError, ...uiProps }: S3UploaderProps): import("react").JSX.Element;
|
|
6
|
+
//# sourceMappingURL=S3Uploader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"S3Uploader.d.ts","sourceRoot":"","sources":["../../../src/web/components/S3Uploader.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,MAAM,MAAM,eAAe,GAAG,kBAAkB,GAC9C,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAA;AAEjC,gEAAgE;AAChE,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,OAAO,EACP,gBAAgB,EAChB,aAAa,EACb,GAAG,OAAO,EACX,EAAE,eAAe,+BASjB"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useS3Upload } from "../hooks/useS3Upload.js";
|
|
3
|
+
import { UppyUploader } from "./UppyUploader.js";
|
|
4
|
+
function S3Uploader({
|
|
5
|
+
profile,
|
|
6
|
+
confirm,
|
|
7
|
+
onUploadComplete,
|
|
8
|
+
onUploadError,
|
|
9
|
+
...uiProps
|
|
10
|
+
}) {
|
|
11
|
+
const { uppy } = useS3Upload({
|
|
12
|
+
profile,
|
|
13
|
+
confirm,
|
|
14
|
+
onUploadComplete,
|
|
15
|
+
onUploadError
|
|
16
|
+
});
|
|
17
|
+
return /* @__PURE__ */ jsx(UppyUploader, { uppy, ...uiProps });
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
S3Uploader
|
|
21
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { CedarUppy } from '../createUppy.js';
|
|
3
|
+
export type UploaderVariant = 'dashboard' | 'drag-drop' | 'file-input';
|
|
4
|
+
export interface UppyUploaderProps {
|
|
5
|
+
uppy: CedarUppy | null;
|
|
6
|
+
/**
|
|
7
|
+
* `dashboard` mounts the full `@uppy/dashboard` UI. `drag-drop` renders
|
|
8
|
+
* Uppy's headless dropzone with a file list. `file-input` renders a plain
|
|
9
|
+
* upload button. Defaults to `dashboard`.
|
|
10
|
+
*/
|
|
11
|
+
variant?: UploaderVariant;
|
|
12
|
+
/** Options passed to `@uppy/dashboard` for the `dashboard` variant. */
|
|
13
|
+
dashboardOptions?: Record<string, unknown>;
|
|
14
|
+
/** Text shown under the dropzone for the `drag-drop` variant. */
|
|
15
|
+
note?: string;
|
|
16
|
+
children?: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Renders an Uppy UI for an instance created by `useS3Upload` or
|
|
20
|
+
* `useFsUpload`. Renders nothing until the instance exists.
|
|
21
|
+
*/
|
|
22
|
+
export declare function UppyUploader({ uppy, variant, dashboardOptions, note, children, }: UppyUploaderProps): import("react").JSX.Element | null;
|
|
23
|
+
//# sourceMappingURL=UppyUploader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UppyUploader.d.ts","sourceRoot":"","sources":["../../../src/web/components/UppyUploader.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAStC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEjD,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,WAAW,GAAG,YAAY,CAAA;AAEtE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,GAAG,IAAI,CAAA;IACtB;;;;OAIG;IACH,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC1C,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AA4DD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,OAAqB,EACrB,gBAAgB,EAChB,IAAI,EACJ,QAAQ,GACT,EAAE,iBAAiB,sCAsBnB"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
|
+
import {
|
|
4
|
+
Dropzone,
|
|
5
|
+
FilesList,
|
|
6
|
+
UploadButton,
|
|
7
|
+
UppyContextProvider
|
|
8
|
+
} from "@uppy/react";
|
|
9
|
+
function DashboardMount({
|
|
10
|
+
uppy,
|
|
11
|
+
options
|
|
12
|
+
}) {
|
|
13
|
+
const ref = useRef(null);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const target = ref.current;
|
|
16
|
+
if (!target) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
let cancelled = false;
|
|
20
|
+
import("@uppy/dashboard").then(({ default: Dashboard }) => {
|
|
21
|
+
if (cancelled) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
uppy.use(Dashboard, {
|
|
25
|
+
inline: true,
|
|
26
|
+
target,
|
|
27
|
+
proudlyDisplayPoweredByUppy: false,
|
|
28
|
+
...options
|
|
29
|
+
});
|
|
30
|
+
}).catch((e) => {
|
|
31
|
+
if (cancelled) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
uppy.emit(
|
|
35
|
+
"error",
|
|
36
|
+
e instanceof Error ? e : new Error("Could not load @uppy/dashboard")
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
return () => {
|
|
40
|
+
cancelled = true;
|
|
41
|
+
const plugin = uppy.getPlugin("Dashboard");
|
|
42
|
+
if (plugin) {
|
|
43
|
+
uppy.removePlugin(plugin);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}, [uppy]);
|
|
47
|
+
return /* @__PURE__ */ jsx("div", { ref });
|
|
48
|
+
}
|
|
49
|
+
function UppyUploader({
|
|
50
|
+
uppy,
|
|
51
|
+
variant = "dashboard",
|
|
52
|
+
dashboardOptions,
|
|
53
|
+
note,
|
|
54
|
+
children
|
|
55
|
+
}) {
|
|
56
|
+
if (!uppy) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
if (variant === "dashboard") {
|
|
60
|
+
return /* @__PURE__ */ jsx(DashboardMount, { uppy, options: dashboardOptions });
|
|
61
|
+
}
|
|
62
|
+
return /* @__PURE__ */ jsxs(UppyContextProvider, { uppy, children: [
|
|
63
|
+
variant === "drag-drop" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
64
|
+
/* @__PURE__ */ jsx(Dropzone, { note }),
|
|
65
|
+
/* @__PURE__ */ jsx(FilesList, {})
|
|
66
|
+
] }) : /* @__PURE__ */ jsx(UploadButton, {}),
|
|
67
|
+
children
|
|
68
|
+
] });
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
UppyUploader
|
|
72
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import Uppy from '@uppy/core';
|
|
2
|
+
import type { Meta, UppyFile } from '@uppy/core';
|
|
3
|
+
import type { UploadConstraints } from './graphql.js';
|
|
4
|
+
/** The Uppy instance type every Cedar hook and component works with. */
|
|
5
|
+
export type CedarUppy = Uppy;
|
|
6
|
+
/** A file inside a `CedarUppy` instance. */
|
|
7
|
+
export type CedarUppyFile = UppyFile<Meta, Record<string, never>>;
|
|
8
|
+
export { UPLOAD_TOKEN_HEADER } from '../constants.js';
|
|
9
|
+
/** Route the FS uploader posts to, relative to the api origin. */
|
|
10
|
+
export declare const DEFAULT_FS_UPLOAD_PATH = "/upload/fs";
|
|
11
|
+
export interface BaseUppyOptions {
|
|
12
|
+
/** Constraints from the upload token, applied as Uppy restrictions. */
|
|
13
|
+
constraints?: UploadConstraints | null;
|
|
14
|
+
/** Start uploading as soon as files are added. Defaults to `true`. */
|
|
15
|
+
autoProceed?: boolean;
|
|
16
|
+
debug?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* One file's `{ url, method, headers }` from the api, plus the id of the
|
|
20
|
+
* pending `Upload` row it belongs to.
|
|
21
|
+
*/
|
|
22
|
+
export interface PresignedUploadParameters {
|
|
23
|
+
uploadId: string;
|
|
24
|
+
url: string;
|
|
25
|
+
method: string;
|
|
26
|
+
headers: Record<string, string>;
|
|
27
|
+
}
|
|
28
|
+
export interface S3UppyOptions extends BaseUppyOptions {
|
|
29
|
+
provider: 's3';
|
|
30
|
+
/**
|
|
31
|
+
* Asks the api for a presigned URL for one file. Called once per file
|
|
32
|
+
* with the file's name, type, and size.
|
|
33
|
+
*/
|
|
34
|
+
getUploadParameters: (file: CedarUppyFile) => Promise<PresignedUploadParameters>;
|
|
35
|
+
}
|
|
36
|
+
export interface FsUppyOptions extends BaseUppyOptions {
|
|
37
|
+
provider: 'fs';
|
|
38
|
+
/** Full URL of the api's `POST {prefix}/fs` route, or a function returning it. */
|
|
39
|
+
endpoint: string | (() => string);
|
|
40
|
+
/** The upload token to send. Called per request so a refreshed token is used. */
|
|
41
|
+
getUploadToken: () => string | null;
|
|
42
|
+
}
|
|
43
|
+
export type CreateUppyOptions = S3UppyOptions | FsUppyOptions;
|
|
44
|
+
/** Response body of the api's `POST {prefix}/fs` route. */
|
|
45
|
+
export interface FsUploadResponseBody {
|
|
46
|
+
uploads: {
|
|
47
|
+
id: string;
|
|
48
|
+
status: string;
|
|
49
|
+
filename: string;
|
|
50
|
+
}[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Creates an Uppy instance pre-configured for one of Cedar's upload flows.
|
|
54
|
+
* Direct-to-S3 uploads use `@uppy/aws-s3` with the presigned URLs the api
|
|
55
|
+
* hands out; FS uploads use `@uppy/xhr-upload` against the api's upload
|
|
56
|
+
* route. The matching plugin is loaded on demand, so only the one in use
|
|
57
|
+
* needs to be installed.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createUppy(options: CreateUppyOptions): Promise<CedarUppy>;
|
|
60
|
+
/** Reads the `Upload` id Cedar recorded on a file after it uploaded. */
|
|
61
|
+
export declare function getCedarUploadId(file: CedarUppyFile): string | null;
|
|
62
|
+
//# sourceMappingURL=createUppy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createUppy.d.ts","sourceRoot":"","sources":["../../src/web/createUppy.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,YAAY,CAAA;AAC7B,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAIhD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAErD,wEAAwE;AACxE,MAAM,MAAM,SAAS,GAAG,IAAI,CAAA;AAE5B,4CAA4C;AAC5C,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAA;AAEjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAErD,kEAAkE;AAClE,eAAO,MAAM,sBAAsB,eAAe,CAAA;AAElD,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,WAAW,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAA;IACtC,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,aAAc,SAAQ,eAAe;IACpD,QAAQ,EAAE,IAAI,CAAA;IACd;;;OAGG;IACH,mBAAmB,EAAE,CACnB,IAAI,EAAE,aAAa,KAChB,OAAO,CAAC,yBAAyB,CAAC,CAAA;CACxC;AAED,MAAM,WAAW,aAAc,SAAQ,eAAe;IACpD,QAAQ,EAAE,IAAI,CAAA;IACd,kFAAkF;IAClF,QAAQ,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAA;IACjC,iFAAiF;IACjF,cAAc,EAAE,MAAM,MAAM,GAAG,IAAI,CAAA;CACpC;AAED,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG,aAAa,CAAA;AAE7D,2DAA2D;AAC3D,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC5D;AAcD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,SAAS,CAAC,CA2EpB;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAInE"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import Uppy from "@uppy/core";
|
|
2
|
+
import { UPLOAD_TOKEN_HEADER } from "../constants.js";
|
|
3
|
+
import { UPLOAD_TOKEN_HEADER as UPLOAD_TOKEN_HEADER2 } from "../constants.js";
|
|
4
|
+
const DEFAULT_FS_UPLOAD_PATH = "/upload/fs";
|
|
5
|
+
function restrictionsFor(constraints) {
|
|
6
|
+
if (!constraints) {
|
|
7
|
+
return {};
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
allowedFileTypes: constraints.allowedMimeTypes,
|
|
11
|
+
maxFileSize: constraints.maxFileSize,
|
|
12
|
+
maxNumberOfFiles: constraints.maxFiles
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
async function createUppy(options) {
|
|
16
|
+
const { constraints, autoProceed = true, debug = false } = options;
|
|
17
|
+
const uppy = new Uppy({
|
|
18
|
+
autoProceed,
|
|
19
|
+
debug,
|
|
20
|
+
restrictions: restrictionsFor(constraints)
|
|
21
|
+
});
|
|
22
|
+
if (options.provider === "s3") {
|
|
23
|
+
const { default: AwsS3 } = await import("@uppy/aws-s3");
|
|
24
|
+
uppy.use(AwsS3, {
|
|
25
|
+
shouldUseMultipart: false,
|
|
26
|
+
// The S3 plugin signs by object key, not by file, so the key is set to
|
|
27
|
+
// the Uppy file id and the file looked up from it inside `signRequest`.
|
|
28
|
+
// The server chooses the real object key.
|
|
29
|
+
generateObjectKey: (file) => file.id,
|
|
30
|
+
signRequest: async (request) => {
|
|
31
|
+
if (request.method !== "PUT" || "uploadId" in request) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`Cedar presigned uploads only support single PUT requests, got ${request.method}.`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const file = uppy.getFile(request.key);
|
|
37
|
+
if (!file) {
|
|
38
|
+
throw new Error(`Unknown file '${request.key}'.`);
|
|
39
|
+
}
|
|
40
|
+
const params = await options.getUploadParameters(file);
|
|
41
|
+
uppy.setFileMeta(file.id, { cedarUploadId: params.uploadId });
|
|
42
|
+
return { url: params.url };
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return uppy;
|
|
46
|
+
}
|
|
47
|
+
const { default: XHRUpload } = await import("@uppy/xhr-upload");
|
|
48
|
+
const { endpoint } = options;
|
|
49
|
+
uppy.use(XHRUpload, {
|
|
50
|
+
endpoint: typeof endpoint === "function" ? () => endpoint() : endpoint,
|
|
51
|
+
method: "POST",
|
|
52
|
+
formData: true,
|
|
53
|
+
fieldName: "file",
|
|
54
|
+
bundle: false,
|
|
55
|
+
headers: () => {
|
|
56
|
+
const headers = {};
|
|
57
|
+
const token = options.getUploadToken();
|
|
58
|
+
if (token) {
|
|
59
|
+
headers[UPLOAD_TOKEN_HEADER] = token;
|
|
60
|
+
}
|
|
61
|
+
return headers;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
uppy.on("upload-success", (file, response) => {
|
|
65
|
+
const body = response.body;
|
|
66
|
+
const id = body?.uploads?.[0]?.id;
|
|
67
|
+
if (file && id) {
|
|
68
|
+
uppy.setFileMeta(file.id, { cedarUploadId: id });
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return uppy;
|
|
72
|
+
}
|
|
73
|
+
function getCedarUploadId(file) {
|
|
74
|
+
const id = file.meta.cedarUploadId;
|
|
75
|
+
return typeof id === "string" ? id : null;
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
DEFAULT_FS_UPLOAD_PATH,
|
|
79
|
+
UPLOAD_TOKEN_HEADER2 as UPLOAD_TOKEN_HEADER,
|
|
80
|
+
createUppy,
|
|
81
|
+
getCedarUploadId
|
|
82
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constraints echoed with an upload token. The authoritative copy is inside
|
|
3
|
+
* the signed token; these are for client-side UX only.
|
|
4
|
+
*/
|
|
5
|
+
export interface UploadConstraints {
|
|
6
|
+
allowedMimeTypes: string[];
|
|
7
|
+
maxFileSize: number;
|
|
8
|
+
maxFiles: number;
|
|
9
|
+
}
|
|
10
|
+
export interface RequestUploadTokenData {
|
|
11
|
+
requestUploadToken: {
|
|
12
|
+
token: string;
|
|
13
|
+
allowedMimeTypes: string[];
|
|
14
|
+
maxFileSize: string | number;
|
|
15
|
+
maxFiles: number;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface RequestUploadTokenVariables {
|
|
19
|
+
profile: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const REQUEST_UPLOAD_TOKEN: import("@apollo/client").DocumentNode;
|
|
22
|
+
export interface CreatePresignedUploadUrlData {
|
|
23
|
+
createPresignedUploadUrl: {
|
|
24
|
+
uploadId: string;
|
|
25
|
+
url: string;
|
|
26
|
+
method: string;
|
|
27
|
+
headers: Record<string, string>;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface CreatePresignedUploadUrlVariables {
|
|
31
|
+
input: {
|
|
32
|
+
filename: string;
|
|
33
|
+
contentType: string;
|
|
34
|
+
size: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export declare const CREATE_PRESIGNED_UPLOAD_URL: import("@apollo/client").DocumentNode;
|
|
38
|
+
export interface ConfirmUploadData {
|
|
39
|
+
confirmUpload: {
|
|
40
|
+
id: string;
|
|
41
|
+
status: string;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export interface ConfirmUploadVariables {
|
|
45
|
+
uploadId: string;
|
|
46
|
+
}
|
|
47
|
+
export declare const CONFIRM_UPLOAD: import("@apollo/client").DocumentNode;
|
|
48
|
+
//# sourceMappingURL=graphql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql.d.ts","sourceRoot":"","sources":["../../src/web/graphql.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,kBAAkB,EAAE;QAClB,KAAK,EAAE,MAAM,CAAA;QACb,gBAAgB,EAAE,MAAM,EAAE,CAAA;QAC1B,WAAW,EAAE,MAAM,GAAG,MAAM,CAAA;QAC5B,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAA;CACF;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,oBAAoB,uCAShC,CAAA;AAED,MAAM,WAAW,4BAA4B;IAC3C,wBAAwB,EAAE;QACxB,QAAQ,EAAE,MAAM,CAAA;QAChB,GAAG,EAAE,MAAM,CAAA;QACX,MAAM,EAAE,MAAM,CAAA;QACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAChC,CAAA;CACF;AAED,MAAM,WAAW,iCAAiC;IAChD,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,EAAE,MAAM,CAAA;QACnB,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;CACF;AAED,eAAO,MAAM,2BAA2B,uCAWvC,CAAA;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE;QACb,EAAE,EAAE,MAAM,CAAA;QACV,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;CACF;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,eAAO,MAAM,cAAc,uCAO1B,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { gql } from "@apollo/client";
|
|
2
|
+
const REQUEST_UPLOAD_TOKEN = gql`
|
|
3
|
+
query CedarRequestUploadToken($profile: String!) {
|
|
4
|
+
requestUploadToken(profile: $profile) {
|
|
5
|
+
token
|
|
6
|
+
allowedMimeTypes
|
|
7
|
+
maxFileSize
|
|
8
|
+
maxFiles
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
`;
|
|
12
|
+
const CREATE_PRESIGNED_UPLOAD_URL = gql`
|
|
13
|
+
mutation CedarCreatePresignedUploadUrl(
|
|
14
|
+
$input: CreatePresignedUploadUrlInput!
|
|
15
|
+
) {
|
|
16
|
+
createPresignedUploadUrl(input: $input) {
|
|
17
|
+
uploadId
|
|
18
|
+
url
|
|
19
|
+
method
|
|
20
|
+
headers
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
24
|
+
const CONFIRM_UPLOAD = gql`
|
|
25
|
+
mutation CedarConfirmUpload($uploadId: String!) {
|
|
26
|
+
confirmUpload(uploadId: $uploadId) {
|
|
27
|
+
id
|
|
28
|
+
status
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
export {
|
|
33
|
+
CONFIRM_UPLOAD,
|
|
34
|
+
CREATE_PRESIGNED_UPLOAD_URL,
|
|
35
|
+
REQUEST_UPLOAD_TOKEN
|
|
36
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface DbUploadFile {
|
|
2
|
+
filename: string;
|
|
3
|
+
mimeType: string;
|
|
4
|
+
/** Base64-encoded bytes. */
|
|
5
|
+
data: string;
|
|
6
|
+
size: number;
|
|
7
|
+
}
|
|
8
|
+
export interface UseDbUploadOptions {
|
|
9
|
+
allowedMimeTypes: string[];
|
|
10
|
+
maxFileSize: number;
|
|
11
|
+
maxFiles?: number;
|
|
12
|
+
onFileReady?: (file: DbUploadFile) => void;
|
|
13
|
+
}
|
|
14
|
+
export interface UseDbUploadResult {
|
|
15
|
+
/** Reads one `File` as base64, validating type and size first. */
|
|
16
|
+
readFile: (file: File) => Promise<DbUploadFile>;
|
|
17
|
+
/** Reads every file of a `FileList`, validating the count first. */
|
|
18
|
+
readFiles: (files: FileList | File[]) => Promise<DbUploadFile[]>;
|
|
19
|
+
progress: {
|
|
20
|
+
completed: number;
|
|
21
|
+
total: number;
|
|
22
|
+
};
|
|
23
|
+
isReading: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Reads small files as base64 for the DB upload path, which sends bytes
|
|
27
|
+
* through a GraphQL mutation to `storeFile()`. No Uppy involved. The checks
|
|
28
|
+
* here are UX only; the service enforces the real limits.
|
|
29
|
+
*/
|
|
30
|
+
export declare function useDbUpload({ allowedMimeTypes, maxFileSize, maxFiles, onFileReady, }: UseDbUploadOptions): UseDbUploadResult;
|
|
31
|
+
//# sourceMappingURL=useDbUpload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDbUpload.d.ts","sourceRoot":"","sources":["../../../src/web/hooks/useDbUpload.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;CAC3C;AAED,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;IAC/C,oEAAoE;IACpE,SAAS,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,EAAE,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAChE,QAAQ,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9C,SAAS,EAAE,OAAO,CAAA;CACnB;AAkCD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAC1B,gBAAgB,EAChB,WAAW,EACX,QAAQ,EACR,WAAW,GACZ,EAAE,kBAAkB,GAAG,iBAAiB,CA0DxC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
function mimeTypeAllowed(allowed, mimeType) {
|
|
3
|
+
const normalized = mimeType.toLowerCase();
|
|
4
|
+
return allowed.some((entry) => {
|
|
5
|
+
const pattern = entry.toLowerCase();
|
|
6
|
+
if (pattern === "*/*") {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
if (pattern.endsWith("/*")) {
|
|
10
|
+
return normalized.startsWith(pattern.slice(0, -1));
|
|
11
|
+
}
|
|
12
|
+
return pattern === normalized;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function readAsBase64(file) {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const reader = new FileReader();
|
|
18
|
+
reader.onerror = () => reject(reader.error ?? new Error("Read failed"));
|
|
19
|
+
reader.onload = () => {
|
|
20
|
+
const result = String(reader.result);
|
|
21
|
+
resolve(result.slice(result.indexOf(",") + 1));
|
|
22
|
+
};
|
|
23
|
+
reader.readAsDataURL(file);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function useDbUpload({
|
|
27
|
+
allowedMimeTypes,
|
|
28
|
+
maxFileSize,
|
|
29
|
+
maxFiles,
|
|
30
|
+
onFileReady
|
|
31
|
+
}) {
|
|
32
|
+
const [progress, setProgress] = useState({ completed: 0, total: 0 });
|
|
33
|
+
const [isReading, setIsReading] = useState(false);
|
|
34
|
+
const readFile = useCallback(
|
|
35
|
+
async (file) => {
|
|
36
|
+
if (!mimeTypeAllowed(allowedMimeTypes, file.type)) {
|
|
37
|
+
throw new Error(`File type '${file.type}' is not allowed.`);
|
|
38
|
+
}
|
|
39
|
+
if (file.size > maxFileSize) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`File is ${file.size} bytes, which exceeds the ${maxFileSize} byte limit.`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
const result = {
|
|
45
|
+
filename: file.name,
|
|
46
|
+
mimeType: file.type,
|
|
47
|
+
data: await readAsBase64(file),
|
|
48
|
+
size: file.size
|
|
49
|
+
};
|
|
50
|
+
onFileReady?.(result);
|
|
51
|
+
return result;
|
|
52
|
+
},
|
|
53
|
+
[allowedMimeTypes, maxFileSize, onFileReady]
|
|
54
|
+
);
|
|
55
|
+
const readFiles = useCallback(
|
|
56
|
+
async (files) => {
|
|
57
|
+
const list = Array.from(files);
|
|
58
|
+
if (maxFiles !== void 0 && list.length > maxFiles) {
|
|
59
|
+
throw new Error(`At most ${maxFiles} file(s) can be selected.`);
|
|
60
|
+
}
|
|
61
|
+
setIsReading(true);
|
|
62
|
+
setProgress({ completed: 0, total: list.length });
|
|
63
|
+
try {
|
|
64
|
+
const results = [];
|
|
65
|
+
for (const file of list) {
|
|
66
|
+
results.push(await readFile(file));
|
|
67
|
+
setProgress({ completed: results.length, total: list.length });
|
|
68
|
+
}
|
|
69
|
+
return results;
|
|
70
|
+
} finally {
|
|
71
|
+
setIsReading(false);
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
[maxFiles, readFile]
|
|
75
|
+
);
|
|
76
|
+
return { readFile, readFiles, progress, isReading };
|
|
77
|
+
}
|
|
78
|
+
export {
|
|
79
|
+
useDbUpload
|
|
80
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { UppyUploadCallbacks, UppyUploadResult } from './useUppyUpload.js';
|
|
2
|
+
export interface UseFsUploadOptions extends UppyUploadCallbacks {
|
|
3
|
+
/** Name of a server-defined upload profile. */
|
|
4
|
+
profile: string;
|
|
5
|
+
/**
|
|
6
|
+
* Full URL of the api's upload route. Defaults to the api URL from
|
|
7
|
+
* `RWJS_API_URL` plus `/upload/fs`. Read on every request, so it may
|
|
8
|
+
* change after mount.
|
|
9
|
+
*/
|
|
10
|
+
endpoint?: string;
|
|
11
|
+
}
|
|
12
|
+
export type UseFsUploadResult = UppyUploadResult & {
|
|
13
|
+
requestToken: () => Promise<string>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Uploads through the api server to an FS target: fetches an upload token
|
|
17
|
+
* and posts each file to `POST {prefix}/fs` with `@uppy/xhr-upload`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function useFsUpload({ profile, endpoint, onUploadComplete, onUploadError, }: UseFsUploadOptions): UseFsUploadResult;
|
|
20
|
+
//# sourceMappingURL=useFsUpload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFsUpload.d.ts","sourceRoot":"","sources":["../../../src/web/hooks/useFsUpload.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE/E,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG;IACjD,YAAY,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACpC,CAAA;AAWD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,QAAQ,EACR,gBAAgB,EAChB,aAAa,GACd,EAAE,kBAAkB,GAAG,iBAAiB,CAyDxC"}
|