@gentleduck/upload 0.2.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/README.md +170 -193
  2. package/dist/core/index.d.ts +2 -3
  3. package/dist/core/index.js +1 -1
  4. package/dist/core-BVgloTiP.js +10 -0
  5. package/dist/index-DCqyBVcx.d.ts +1441 -0
  6. package/dist/index-DsZHPmJm.d.ts +225 -0
  7. package/dist/index-KROXtLQh.d.ts +281 -0
  8. package/dist/index.d.ts +4 -5
  9. package/dist/index.js +1 -1
  10. package/dist/react/index.d.ts +2 -51
  11. package/dist/react/index.js +1 -1
  12. package/dist/react-euPrDv24.js +1 -0
  13. package/dist/strategies/index.d.ts +2 -56
  14. package/dist/strategies/index.js +1 -1
  15. package/dist/strategies-CUF0s68j.js +1 -0
  16. package/package.json +3 -2
  17. package/src/{__test__ → __tests__}/emitter.test.ts +4 -4
  18. package/src/{__test__ → __tests__}/fingerprint.test.ts +1 -1
  19. package/src/{__test__ → __tests__}/guards.test.ts +15 -5
  20. package/src/__tests__/id.test.ts +67 -0
  21. package/src/__tests__/mime-sniff.test.ts +142 -0
  22. package/src/{__test__ → __tests__}/persistence.test.ts +43 -8
  23. package/src/__tests__/sanitize-filename.test.ts +109 -0
  24. package/src/__tests__/sleep.test.ts +34 -0
  25. package/src/__tests__/static-analysis.test.ts +145 -0
  26. package/src/{__test__ → __tests__}/store-libs.test.ts +57 -3
  27. package/src/__tests__/transport-fetch.test.ts +108 -0
  28. package/src/{__test__ → __tests__}/transport.test.ts +5 -5
  29. package/src/core/__tests__/errors.test.ts +152 -0
  30. package/src/core/client.ts +3 -0
  31. package/src/core/contracts/contracts.types.ts +335 -141
  32. package/src/core/contracts/index.ts +3 -8
  33. package/src/core/contracts/transport/index.ts +3 -2
  34. package/src/core/contracts/transport/transport.fetch.ts +203 -0
  35. package/src/core/contracts/transport/transport.libs.ts +7 -8
  36. package/src/core/contracts/transport/transport.ts +91 -83
  37. package/src/core/contracts/transport/transport.types.ts +71 -35
  38. package/src/core/engine/__tests__/config-nan-bypass.test.ts +40 -0
  39. package/src/core/engine/engine.libs.ts +35 -0
  40. package/src/core/engine/engine.types.ts +367 -241
  41. package/src/core/engine/index.ts +3 -8
  42. package/src/core/engine/reducer.ts +89 -43
  43. package/src/core/engine/store/handlers/add-file.ts +39 -29
  44. package/src/core/engine/store/handlers/cancel.ts +13 -8
  45. package/src/core/engine/store/handlers/clean-up.ts +11 -8
  46. package/src/core/engine/store/handlers/create-intent.ts +82 -27
  47. package/src/core/engine/store/handlers/finalize.ts +30 -13
  48. package/src/core/engine/store/handlers/index.ts +7 -7
  49. package/src/core/engine/store/handlers/pause.ts +8 -6
  50. package/src/core/engine/store/handlers/run-upload.ts +49 -34
  51. package/src/core/engine/store/index.ts +27 -21
  52. package/src/core/engine/store/store.dispatch.ts +10 -8
  53. package/src/core/engine/store/store.libs.ts +184 -41
  54. package/src/core/engine/store/store.runtime.ts +45 -36
  55. package/src/core/engine/store/store.schedule.ts +27 -21
  56. package/src/core/engine/store/store.types.ts +177 -227
  57. package/src/core/engine/validation/__tests__/intent.test.ts +70 -0
  58. package/src/core/engine/validation/file.ts +7 -3
  59. package/src/core/engine/validation/index.ts +1 -0
  60. package/src/core/engine/validation/intent.ts +49 -27
  61. package/src/core/engine/validation/list.ts +14 -15
  62. package/src/core/engine/validation/mime.ts +39 -0
  63. package/src/core/errors.ts +271 -0
  64. package/src/core/index.ts +28 -5
  65. package/src/core/persistence/__tests__/deserialize-nan-bypass.test.ts +100 -0
  66. package/src/core/persistence/__tests__/persistence.test.ts +85 -0
  67. package/src/core/persistence/adapters.indexeddb.ts +9 -3
  68. package/src/core/persistence/adapters.local.ts +9 -3
  69. package/src/core/persistence/adapters.memory.ts +35 -13
  70. package/src/core/persistence/index.ts +5 -5
  71. package/src/core/persistence/persistence.ts +73 -60
  72. package/src/core/persistence/persistence.types.ts +140 -60
  73. package/src/core/utils/__tests__/guards.test.ts +93 -0
  74. package/src/core/utils/__tests__/url-safety.test.ts +112 -0
  75. package/src/core/utils/async.ts +7 -2
  76. package/src/core/utils/constants.ts +3 -9
  77. package/src/core/utils/emitter/emitter.ts +7 -24
  78. package/src/core/utils/emitter/emitter.types.ts +33 -16
  79. package/src/core/utils/emitter/index.ts +2 -74
  80. package/src/core/utils/fingerprint.ts +16 -5
  81. package/src/core/utils/guards.ts +91 -1
  82. package/src/core/utils/hash/__tests__/sha256.test.ts +61 -0
  83. package/src/core/utils/hash/index.ts +126 -0
  84. package/src/core/utils/hash/sha256.ts +179 -0
  85. package/src/core/utils/id.ts +33 -1
  86. package/src/core/utils/index.ts +15 -6
  87. package/src/core/utils/mime-sniff.ts +119 -0
  88. package/src/core/utils/sanitize-filename.ts +85 -0
  89. package/src/core/utils/url-safety.ts +156 -0
  90. package/src/react/__tests__/use-dropzone.test.ts +64 -0
  91. package/src/react/index.ts +5 -2
  92. package/src/react/upload-provider.tsx +68 -53
  93. package/src/react/uploader.types.ts +58 -61
  94. package/src/react/use-dropzone.tsx +226 -0
  95. package/src/react/use-uploader.tsx +98 -91
  96. package/src/strategies/_shared/__tests__/retry.test.ts +120 -0
  97. package/src/strategies/_shared/retry.ts +79 -0
  98. package/src/strategies/index.ts +9 -15
  99. package/src/strategies/multipart/__tests__/multipart.test.ts +229 -0
  100. package/src/strategies/multipart/index.ts +206 -108
  101. package/src/strategies/post/__tests__/post-url-safety.test.ts +119 -0
  102. package/src/strategies/post/index.ts +115 -33
  103. package/src/strategies/put/__tests__/put.test.ts +132 -0
  104. package/src/strategies/put/index.ts +139 -0
  105. package/src/strategies/registry/index.ts +12 -9
  106. package/src/strategies/tus/__tests__/tus.test.ts +159 -0
  107. package/src/strategies/tus/index.ts +211 -0
  108. package/dist/async-DxRWu4le.js +0 -1
  109. package/dist/core-CMkrP9DX.js +0 -2
  110. package/dist/index-C38Jmizu.d.ts +0 -1005
  111. package/dist/strategy.types-gg9ZStRe.d.ts +0 -225
  112. package/src/__test__/effect-pool.test.ts +0 -5
  113. package/src/__test__/id.test.ts +0 -14
  114. package/src/__test__/store-integration.test.ts +0 -5
  115. package/src/core/client/client.ts +0 -50
  116. package/src/core/client/client.types.ts +0 -184
  117. package/src/core/client/config.types.ts +0 -77
  118. package/src/core/client/index.ts +0 -4
  119. package/src/core/client/plugins.types.ts +0 -46
  120. package/src/core/client/retry.types.ts +0 -6
  121. package/src/core/client/uploadClient.ts +0 -19
  122. package/src/core/contracts/backendApi.ts +0 -62
  123. package/src/core/contracts/cursor.types.ts +0 -23
  124. package/src/core/contracts/errors.types.ts +0 -67
  125. package/src/core/contracts/fingerprint.types.ts +0 -18
  126. package/src/core/contracts/intent.types.ts +0 -39
  127. package/src/core/contracts/result.types.ts +0 -11
  128. package/src/core/contracts/strategy.types.ts +0 -45
  129. package/src/core/engine/commands.types.ts +0 -17
  130. package/src/core/engine/event-map.types.ts +0 -45
  131. package/src/core/engine/internal-events.types.ts +0 -202
  132. package/src/core/engine/outcome.types.ts +0 -9
  133. package/src/core/engine/progress.types.ts +0 -15
  134. package/src/core/engine/store/handlers.ts +0 -819
  135. package/src/core/engine/validation.ts +0 -216
  136. /package/src/{__test__ → __tests__}/transport-libs.test.ts +0 -0
@@ -0,0 +1,225 @@
1
+ import { O as Contracts, i as Store, n as Engine } from "./index-DCqyBVcx.js";
2
+ import * as React$1 from "react";
3
+ import React from "react";
4
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
5
+
6
+ //#region src/react/uploader.types.d.ts
7
+ /**
8
+ * Public typings and namespaces consumed by React hook components.
9
+ * @author wildduck2 <https://github.com/wildduck2>
10
+ */
11
+ declare namespace Uploader {
12
+ /**
13
+ * Return state payload returned by the `useUploader` hook.
14
+ *
15
+ * @template M - Intent map type
16
+ * @template C - Cursor map type
17
+ * @template P - Purpose string union type
18
+ * @template R - Backend result shape
19
+ */
20
+ type State<M extends Contracts.Intent.Map, C extends Contracts.Cursor.Map<M>, P extends string, R extends Contracts.Result.Base = Contracts.Result.Base> = Pick<Store.UploadStore<M, C, P, R>, 'dispatch' | 'on' | 'off'> & {
21
+ /** List of all registered upload items currently tracked. */items: Array<Engine.Item<M, C, P, R>>; /** Upload items grouped by phase. */
22
+ byPhase: Record<Engine.Phase, Array<Engine.Item<M, C, P, R>>>; /** Subset of items currently active in the transfer phase. */
23
+ uploading: Array<Engine.Item<M, C, P, R>>; /** Subset of items currently paused. */
24
+ paused: Array<Engine.Item<M, C, P, R>>; /** Subset of items that successfully completed uploading and backend finalization. */
25
+ completed: Array<Engine.Item<M, C, P, R>>; /** Subset of items currently in the error state. */
26
+ failed: Array<Engine.Item<M, C, P, R>>; /** Subset of items validated and waiting to begin uploading. */
27
+ ready: Array<Engine.Item<M, C, P, R>>;
28
+ };
29
+ /**
30
+ * Bound action callbacks returned by context hooks.
31
+ *
32
+ * Houses both the bound dispatchers and the raw underlying store reference.
33
+ *
34
+ * @template M - Intent map type
35
+ * @template C - Cursor map type
36
+ * @template P - Purpose string union type
37
+ * @template R - Backend result shape
38
+ */
39
+ type IActions<M extends Contracts.Intent.Map, C extends Contracts.Cursor.Map<M>, P extends string, R extends Contracts.Result.Base = Contracts.Result.Base> = Pick<Store.UploadStore<M, C, P, R>, 'dispatch' | 'on'> & {
40
+ /** The raw upload store instance. */store: Store.UploadStore<M, C, P, R>;
41
+ };
42
+ /**
43
+ * Props for the `<UploadProvider>` component.
44
+ */
45
+ interface ProviderProps<M extends Contracts.Intent.Map, C extends Contracts.Cursor.Map<M>, P extends string, R extends Contracts.Result.Base = Contracts.Result.Base> {
46
+ /** The upload store instance to distribute. */
47
+ store: Store.UploadStore<M, C, P, R>;
48
+ /** React child elements. */
49
+ children: React.ReactNode;
50
+ }
51
+ }
52
+ //#endregion
53
+ //#region src/react/upload-provider.d.ts
54
+ /**
55
+ * Context provider that distributes the upload store across the React component hierarchy.
56
+ *
57
+ * Wrap this provider around the top of your layout to enable child hooks like `useUploader`
58
+ * to access upload status.
59
+ *
60
+ * @example
61
+ * ```tsx
62
+ * const store = createUploadStore({ ... });
63
+ *
64
+ * function App() {
65
+ * return (
66
+ * <UploadProvider store={store}>
67
+ * <UploadForm />
68
+ * </UploadProvider>
69
+ * );
70
+ * }
71
+ * ```
72
+ * @author wildduck2 <https://github.com/wildduck2>
73
+ */
74
+ declare function UploadProvider<M extends Contracts.Intent.Map, C extends Contracts.Cursor.Map<M>, P extends string, R extends Contracts.Result.Base = Contracts.Result.Base>({
75
+ store,
76
+ children
77
+ }: Uploader.ProviderProps<M, C, P, R>): react_jsx_runtime0.JSX.Element;
78
+ /**
79
+ * Returns the active upload store instance from context.
80
+ * Throws a runtime exception if called outside an `<UploadProvider>`.
81
+ * @author wildduck2 <https://github.com/wildduck2>
82
+ */
83
+ declare function useUploadStore<M extends Contracts.Intent.Map, C extends Contracts.Cursor.Map<M>, P extends string, R extends Contracts.Result.Base = Contracts.Result.Base>(): Store.UploadStore<M, C, P, R>;
84
+ /**
85
+ * Runtime type guard: returns `true` when `value` exposes the upload-store
86
+ * surface (`getSnapshot`, `subscribe`, `dispatch`, `on`, `off`, `waitFor`).
87
+ * @author wildduck2 <https://github.com/wildduck2>
88
+ */
89
+ declare function isUploadStore<M extends Contracts.Intent.Map, C extends Contracts.Cursor.Map<M>, P extends string, R extends Contracts.Result.Base = Contracts.Result.Base>(value: unknown): value is Store.UploadStore<M, C, P, R>;
90
+ //#endregion
91
+ //#region src/react/use-dropzone.d.ts
92
+ /**
93
+ * Test a file against one token from an `accept` string. A token is a MIME type
94
+ * (`image/png`), a MIME wildcard (`image/*`), or a filename extension (`.pdf`).
95
+ * @internal exported for tests.
96
+ */
97
+ declare function matchesAcceptToken(file: File, token: string): boolean;
98
+ /**
99
+ * True when `file` satisfies an `accept` list (comma-separated tokens). An empty
100
+ * or absent list accepts everything.
101
+ * @internal exported for tests.
102
+ */
103
+ declare function fileMatchesAccept(file: File, accept?: string): boolean;
104
+ /**
105
+ * Filter a dropped/selected file list by `accept` and collapse to a single file
106
+ * when `multiple` is false.
107
+ * @internal exported for tests.
108
+ */
109
+ declare function selectFiles(files: File[], opts: {
110
+ accept?: string | undefined;
111
+ multiple?: boolean | undefined;
112
+ }): File[];
113
+ /** Options for {@link useDropzone}. */
114
+ type UseDropzoneOptions<P extends string> = {
115
+ /** Purpose forwarded to the `addFiles` command. */purpose: P; /** Optional caller metadata forwarded to every backend API call. */
116
+ meta?: Record<string, unknown>;
117
+ /**
118
+ * Comma-separated `accept` list (`"image/*,.pdf"`). Filters dropped files and
119
+ * populates the input's `accept` attribute. Absent = accept everything.
120
+ */
121
+ accept?: string; /** Allow multiple files. Defaults to `true`. */
122
+ multiple?: boolean; /** Disable all interaction (no drop, no click-to-open). Defaults to `false`. */
123
+ disabled?: boolean; /** Do not open the file dialog when the root is clicked. Defaults to `false`. */
124
+ noClick?: boolean;
125
+ /**
126
+ * Override the default dispatch. When provided, accepted files are handed here
127
+ * instead of being dispatched as `addFiles` to the store.
128
+ */
129
+ onFiles?: (files: File[]) => void; /** Store instance to dispatch to. Falls back to the `<UploadProvider>` store. */
130
+ store?: Store.UploadStore<Contracts.Intent.Map, Contracts.Cursor.Map<Contracts.Intent.Map>, P, Contracts.Result.Base>;
131
+ };
132
+ /** Return value of {@link useDropzone}. */
133
+ type UseDropzoneReturn = {
134
+ /** True while files are being dragged over the root. */isDragging: boolean; /** Programmatically open the native file picker. */
135
+ open: () => void; /** Ref to attach to the hidden `<input type="file">`. */
136
+ inputRef: React$1.RefObject<HTMLInputElement | null>; /** Spread onto the drop-target element. */
137
+ getRootProps: (extra?: React$1.HTMLAttributes<HTMLElement>) => React$1.HTMLAttributes<HTMLElement>; /** Spread onto the hidden `<input type="file">`. */
138
+ getInputProps: (extra?: React$1.InputHTMLAttributes<HTMLInputElement>) => React$1.InputHTMLAttributes<HTMLInputElement> & {
139
+ ref: React$1.Ref<HTMLInputElement>;
140
+ };
141
+ };
142
+ /**
143
+ * Headless drag-and-drop / file-picker hook.
144
+ *
145
+ * Wires drop and file-input events to the upload store's `addFiles` command
146
+ * (or a custom `onFiles` handler). Returns prop-getters for the drop target and
147
+ * a hidden file input plus a live `isDragging` flag — styling and markup are
148
+ * entirely yours.
149
+ *
150
+ * @example
151
+ * ```tsx
152
+ * function Drop() {
153
+ * const { getRootProps, getInputProps, isDragging, open } = useDropzone({
154
+ * purpose: 'attachment',
155
+ * accept: 'image/*',
156
+ * });
157
+ * return (
158
+ * <div {...getRootProps()} data-active={isDragging}>
159
+ * <input {...getInputProps()} />
160
+ * <button type="button" onClick={open}>Choose files</button>
161
+ * </div>
162
+ * );
163
+ * }
164
+ * ```
165
+ * @author wildduck2 <https://github.com/wildduck2>
166
+ */
167
+ declare function useDropzone<P extends string>(options: UseDropzoneOptions<P>): UseDropzoneReturn;
168
+ //#endregion
169
+ //#region src/react/use-uploader.d.ts
170
+ /**
171
+ * Hook to consume the upload store state, track files, and interact with the upload engine.
172
+ *
173
+ * Exposes files, categorizes items by status phase (ready, uploading, paused, completed, failed),
174
+ * and registers action dispatchers.
175
+ *
176
+ * Can optionally be passed a specific store instance directly. Otherwise, it will read the store from context.
177
+ *
178
+ * @example
179
+ * ```tsx
180
+ * function UploadForm() {
181
+ * const { items, uploading, dispatch } = useUploader();
182
+ *
183
+ * const onFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
184
+ * if (e.target.files) {
185
+ * dispatch({ type: 'addFiles', files: Array.from(e.target.files), purpose: 'avatar' });
186
+ * }
187
+ * };
188
+ *
189
+ * return (
190
+ * <div>
191
+ * <input type="file" onChange={onFileChange} multiple />
192
+ * <ul>
193
+ * {items.map(item => (
194
+ * <li key={item.localId}>{item.fingerprint.name} - {item.phase}</li>
195
+ * ))}
196
+ * </ul>
197
+ * </div>
198
+ * );
199
+ * }
200
+ * ```
201
+ *
202
+ * @template M - Intent map type
203
+ * @template C - Cursor map type
204
+ * @template P - Purpose string union type
205
+ * @template R - Backend result shape
206
+ * @author wildduck2 <https://github.com/wildduck2>
207
+ */
208
+ declare function useUploader<M extends Contracts.Intent.Map, C extends Contracts.Cursor.Map<M>, P extends string, R extends Contracts.Result.Base = Contracts.Result.Base>(providedStore?: Store.UploadStore<M, C, P, R> | undefined): Uploader.State<M, C, P, R>;
209
+ /**
210
+ * Returns the store's imperative actions (dispatch, event bindings) along with a direct
211
+ * reference to the store instance. Does not trigger React re-renders on upload progress or state changes.
212
+ *
213
+ * Use this when you only need to trigger commands or subscribe to events without binding UI lists.
214
+ * @author wildduck2 <https://github.com/wildduck2>
215
+ */
216
+ declare function useUploaderActions<M extends Contracts.Intent.Map, C extends Contracts.Cursor.Map<M>, P extends string, R extends Contracts.Result.Base = Contracts.Result.Base>(): Uploader.IActions<M, C, P, R>;
217
+ /**
218
+ * Creates a bound `useUploader` hook pre-configured for a specific store instance.
219
+ *
220
+ * Useful for building static multi-uploader widgets or context-free setups.
221
+ * @author wildduck2 <https://github.com/wildduck2>
222
+ */
223
+ declare function createUploadFactory<M extends Contracts.Intent.Map, C extends Contracts.Cursor.Map<M>, P extends string, R extends Contracts.Result.Base = Contracts.Result.Base>(store: Store.UploadStore<M, C, P, R>): () => Uploader.State<M, C, P, R>;
224
+ //#endregion
225
+ export { UseDropzoneReturn as a, selectFiles as c, isUploadStore as d, useUploadStore as f, UseDropzoneOptions as i, useDropzone as l, useUploader as n, fileMatchesAccept as o, Uploader as p, useUploaderActions as r, matchesAcceptToken as s, createUploadFactory as t, UploadProvider as u };
@@ -0,0 +1,281 @@
1
+ import { O as Contracts } from "./index-DCqyBVcx.js";
2
+
3
+ //#region src/strategies/multipart/index.d.ts
4
+ /**
5
+ * Namespace containing types and interfaces specific to the S3/MinIO multipart upload strategy.
6
+ * @author wildduck2 <https://github.com/wildduck2>
7
+ */
8
+ declare namespace MultipartStrategy {
9
+ /**
10
+ * Configuration options for the multipart upload strategy.
11
+ */
12
+ type Config = {
13
+ /** Maximum concurrent HTTP PUT part uploads. Defaults to 4. */maxPartConcurrency?: number;
14
+ /**
15
+ * Optional case-insensitive list of trusted hosts (with optional port, e.g. `upload.example.com`).
16
+ * When specified, every signed part URL must match one of the listed hosts.
17
+ */
18
+ allowedHosts?: string[];
19
+ /**
20
+ * When `true`, allows private network IP addresses (loopback, link-local, RFC1918) in signed part URLs.
21
+ * Defaults to `false`.
22
+ */
23
+ allowPrivateHosts?: boolean;
24
+ };
25
+ /**
26
+ * Intent payload detailing part sizing and active upload session IDs returned by backends.
27
+ */
28
+ type Intent = {
29
+ /** Discriminant matching strategy configuration registry keys. */strategy: 'multipart'; /** Unique database identifier for the file resource. */
30
+ fileId: string; /** Active multipart session ID returned by S3/GCS. */
31
+ uploadId: string; /** Chunk size in bytes for each part slice (typically 5MB minimum). */
32
+ partSize: number; /** Total count of parts predicted for this file size. */
33
+ partCount: number; /** Optional array of pre-generated URLs and headers for each part (if signed up front). */
34
+ parts?: Array<{
35
+ partNumber: number;
36
+ url: string;
37
+ headers?: Record<string, string>;
38
+ }>;
39
+ };
40
+ /**
41
+ * Persisted resume state for multipart strategy uploads.
42
+ */
43
+ type Cursor = {
44
+ /** List of completed parts. */done: Array<{
45
+ partNumber: number;
46
+ etag: string;
47
+ size: number;
48
+ }>;
49
+ /**
50
+ * True if the backend assembled the parts.
51
+ * Prevents repeating completeMultipart calls on subsequent resume attempts.
52
+ */
53
+ completed?: true;
54
+ };
55
+ }
56
+ /**
57
+ * S3/GCS-compatible Resumable Multipart Upload Strategy.
58
+ *
59
+ * Slices files into chunks, uploads them concurrently using S3 PUT requests,
60
+ * and completes the upload on the backend once all chunks are transferred.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * const registry = createStrategyRegistry([
65
+ * multipartStrategy({ maxPartConcurrency: 4 })
66
+ * ]);
67
+ * ```
68
+ * @author wildduck2 <https://github.com/wildduck2>
69
+ */
70
+ declare function multipartStrategy<M extends Contracts.Intent.Map & {
71
+ multipart: MultipartStrategy.Intent;
72
+ }, C extends Contracts.Cursor.Map<M> & {
73
+ multipart?: MultipartStrategy.Cursor;
74
+ }, P extends string = string, R extends Contracts.Result.Base = Contracts.Result.Base>(opts?: MultipartStrategy.Config): Contracts.Strategy.Me<M, C, P, R, 'multipart'>;
75
+ //#endregion
76
+ //#region src/strategies/post/index.d.ts
77
+ /**
78
+ * Types for the presigned HTTP POST upload strategy.
79
+ * @author wildduck2 <https://github.com/wildduck2>
80
+ */
81
+ declare namespace PostStrategy {
82
+ /**
83
+ * Presigned HTTP POST strategy configuration options.
84
+ */
85
+ type Config = {
86
+ /**
87
+ * Case-insensitive allow-list of host names (with optional port). When
88
+ * set, the presigned POST URL must match a listed host or it is rejected.
89
+ */
90
+ allowedHosts?: string[];
91
+ /**
92
+ * When `true`, allow private-network IP literals in the POST URL.
93
+ * Defaults to `false`.
94
+ */
95
+ allowPrivateHosts?: boolean;
96
+ /**
97
+ * Retries after the first attempt for transient network failures.
98
+ * Defaults to the shared retry default (3).
99
+ */
100
+ maxRetries?: number;
101
+ };
102
+ /**
103
+ * Presigned HTTP POST intent payload mapping parameters returned by backend endpoints.
104
+ */
105
+ type Intent = {
106
+ /** Discriminant identifier matching strategy configuration registry keys. */strategy: 'post'; /** Unique database identifier for the file resource. */
107
+ fileId: string; /** Presigned POST action destination URL (e.g. presigned S3/GCS bucket location). */
108
+ url: string; /** Key/value pair list representing form properties (e.g. AWS credential fields, policies). */
109
+ fields: Record<string, string>; /** Optional epoch string indicating when the pre-signed credentials lapse. */
110
+ expiresAt?: string;
111
+ };
112
+ /**
113
+ * Direct strategy cursor state representing that no resumable bytes exist.
114
+ */
115
+ type Cursor = Record<string, never>;
116
+ }
117
+ /** Convenience alias for {@link PostStrategy.Intent}. */
118
+ type PostIntent = PostStrategy.Intent;
119
+ /**
120
+ * Presigned HTTP POST form strategy.
121
+ *
122
+ * Sends the entire file along with backend policy fields as a single
123
+ * `multipart/form-data` request body. Does not support resumability.
124
+ *
125
+ * Security: the presigned URL is backend-supplied and flows straight to the
126
+ * transport, so a compromised backend or MITM could return a `file:`,
127
+ * `javascript:`, or private-network URL. Every URL is checked with
128
+ * {@link validateUploadUrl}; set {@link PostStrategy.Config.allowedHosts} to
129
+ * lock it to known hosts, or leave `allowPrivateHosts` at its default `false`
130
+ * to block loopback/private addresses.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * const strategies = createStrategyRegistry([
135
+ * PostStrategy({ allowedHosts: ['uploads.example.com'] }),
136
+ * MultipartStrategy()
137
+ * ]);
138
+ * ```
139
+ * @author wildduck2 <https://github.com/wildduck2>
140
+ */
141
+ declare function PostStrategy<M extends Contracts.Intent.Map, C extends Contracts.Cursor.Map<M>, P extends string, R extends Contracts.Result.Base = Contracts.Result.Base>(opts?: PostStrategy.Config): Contracts.Strategy.Me<M, C, P, R, 'post'>;
142
+ //#endregion
143
+ //#region src/strategies/put/index.d.ts
144
+ /**
145
+ * Types for the single-request presigned HTTP PUT upload strategy.
146
+ * @author wildduck2 <https://github.com/wildduck2>
147
+ */
148
+ declare namespace PutStrategy {
149
+ /**
150
+ * Presigned HTTP PUT strategy configuration options.
151
+ */
152
+ type Config = {
153
+ /**
154
+ * Case-insensitive allow-list of host names (with optional port). When
155
+ * set, the presigned PUT URL must match a listed host or it is rejected.
156
+ */
157
+ allowedHosts?: string[];
158
+ /**
159
+ * When `true`, allow private-network IP literals in the PUT URL.
160
+ * Defaults to `false`.
161
+ */
162
+ allowPrivateHosts?: boolean;
163
+ /**
164
+ * Retries after the first attempt for transient network failures.
165
+ * Defaults to the shared retry default (3).
166
+ */
167
+ maxRetries?: number;
168
+ };
169
+ /**
170
+ * Presigned HTTP PUT intent payload. The whole file body is sent in one
171
+ * request to a backend-signed URL (e.g. S3 `putObject`, GCS signed PUT).
172
+ */
173
+ type Intent = {
174
+ /** Discriminant identifier matching strategy configuration registry keys. */strategy: 'put'; /** Unique database identifier for the file resource. */
175
+ fileId: string; /** Presigned PUT destination URL. */
176
+ url: string; /** Optional request headers required by the signature (e.g. `Content-Type`). */
177
+ headers?: Record<string, string>; /** Optional epoch string indicating when the pre-signed credentials lapse. */
178
+ expiresAt?: string;
179
+ };
180
+ /**
181
+ * Direct strategy cursor state representing that no resumable bytes exist.
182
+ */
183
+ type Cursor = Record<string, never>;
184
+ }
185
+ /** Convenience alias for {@link PutStrategy.Intent}. */
186
+ type PutIntent = PutStrategy.Intent;
187
+ /**
188
+ * Presigned single-request HTTP PUT strategy.
189
+ *
190
+ * Sends the entire file as the request body to a backend-signed URL in one PUT.
191
+ * The most common direct-to-storage pattern (S3 `putObject`, GCS/Azure signed
192
+ * PUT). Not resumable — use {@link multipartStrategy} or the tus strategy for
193
+ * resumable transfers.
194
+ *
195
+ * Security: the presigned URL is backend-supplied and flows straight to the
196
+ * transport, so a compromised backend or MITM could return a `file:`,
197
+ * `javascript:`, or private-network URL. Every URL is checked with
198
+ * {@link validateUploadUrl}; set {@link PutStrategy.Config.allowedHosts} to
199
+ * lock it to known hosts, or leave `allowPrivateHosts` at its default `false`
200
+ * to block loopback/private addresses.
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * const strategies = createStrategyRegistry([
205
+ * PutStrategy({ allowedHosts: ['uploads.example.com'] }),
206
+ * multipartStrategy(),
207
+ * ]);
208
+ * ```
209
+ * @author wildduck2 <https://github.com/wildduck2>
210
+ */
211
+ declare function PutStrategy<M extends Contracts.Intent.Map, C extends Contracts.Cursor.Map<M>, P extends string, R extends Contracts.Result.Base = Contracts.Result.Base>(opts?: PutStrategy.Config): Contracts.Strategy.Me<M, C, P, R, 'put'>;
212
+ //#endregion
213
+ //#region src/strategies/registry/index.d.ts
214
+ /**
215
+ * Create an empty strategy registry. Register upload strategies with `set`, then
216
+ * resolve them by id with `get` / `has`.
217
+ * @author wildduck2 <https://github.com/wildduck2>
218
+ */
219
+ declare function createStrategyRegistry<M extends Contracts.Intent.Map, C extends Contracts.Cursor.Map<M>, P extends string, R extends Contracts.Result.Base = Contracts.Result.Base>(): Contracts.Strategy.Registry<M, C, P, R>;
220
+ //#endregion
221
+ //#region src/strategies/tus/index.d.ts
222
+ /**
223
+ * Types for the tus resumable upload strategy.
224
+ * @author wildduck2 <https://github.com/wildduck2>
225
+ */
226
+ declare namespace TusStrategy {
227
+ /**
228
+ * Configuration options for the tus strategy.
229
+ */
230
+ type Config = {
231
+ /** PATCH chunk size in bytes. Overridden by `intent.chunkSize`. Defaults to 8 MiB. */chunkSize?: number;
232
+ /**
233
+ * Case-insensitive allow-list of host names (with optional port). When set,
234
+ * the tus upload URL must match a listed host or it is rejected.
235
+ */
236
+ allowedHosts?: string[];
237
+ /**
238
+ * When `true`, allow private-network IP literals in the tus URL.
239
+ * Defaults to `false`.
240
+ */
241
+ allowPrivateHosts?: boolean; /** Retries after the first attempt for transient PATCH/HEAD failures. Defaults to 3. */
242
+ maxRetries?: number;
243
+ };
244
+ /**
245
+ * tus intent payload. The backend has already created the upload; `url` is the
246
+ * ready upload resource to PATCH against.
247
+ */
248
+ type Intent = {
249
+ /** Discriminant matching strategy configuration registry keys. */strategy: 'tus'; /** Unique database identifier for the file resource. */
250
+ fileId: string; /** Ready tus upload URL (backend-created via the creation extension). */
251
+ url: string; /** Optional per-upload chunk size override in bytes. */
252
+ chunkSize?: number; /** Optional extra headers to send on every request (e.g. auth). */
253
+ headers?: Record<string, string>;
254
+ };
255
+ /**
256
+ * Persisted resume state: the last acknowledged upload offset in bytes.
257
+ */
258
+ type Cursor = {
259
+ /** Byte offset already accepted by the server. */offset: number;
260
+ };
261
+ }
262
+ /** Convenience alias for {@link TusStrategy.Intent}. */
263
+ type TusIntent = TusStrategy.Intent;
264
+ /**
265
+ * tus resumable upload strategy (creation-less).
266
+ *
267
+ * @example
268
+ * ```ts
269
+ * const registry = createStrategyRegistry([
270
+ * TusStrategy({ allowedHosts: ['tus.example.com'], chunkSize: 8 * 1024 * 1024 }),
271
+ * ]);
272
+ * ```
273
+ * @author wildduck2 <https://github.com/wildduck2>
274
+ */
275
+ declare function TusStrategy<M extends Contracts.Intent.Map & {
276
+ tus: TusStrategy.Intent;
277
+ }, C extends Contracts.Cursor.Map<M> & {
278
+ tus?: TusStrategy.Cursor;
279
+ }, P extends string = string, R extends Contracts.Result.Base = Contracts.Result.Base>(opts?: TusStrategy.Config): Contracts.Strategy.Me<M, C, P, R, 'tus'>;
280
+ //#endregion
281
+ export { PutStrategy as a, MultipartStrategy as c, PutIntent as i, multipartStrategy as l, TusStrategy as n, PostIntent as o, createStrategyRegistry as r, PostStrategy as s, TusIntent as t };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { a as AnyCursor, c as WithSignal, d as IntentBase, f as IntentMap, i as UploadTransport, l as UploadResultBase, n as StrategyRegistry, o as CursorMap, p as StrategyKey, r as UploadStrategy, s as UploadApi, t as StrategyCtx, u as AnyIntent } from "./strategy.types-gg9ZStRe.js";
2
- import { $ as RejectReason, A as serializeSnapshot, B as UploadItem, C as StoreOptions, D as createTypedEmitter, E as UploadEventMap, F as PersistedUploadItem, G as UploadCommand, H as UploadProgress, I as PersistenceAdapter, J as resolveUploadConfig, K as UploadConfig, L as UploadState, M as LocalStorageAdapter, N as IndexedDBAdapter, O as TypedEmitter, P as PersistedSnapshot, Q as BuiltInUploadError, R as createReducer, S as PersistenceOptions, T as UploadStore, U as UploadCompletionKind, V as UploadPhase, W as UploadOutcome, X as createXHRTransport, Y as RetryDecision, Z as FileFingerprint, _ as UploadHooks, a as DEFAULT_MAX_ATTEMPTS, b as DeserializeContext, c as DEFAULT_PROGRESS_THROTTLE_MS, d as sleep, et as UploadError, f as validateFile, g as createUploadClient, h as UploadClient, i as fingerprintMatches, j as MemoryAdapter, k as deserializeSnapshot, l as DEFAULT_RETRY_DELAY_BASE_MS, m as validateIntent, n as isRecord, nt as UploadValidationRules, o as DEFAULT_MAX_CONCURRENT_UPLOADS, p as validateFileList, q as UploadConfigInput, r as computeFingerprint, s as DEFAULT_MAX_ITEMS, t as generateId, tt as UploadErrorBase, u as DEFAULT_RETRY_DELAY_MAX_MS, v as UploadPlugin, w as StoreRuntime, x as InflightUpload, y as createUploadStore, z as InternalEvent } from "./index-C38Jmizu.js";
3
- import { PickItemsByPhase, UploadProvider, UploaderActions, createUploadFactory, useOptionalUploadStore, useUploadStore, useUploader, useUploaderActions } from "./react/index.js";
4
- import { MultipartCursor, MultipartIntent, PostCursor, PostIntent, PostStrategy, createStrategyRegistry, multipartStrategy } from "./strategies/index.js";
5
- export { AnyCursor, AnyIntent, BuiltInUploadError, CursorMap, DEFAULT_MAX_ATTEMPTS, DEFAULT_MAX_CONCURRENT_UPLOADS, DEFAULT_MAX_ITEMS, DEFAULT_PROGRESS_THROTTLE_MS, DEFAULT_RETRY_DELAY_BASE_MS, DEFAULT_RETRY_DELAY_MAX_MS, DeserializeContext, FileFingerprint, IndexedDBAdapter, InflightUpload, IntentBase, IntentMap, InternalEvent, LocalStorageAdapter, MemoryAdapter, MultipartCursor, MultipartIntent, PersistedSnapshot, PersistedUploadItem, PersistenceAdapter, PersistenceOptions, PickItemsByPhase, PostCursor, PostIntent, PostStrategy, RejectReason, RetryDecision, StoreOptions, StoreRuntime, StrategyCtx, StrategyKey, StrategyRegistry, TypedEmitter, UploadApi, UploadClient, UploadCommand, UploadCompletionKind, UploadConfig, UploadConfigInput, UploadError, UploadErrorBase, UploadEventMap, UploadHooks, UploadItem, UploadOutcome, UploadPhase, UploadPlugin, UploadProgress, UploadProvider, UploadResultBase, UploadState, UploadStore, UploadStrategy, UploadTransport, UploadValidationRules, UploaderActions, WithSignal, computeFingerprint, createReducer, createStrategyRegistry, createTypedEmitter, createUploadClient, createUploadFactory, createUploadStore, createXHRTransport, deserializeSnapshot, fingerprintMatches, generateId, isRecord, multipartStrategy, resolveUploadConfig, serializeSnapshot, sleep, useOptionalUploadStore, useUploadStore, useUploader, useUploaderActions, validateFile, validateFileList, validateIntent };
1
+ import { C as UploadUnknownError, D as Transport, E as createXHRTransport, O as Contracts, S as UploadTimeoutError, T as createFetchTransport, _ as UploadHttpError, a as deserializeSnapshot, b as UploadServerError, c as createMemoryAdapter, d as UploadPersistence, f as UploadAbortError, g as UploadErrorContext, h as UploadError, i as Store, l as LocalStorageAdapter, m as UploadEngineError, n as Engine, o as serializeSnapshot, p as UploadAuthError, r as createUploadStore, s as MemoryAdapter, t as resolveUploadConfig, u as IndexedDBAdapter, v as UploadNetworkError, w as UploadValidationError, x as UploadStrategyMissingError, y as UploadRateLimitError } from "./index-DCqyBVcx.js";
2
+ import { a as UseDropzoneReturn, c as selectFiles, d as isUploadStore, f as useUploadStore, i as UseDropzoneOptions, l as useDropzone, n as useUploader, o as fileMatchesAccept, p as Uploader, r as useUploaderActions, s as matchesAcceptToken, t as createUploadFactory, u as UploadProvider } from "./index-DsZHPmJm.js";
3
+ import { a as PutStrategy, c as MultipartStrategy, i as PutIntent, l as multipartStrategy, n as TusStrategy, o as PostIntent, r as createStrategyRegistry, s as PostStrategy, t as TusIntent } from "./index-KROXtLQh.js";
4
+ export { Contracts, Engine, IndexedDBAdapter, LocalStorageAdapter, MemoryAdapter, MultipartStrategy, PostIntent, PostStrategy, PutIntent, PutStrategy, Store, Transport, TusIntent, TusStrategy, UploadAbortError, UploadAuthError, UploadEngineError, UploadError, UploadErrorContext, UploadHttpError, UploadNetworkError, UploadPersistence, UploadProvider, UploadRateLimitError, UploadServerError, UploadStrategyMissingError, UploadTimeoutError, UploadUnknownError, UploadValidationError, Uploader, UseDropzoneOptions, UseDropzoneReturn, createFetchTransport, createMemoryAdapter, createStrategyRegistry, createUploadFactory, createUploadStore, createXHRTransport, deserializeSnapshot, fileMatchesAccept, isUploadStore, matchesAcceptToken, multipartStrategy, resolveUploadConfig, selectFiles, serializeSnapshot, useDropzone, useUploadStore, useUploader, useUploaderActions };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{C as e,S as t,_ as n,a as r,b as i,c as a,d as o,f as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y,v as b,w as x,x as S,y as C}from"./core-CMkrP9DX.js";import{t as w}from"./async-DxRWu4le.js";import{UploadProvider as T,createUploadFactory as E,useOptionalUploadStore as D,useUploadStore as O,useUploader as k,useUploaderActions as A}from"./react/index.js";import{PostStrategy as j,createStrategyRegistry as M,multipartStrategy as N}from"./strategies/index.js";export{C as DEFAULT_MAX_ATTEMPTS,i as DEFAULT_MAX_CONCURRENT_UPLOADS,S as DEFAULT_MAX_ITEMS,t as DEFAULT_PROGRESS_THROTTLE_MS,e as DEFAULT_RETRY_DELAY_BASE_MS,x as DEFAULT_RETRY_DELAY_MAX_MS,d as IndexedDBAdapter,a as LocalStorageAdapter,_ as MemoryAdapter,j as PostStrategy,T as UploadProvider,o as computeFingerprint,g as createReducer,M as createStrategyRegistry,u as createTypedEmitter,v as createUploadClient,E as createUploadFactory,p as createUploadStore,y as createXHRTransport,r as deserializeSnapshot,s as fingerprintMatches,n as generateId,c as isRecord,N as multipartStrategy,b as resolveUploadConfig,m as serializeSnapshot,w as sleep,D as useOptionalUploadStore,O as useUploadStore,k as useUploader,A as useUploaderActions,h as validateFile,f as validateFileList,l as validateIntent};
1
+ import{C as e,S as t,_ as n,a as r,b as i,c as a,f as o,g as s,h as c,i as l,l as u,m as d,n as f,o as p,p as m,r as h,s as g,t as _,u as v,v as y,x as b,y as x}from"./core-BVgloTiP.js";import{a as S,c as C,i as w,l as T,n as E,o as D,r as O,s as k,t as A,u as j}from"./react-euPrDv24.js";import{a as M,i as N,n as P,r as F,t as I}from"./strategies-CUF0s68j.js";export{_ as Engine,a as IndexedDBAdapter,g as LocalStorageAdapter,r as MemoryAdapter,N as PostStrategy,F as PutStrategy,I as TusStrategy,o as UploadAbortError,m as UploadAuthError,d as UploadEngineError,c as UploadHttpError,s as UploadNetworkError,C as UploadProvider,n as UploadRateLimitError,y as UploadServerError,x as UploadStrategyMissingError,i as UploadTimeoutError,b as UploadUnknownError,t as UploadValidationError,u as createFetchTransport,p as createMemoryAdapter,P as createStrategyRegistry,A as createUploadFactory,f as createUploadStore,v as createXHRTransport,h as deserializeSnapshot,w as fileMatchesAccept,T as isUploadStore,S as matchesAcceptToken,M as multipartStrategy,e as resolveUploadConfig,D as selectFiles,l as serializeSnapshot,k as useDropzone,j as useUploadStore,E as useUploader,O as useUploaderActions};
@@ -1,51 +1,2 @@
1
- import { f as IntentMap, l as UploadResultBase, o as CursorMap } from "../strategy.types-gg9ZStRe.js";
2
- import { B as UploadItem, E as UploadEventMap, G as UploadCommand, T as UploadStore, V as UploadPhase } from "../index-C38Jmizu.js";
3
- import { ReactNode } from "react";
4
-
5
- //#region src/react/upload-provider.d.ts
6
- /** Provides an upload store to descendants. */
7
- declare function UploadProvider<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase>({
8
- store,
9
- children
10
- }: {
11
- store: UploadStore<M, C, P, R>;
12
- children: ReactNode;
13
- }): React.JSX.Element;
14
- /**
15
- * Read the upload store from context if provided. Returns `null` outside a
16
- * provider so higher-level hooks can keep their context read unconditional
17
- * while still accepting an explicit store argument.
18
- */
19
- declare function useOptionalUploadStore<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase>(): UploadStore<M, C, P, R> | null;
20
- /** Read the upload store from context. Throws when called outside `UploadProvider`. */
21
- declare function useUploadStore<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase>(): UploadStore<M, C, P, R>;
22
- //#endregion
23
- //#region src/react/use-uploader.d.ts
24
- declare function createUploadFactory<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase>(store: UploadStore<M, C, P, R>): () => Uploader<M, C, P, R>;
25
- type PickItemsByPhase<Phase extends UploadPhase> = Extract<UploadItem<IntentMap, CursorMap<IntentMap>, string, UploadResultBase>, {
26
- phase: Phase;
27
- }>;
28
- type Uploader<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase> = {
29
- items: UploadItem<M, C, P, R>[];
30
- byPhase: Record<string, UploadItem<M, C, P, R>[]>;
31
- dispatch: (cmd: UploadCommand<P>) => void;
32
- on: <K extends keyof UploadEventMap<M, C, P, R> & string>(type: K, cb: (payload: UploadEventMap<M, C, P, R>[K]) => void) => () => void;
33
- off: <K extends keyof UploadEventMap<M, C, P, R> & string>(type: K, cb: (payload: UploadEventMap<M, C, P, R>[K]) => void) => () => void;
34
- uploading: UploadItem<M, C, P, R>[];
35
- paused: UploadItem<M, C, P, R>[];
36
- completed: UploadItem<M, C, P, R>[];
37
- failed: UploadItem<M, C, P, R>[];
38
- ready: UploadItem<M, C, P, R>[];
39
- };
40
- /**
41
- * Imperative action surface. Declared explicitly (not inferred) so generated
42
- * .d.ts files do not leak internal generic names created by `store.on.bind(store)`.
43
- */
44
- type UploaderActions<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase> = Pick<UploadStore<M, C, P, R>, 'dispatch' | 'on'> & {
45
- store: UploadStore<M, C, P, R>;
46
- };
47
- declare function useUploader<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase>(): Uploader<M, C, P, R>;
48
- declare function useUploader<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase>(store: UploadStore<M, C, P, R>): Uploader<M, C, P, R>;
49
- declare function useUploaderActions<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase>(): UploaderActions<M, C, P, R>;
50
- //#endregion
51
- export { PickItemsByPhase, UploadProvider, UploaderActions, createUploadFactory, useOptionalUploadStore, useUploadStore, useUploader, useUploaderActions };
1
+ import { a as UseDropzoneReturn, c as selectFiles, d as isUploadStore, f as useUploadStore, i as UseDropzoneOptions, l as useDropzone, n as useUploader, o as fileMatchesAccept, p as Uploader, r as useUploaderActions, s as matchesAcceptToken, t as createUploadFactory, u as UploadProvider } from "../index-DsZHPmJm.js";
2
+ export { UploadProvider, Uploader, UseDropzoneOptions, UseDropzoneReturn, createUploadFactory, fileMatchesAccept, isUploadStore, matchesAcceptToken, selectFiles, useDropzone, useUploadStore, useUploader, useUploaderActions };
@@ -1 +1 @@
1
- import{g as e}from"../core-CMkrP9DX.js";import{jsxDEV as t}from"react/jsx-dev-runtime";import*as n from"react";import{createContext as r,useContext as i}from"react";const a=r(null);function o({store:e,children:n}){return t(a.Provider,{value:e,children:n},void 0,!1,{fileName:`/home/runner/work/duck-upload/duck-upload/packages/duck-upload/src/react/upload-provider.tsx`,lineNumber:18,columnNumber:10},this)}function s(){let e=i(a);if(e===null)return null;if(!l(e))throw Error(`UploadProvider received an invalid store value`);return e}function c(){let e=s();if(!e)throw Error(`useUploadStore must be used within UploadProvider`);return e}function l(t){return e(t)?typeof t.getSnapshot==`function`&&typeof t.subscribe==`function`&&typeof t.dispatch==`function`&&typeof t.on==`function`&&typeof t.off==`function`&&typeof t.waitFor==`function`:!1}function u(e){return()=>d(e)}function d(e){let t=s(),r=e??t;if(!r)throw Error(`useUploader must be used within UploadProvider when no store argument is provided`);let i=n.useSyncExternalStore(r.subscribe.bind(r),r.getSnapshot.bind(r),r.getSnapshot.bind(r)),a=n.useMemo(()=>Array.from(i.items.values()),[i.items]),o=n.useMemo(()=>{let e={};return a.forEach(t=>{e[t.phase]||(e[t.phase]=[]),e[t.phase].push(t)}),e},[a]);return{items:a,byPhase:o,dispatch:r.dispatch.bind(r),on:r.on.bind(r),off:r.off.bind(r),uploading:o.uploading||[],paused:o.paused||[],completed:o.completed||[],failed:o.error||[],ready:o.ready||[]}}function f(){let e=c();return{dispatch:n.useMemo(()=>e.dispatch.bind(e),[e]),on:n.useMemo(()=>e.on.bind(e),[e]),store:e}}export{o as UploadProvider,u as createUploadFactory,s as useOptionalUploadStore,c as useUploadStore,d as useUploader,f as useUploaderActions};
1
+ import{a as e,c as t,i as n,l as r,n as i,o as a,r as o,s,t as c,u as l}from"../react-euPrDv24.js";export{t as UploadProvider,c as createUploadFactory,n as fileMatchesAccept,r as isUploadStore,e as matchesAcceptToken,a as selectFiles,s as useDropzone,l as useUploadStore,i as useUploader,o as useUploaderActions};
@@ -0,0 +1 @@
1
+ import{jsxDEV as e}from"react/jsx-dev-runtime";import*as t from"react";import{createContext as n,useCallback as r,useContext as i,useEffect as a,useMemo as o,useRef as s,useState as c,useSyncExternalStore as l}from"react";const u=n(null);function d({store:t,children:n}){return a(()=>()=>{`destroy`in t&&typeof t.destroy==`function`&&t.destroy()},[t]),e(u.Provider,{value:t,children:n},void 0,!1,{fileName:`/home/runner/work/duck-upload/duck-upload/packages/duck-upload/src/react/upload-provider.tsx`,lineNumber:43,columnNumber:10},this)}function f(){let e=i(u);if(!e)throw Error(`useUploadStore must be used within an <UploadProvider>`);return e}function p(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.getSnapshot==`function`&&typeof t.subscribe==`function`&&typeof t.dispatch==`function`&&typeof t.on==`function`&&typeof t.off==`function`&&typeof t.waitFor==`function`}function m(e,t){let n=t.trim().toLowerCase();if(!n)return!1;if(n.startsWith(`.`))return e.name.toLowerCase().endsWith(n);let r=(e.type||``).toLowerCase();return n.endsWith(`/*`)?r.startsWith(`${n.slice(0,-1)}`):r===n}function h(e,t){if(!t)return!0;let n=t.split(`,`).map(e=>e.trim()).filter(Boolean);return n.length===0?!0:n.some(t=>m(e,t))}function g(e,t){let n=e.filter(e=>h(e,t.accept));return t.multiple===!1?n.slice(0,1):n}function _(e){let{purpose:t,meta:n,accept:i,multiple:a=!0,disabled:l=!1,noClick:u=!1,onFiles:d}=e,p=f(),m=e.store??p,h=s(null),[_,v]=c(!1),y=s(0),b=r(e=>{if(!e||e.length===0)return;let r=g(Array.from(e),{accept:i,multiple:a});r.length!==0&&(d?d(r):m.dispatch({type:`addFiles`,files:r,purpose:t,meta:n}))},[i,a,d,m,t,n]),x=r(()=>{l||h.current?.click()},[l]),S=r((e={})=>({...e,onDragEnter:t=>{e.onDragEnter?.(t),!l&&(t.preventDefault(),t.stopPropagation(),y.current+=1,v(!0))},onDragOver:t=>{e.onDragOver?.(t),!l&&(t.preventDefault(),t.stopPropagation())},onDragLeave:t=>{e.onDragLeave?.(t),!l&&(t.preventDefault(),t.stopPropagation(),y.current=Math.max(0,y.current-1),y.current===0&&v(!1))},onDrop:t=>{e.onDrop?.(t),!l&&(t.preventDefault(),t.stopPropagation(),y.current=0,v(!1),b(t.dataTransfer?.files??null))},onClick:t=>{e.onClick?.(t),!(l||u)&&x()}}),[l,u,x,b]),C=r((e={})=>({...e,ref:h,type:`file`,multiple:a,disabled:l,...i?{accept:i}:{},style:{display:`none`,...e.style},onChange:t=>{e.onChange?.(t),b(t.target.files),t.target.value=``}}),[a,l,i,b]);return o(()=>({isDragging:_,open:x,inputRef:h,getRootProps:S,getInputProps:C}),[_,x,S,C])}function v(e){let t=f(),n=e??t;if(!n)throw Error(`useUploader must be used within an <UploadProvider> or passed a store instance directly.`);let r=l(n.subscribe,n.getSnapshot,n.getSnapshot),i=o(()=>Array.from(r.items.values()),[r]),a=o(()=>{let e={validating:[],creating_intent:[],ready:[],queued:[],uploading:[],paused:[],completing:[],completed:[],error:[],canceled:[]};return i.forEach(t=>{let n=t.phase;e[n]||(e[n]=[]),e[n].push(t)}),e},[i]);return{items:i,byPhase:a,dispatch:n.dispatch.bind(n),on:n.on.bind(n),off:n.off.bind(n),uploading:a.uploading||[],paused:a.paused||[],completed:a.completed||[],failed:a.error||[],ready:a.ready||[]}}function y(){let e=f();return{dispatch:t.useMemo(()=>e.dispatch.bind(e),[e]),on:t.useMemo(()=>e.on.bind(e),[e]),store:e}}function b(e){return()=>v(e)}export{m as a,d as c,h as i,p as l,v as n,g as o,y as r,_ as s,b as t,f as u};