@thetechfossil/upfiles 0.5.0 → 0.6.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 +75 -367
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -1,414 +1,122 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Upfiles Packages Plugin
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A comprehensive package solution for managing projects and API keys in Upfiles applications.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package provides both a user-friendly dialog interface and reusable functions for managing projects and API keys. It allows developers to either use the pre-built dialog component or integrate the underlying logic directly into their applications.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Multi-functional dialog for managing projects and API keys
|
|
12
|
+
- Reusable functions for programmatic integration
|
|
13
|
+
- Full CRUD operations for projects and API keys
|
|
14
|
+
- Authentication-aware API interactions
|
|
15
|
+
- TypeScript support with comprehensive type definitions
|
|
8
16
|
|
|
9
17
|
## Installation
|
|
10
18
|
|
|
11
19
|
```bash
|
|
12
|
-
# Bun (recommended)
|
|
13
|
-
bun add @thetechfossil/upfiles
|
|
14
|
-
|
|
15
|
-
# npm
|
|
16
20
|
npm install @thetechfossil/upfiles
|
|
21
|
+
```
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
pnpm add @thetechfossil/upfiles
|
|
23
|
+
## API Routes
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
yarn add @thetechfossil/upfiles
|
|
23
|
-
```
|
|
25
|
+
### Projects
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
- `GET /api/packages/projects` - List all projects for the current user
|
|
28
|
+
- `POST /api/packages/projects` - Create a new project for the current user
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
### API Keys
|
|
28
31
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
- Response: `{ presignedUrl, fileKey, publicUrl, apiKeyId?, projectId? }`
|
|
32
|
+
- `GET /api/packages/projects/{projectId}/keys` - List API keys for a project
|
|
33
|
+
- `POST /api/packages/projects/{projectId}/keys` - Create a new API key for a project
|
|
34
|
+
- `DELETE /api/packages/projects/{projectId}/keys` - Revoke an API key
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
## Package Components
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
### 1. Dialog Component
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
The `ProjectKeyDialog` component provides a complete UI for managing projects and API keys:
|
|
39
41
|
|
|
40
42
|
```tsx
|
|
41
|
-
import
|
|
43
|
+
import ProjectKeyDialog from "@thetechfossil/upfiles/packages/dialog/ProjectKeyDialog";
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
function MyComponent() {
|
|
44
46
|
return (
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
onComplete={(files) => {
|
|
50
|
-
console.log('uploaded:', files);
|
|
47
|
+
<ProjectKeyDialog
|
|
48
|
+
userId="user-123"
|
|
49
|
+
onProjectSelected={(projectId) => {
|
|
50
|
+
// Handle project selection
|
|
51
51
|
}}
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
onApiKeySaved={(apiKey) => {
|
|
53
|
+
// Handle API key creation
|
|
54
54
|
}}
|
|
55
|
-
dropzoneClassName="border border-dashed rounded-md p-6 cursor-pointer"
|
|
56
|
-
buttonClassName="px-3 py-2 rounded bg-blue-600 text-white"
|
|
57
|
-
// Optional: pass clientOptions for cross-origin + API key auth
|
|
58
|
-
// clientOptions={{
|
|
59
|
-
// baseUrl: 'https://YOUR_APP_HOST',
|
|
60
|
-
// // or presignUrl: 'https://YOUR_APP_HOST/api/plugin/upload/presigned-url',
|
|
61
|
-
// apiKey: process.env.NEXT_PUBLIC_UPFILES_API_KEY!,
|
|
62
|
-
// apiKeyHeader: 'authorization', // or 'x-api-key' | 'x-up-api-key'
|
|
63
|
-
// }}
|
|
64
55
|
/>
|
|
65
56
|
);
|
|
66
57
|
}
|
|
67
58
|
```
|
|
68
59
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
```ts
|
|
72
|
-
import { UpfilesClient } from '@thetechfossil/upfiles';
|
|
73
|
-
|
|
74
|
-
// Same-origin by default; only set these when needed:
|
|
75
|
-
const client = new UpfilesClient({
|
|
76
|
-
// presignUrl: 'https://YOUR_APP_HOST/api/plugin/upload/presigned-url', // full override
|
|
77
|
-
// baseUrl: 'https://YOUR_APP_HOST', // used with presignPath
|
|
78
|
-
// presignPath: '/api/plugin/upload/presigned-url', // default
|
|
79
|
-
// withCredentials: true, // for session routes (not typical for Plugin API)
|
|
80
|
-
// Provide API key for Plugin API auth:
|
|
81
|
-
// apiKey: 'upk_...'
|
|
82
|
-
// apiKeyHeader: 'authorization' // or 'x-api-key' | 'x-up-api-key'
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
async function upload(file) {
|
|
86
|
-
const { presignedUrl, publicUrl } = await client.getPresignedUrl({
|
|
87
|
-
fileName: file.name,
|
|
88
|
-
fileType: file.type,
|
|
89
|
-
fileSize: file.size, // required
|
|
90
|
-
folderPath: 'my-plugin/uploads/',
|
|
91
|
-
});
|
|
92
|
-
const res = await client.uploadToS3(presignedUrl, file);
|
|
93
|
-
if (!res.ok) throw new Error('Upload failed');
|
|
94
|
-
return publicUrl;
|
|
95
|
-
}
|
|
96
|
-
```
|
|
60
|
+
### 2. Reusable Functions
|
|
97
61
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
- `new UpfilesClient(options)`
|
|
101
|
-
- `presignUrl` (optional): full absolute URL to presign endpoint. Highest priority.
|
|
102
|
-
- `baseUrl` (optional): API base origin. Used with `presignPath`.
|
|
103
|
-
- `presignPath` (optional): relative path, default `/api/plugin/upload/presigned-url`.
|
|
104
|
-
- `headers` (optional): extra headers to send.
|
|
105
|
-
- `apiKey` (optional): API key value (e.g., `upk_...`).
|
|
106
|
-
- `apiKeyHeader` (optional): one of `'authorization' | 'x-api-key' | 'x-up-api-key'` (default `'authorization'`). If `'authorization'`, `Bearer` prefix is auto-added for `upk_...`.
|
|
107
|
-
- `withCredentials` (optional): `true` to send cookies.
|
|
108
|
-
- Defaults: same-origin requests to `/api/plugin/upload/presigned-url`.
|
|
109
|
-
- `client.getPresignedUrl({ fileName, fileType, fileSize, projectId?, folderPath? })`
|
|
110
|
-
- `client.uploadToS3(presignedUrl, file)`
|
|
111
|
-
- `client.upload(file, { projectId?, folderPath?, fetchThumbnails? })` → returns `{ publicUrl, fileKey, fileName, fileType, fileSize, projectId?, apiKeyId?, thumbnails? }`
|
|
112
|
-
- `client.getThumbnails(fileKey)` → returns `Thumbnail[]`
|
|
113
|
-
- `client.getProjectFiles({ folderPath? })` → returns `FileListItem[]`
|
|
114
|
-
|
|
115
|
-
- `<Uploader />` props
|
|
116
|
-
- `clientOptions` (optional): same as `UpfilesClient` options (only needed for cross-origin or auth customization)
|
|
117
|
-
- `multiple` (default true)
|
|
118
|
-
- `accept` (array of MIME patterns)
|
|
119
|
-
- `maxFileSize` (bytes, default 100MB)
|
|
120
|
-
- `maxFiles` (default 10)
|
|
121
|
-
- `fetchThumbnails` (boolean): if true, fetch thumbnails after upload via Plugin API
|
|
122
|
-
- `onComplete(files)` and `onError(error)`
|
|
123
|
-
- `className`, `buttonClassName`, `dropzoneClassName`
|
|
124
|
-
- `children`: custom dropzone inner content
|
|
125
|
-
|
|
126
|
-
### Thumbnails usage
|
|
127
|
-
|
|
128
|
-
Your Upfiles app exposes `GET /api/plugin/thumbnails?fileKey=...` for plugins. Enable `fetchThumbnails` to auto-fetch after upload, or call `client.getThumbnails(fileKey)` yourself.
|
|
129
|
-
|
|
130
|
-
Example with `client.upload`:
|
|
62
|
+
#### Project Management
|
|
131
63
|
|
|
132
64
|
```ts
|
|
133
|
-
|
|
134
|
-
|
|
65
|
+
import {
|
|
66
|
+
listProjects,
|
|
67
|
+
createProject,
|
|
68
|
+
updateProject,
|
|
69
|
+
deleteProject,
|
|
70
|
+
} from "@thetechfossil/upfiles/packages/projectManager";
|
|
71
|
+
|
|
72
|
+
// List projects
|
|
73
|
+
const { projects } = await listProjects("user-123");
|
|
74
|
+
|
|
75
|
+
// Create project
|
|
76
|
+
const newProject = await createProject("user-123", { name: "My Project" });
|
|
135
77
|
```
|
|
136
78
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
Your Upfiles app exposes `GET /api/plugin/files?folderPath=...` for plugins (API key auth + CORS). The client can call it via `getProjectFiles`:
|
|
79
|
+
#### API Key Management
|
|
140
80
|
|
|
141
81
|
```ts
|
|
142
|
-
import {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
82
|
+
import {
|
|
83
|
+
listApiKeys,
|
|
84
|
+
createApiKey,
|
|
85
|
+
revokeApiKey,
|
|
86
|
+
} from "@thetechfossil/upfiles/packages/apiKeyManager";
|
|
87
|
+
|
|
88
|
+
// List API keys
|
|
89
|
+
const { keys } = await listApiKeys("project-456");
|
|
90
|
+
|
|
91
|
+
// Create API key
|
|
92
|
+
const { key } = await createApiKey({
|
|
93
|
+
projectId: "project-456",
|
|
94
|
+
name: "CI Pipeline Key",
|
|
148
95
|
});
|
|
149
|
-
|
|
150
|
-
const files = await client.getProjectFiles({ folderPath: 'optional/subfolder' });
|
|
151
|
-
// [{ key, originalName, size, contentType, uploadedAt, url }, ...]
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### `<ProjectFilesWidget />`
|
|
155
|
-
|
|
156
|
-
Simple UI to fetch and select a file for the project tied to the API key. Emits the selection, and can optionally POST it to your backend.
|
|
157
|
-
|
|
158
|
-
```tsx
|
|
159
|
-
import { ProjectFilesWidget } from '@thetechfossil/upfiles';
|
|
160
|
-
|
|
161
|
-
export default function PickFile() {
|
|
162
|
-
return (
|
|
163
|
-
<ProjectFilesWidget
|
|
164
|
-
clientOptions={{
|
|
165
|
-
baseUrl: 'https://YOUR_APP_HOST',
|
|
166
|
-
apiKey: process.env.NEXT_PUBLIC_UPFILES_API_KEY!,
|
|
167
|
-
apiKeyHeader: 'authorization',
|
|
168
|
-
thumbnailsPath: '/api/plugin/thumbnails',
|
|
169
|
-
}}
|
|
170
|
-
// Optional: filter within a folder
|
|
171
|
-
// folderPath="my-plugin/"
|
|
172
|
-
|
|
173
|
-
onSelect={(f) => {
|
|
174
|
-
// { name, key, url, size, contentType }
|
|
175
|
-
console.log('Selected:', f.name, f.key);
|
|
176
|
-
}}
|
|
177
|
-
|
|
178
|
-
// Optional: built-in save
|
|
179
|
-
// saveUrl="/api/files/save" // Your app route to persist selection
|
|
180
|
-
// onSave={async (f) => { await fetch('/api/files/save', { method: 'POST', body: JSON.stringify(f) }); }}
|
|
181
|
-
// onSaved={(result) => console.log('Saved!', result)}
|
|
182
|
-
/>
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
96
|
```
|
|
186
97
|
|
|
187
|
-
##
|
|
188
|
-
|
|
189
|
-
- Dev with Vite: configure a proxy so `/api/*` maps to your backend (e.g., `http://localhost:4000`), then `<Uploader />` works with no config.
|
|
190
|
-
- Ensure CORS where applicable (S3 bucket CORS; and set `PLUGIN_ALLOWED_ORIGINS` on your Upfiles app for cross-origin Plugin API calls).
|
|
191
|
-
- For cross-origin with cookies (NextAuth), set `withCredentials: true` and configure your server to allow credentials.
|
|
192
|
-
Plugin API typically uses API keys instead of cookies.
|
|
193
|
-
|
|
194
|
-
### Plugin endpoints provided by this repo
|
|
195
|
-
|
|
196
|
-
- `POST /api/plugin/upload/presigned-url` – generate presigned S3 URL for upload
|
|
197
|
-
- `GET /api/plugin/thumbnails?fileKey=...` – list thumbnails for a file
|
|
198
|
-
- `GET /api/plugin/files?folderPath=...` – list project files (API key scoped), optional folder prefix
|
|
199
|
-
|
|
200
|
-
## Full API Reference
|
|
201
|
-
|
|
202
|
-
__UpfilesClient(options)__
|
|
203
|
-
|
|
204
|
-
- __options.baseUrl?: string__
|
|
205
|
-
Base origin, for cross-origin Plugin API calls, e.g. `https://upfiles.example.com`. If omitted, requests are same-origin.
|
|
206
|
-
- __options.presignPath?: string__
|
|
207
|
-
Relative path to the presign endpoint (default `/api/plugin/upload/presigned-url`). Used when `presignUrl` is not set.
|
|
208
|
-
- __options.presignUrl?: string__
|
|
209
|
-
Full absolute URL. If provided, it overrides `baseUrl + presignPath`.
|
|
210
|
-
- __options.headers?: Record<string,string>__
|
|
211
|
-
Extra headers to send with every request.
|
|
212
|
-
- __options.withCredentials?: boolean__
|
|
213
|
-
If true, send cookies (useful for session-based routes). Plugin API typically uses API keys instead.
|
|
214
|
-
- __options.apiKey?: string__
|
|
215
|
-
API key value (e.g., `upk_...`).
|
|
216
|
-
- __options.apiKeyHeader?: 'authorization' | 'x-api-key' | 'x-up-api-key'__
|
|
217
|
-
Header to carry the API key. Default `'authorization'`. If set to `'authorization'` and the key starts with `upk_`, `Bearer ${key}` is auto-applied.
|
|
218
|
-
- __options.thumbnailsPath?: string__
|
|
219
|
-
Relative path to thumbnails endpoint, default `/api/plugin/thumbnails`. Used to derive `/api/plugin/files`.
|
|
220
|
-
|
|
221
|
-
Methods
|
|
222
|
-
|
|
223
|
-
- __getPresignedUrl({ fileName, fileType, fileSize, projectId?, folderPath? }): Promise<PresignResponse>__
|
|
224
|
-
Validates inputs and POSTs to the presign endpoint. Returns `{ presignedUrl, fileKey, publicUrl, apiKeyId?, projectId? }`.
|
|
225
|
-
- __uploadToS3(presignedUrl: string, file: File): Promise<Response>__
|
|
226
|
-
Executes the signed PUT request to S3. You are responsible for checking `res.ok`.
|
|
227
|
-
- __upload(file: File, extras?: { projectId?, folderPath?, fetchThumbnails? }): Promise<UploadedFileResult>__
|
|
228
|
-
Convenience method: presign + PUT + optional thumbnails fetch. Returns `{ publicUrl, fileKey, fileName, fileType, fileSize, projectId?, apiKeyId?, thumbnails? }`.
|
|
229
|
-
- __getThumbnails(fileKey: string): Promise<Thumbnail[]>__
|
|
230
|
-
Calls `GET /api/plugin/thumbnails?fileKey=...`.
|
|
231
|
-
- __getProjectFiles({ folderPath? }?): Promise<FileListItem[]>__
|
|
232
|
-
Calls `GET /api/plugin/files?folderPath=...` (derived from `thumbnailsPath`). Returns metadata for each file.
|
|
233
|
-
|
|
234
|
-
Types
|
|
98
|
+
## Usage Examples
|
|
235
99
|
|
|
236
|
-
|
|
237
|
-
type PresignResponse = {
|
|
238
|
-
presignedUrl: string;
|
|
239
|
-
fileKey: string;
|
|
240
|
-
publicUrl: string;
|
|
241
|
-
apiKeyId?: string;
|
|
242
|
-
projectId?: string;
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
type UploadedFileResult = {
|
|
246
|
-
publicUrl: string;
|
|
247
|
-
fileKey: string;
|
|
248
|
-
fileName: string;
|
|
249
|
-
fileType: string;
|
|
250
|
-
fileSize: number;
|
|
251
|
-
projectId?: string;
|
|
252
|
-
apiKeyId?: string;
|
|
253
|
-
thumbnails?: Thumbnail[];
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
type Thumbnail = {
|
|
257
|
-
id: string;
|
|
258
|
-
key: string;
|
|
259
|
-
url: string;
|
|
260
|
-
size: number;
|
|
261
|
-
sizeType?: string;
|
|
262
|
-
createdAt?: string;
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
type FileListItem = {
|
|
266
|
-
key: string;
|
|
267
|
-
originalName: string;
|
|
268
|
-
size: number;
|
|
269
|
-
contentType: string;
|
|
270
|
-
uploadedAt: string;
|
|
271
|
-
url: string;
|
|
272
|
-
};
|
|
273
|
-
```
|
|
100
|
+
See `packages/examples/usageExample.ts` for detailed usage examples.
|
|
274
101
|
|
|
275
|
-
##
|
|
276
|
-
|
|
277
|
-
__<Uploader />__ from `src/Uploader.tsx`
|
|
278
|
-
|
|
279
|
-
- __clientOptions?: UpfilesClientOptions__
|
|
280
|
-
Supply `baseUrl`, `apiKey`, etc., only if doing cross-origin or custom auth.
|
|
281
|
-
- __multiple?: boolean__ (default: true)
|
|
282
|
-
- __accept?: string[]__
|
|
283
|
-
MIME patterns, default includes common image/video/audio/pdf/text/json.
|
|
284
|
-
- __maxFileSize?: number__ (bytes; default: 100MB)
|
|
285
|
-
- __maxFiles?: number__ (default: 10)
|
|
286
|
-
- __projectId?: string__
|
|
287
|
-
- __folderPath?: string__
|
|
288
|
-
- __fetchThumbnails?: boolean__
|
|
289
|
-
After a successful upload, fetch thumbnails via Plugin API.
|
|
290
|
-
- __onComplete?: (files: UploaderFile[]) => void__
|
|
291
|
-
Called with successful items.
|
|
292
|
-
- __onError?: (error: Error) => void__
|
|
293
|
-
- __className?, buttonClassName?, dropzoneClassName?__
|
|
294
|
-
- __children?__: custom inner content for dropzone.
|
|
295
|
-
|
|
296
|
-
Uploader item shape
|
|
102
|
+
## Comprehensive Package Documentation
|
|
297
103
|
|
|
298
|
-
|
|
299
|
-
type UploaderFile = {
|
|
300
|
-
id: string;
|
|
301
|
-
file: File;
|
|
302
|
-
name: string;
|
|
303
|
-
size: number;
|
|
304
|
-
type: string;
|
|
305
|
-
progress: number; // 0-100
|
|
306
|
-
status: 'pending' | 'uploading' | 'success' | 'error';
|
|
307
|
-
error?: string;
|
|
308
|
-
publicUrl?: string;
|
|
309
|
-
fileKey?: string;
|
|
310
|
-
projectId?: string;
|
|
311
|
-
apiKeyId?: string;
|
|
312
|
-
// thumbnails?: Thumbnail[] // added at runtime if fetchThumbnails
|
|
313
|
-
};
|
|
314
|
-
```
|
|
104
|
+
For detailed package documentation including installation instructions, configuration options, usage examples, available methods and functions, parameter specifications, return value descriptions, troubleshooting guides, best practices, and detailed explanations of all package features and capabilities, see: [`docs/PACKAGE_DOCUMENTATION.md`](docs/PACKAGE_DOCUMENTATION.md)
|
|
315
105
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
- Uses `XMLHttpRequest` for the S3 PUT to expose upload progress.
|
|
319
|
-
- Progress caps at 99% until completion; then sets to 100% on success.
|
|
320
|
-
- Sets `Content-Type` header to file.type (or `application/octet-stream`).
|
|
321
|
-
|
|
322
|
-
__<ProjectFilesWidget />__ from `src/ProjectFilesWidget.tsx`
|
|
323
|
-
|
|
324
|
-
- __clientOptions: UpfilesClientOptions__
|
|
325
|
-
Provide `baseUrl` and `apiKey` (or `withCredentials`) for Plugin API.
|
|
326
|
-
- __folderPath?: string__
|
|
327
|
-
- __className?, listClassName?, itemClassName?__
|
|
328
|
-
- __onSelect(file): void__
|
|
329
|
-
Receives `{ name, key, url, size, contentType }`.
|
|
330
|
-
- __saveUrl?: string__
|
|
331
|
-
If set, the component will POST the selected file JSON to this URL (same-origin).
|
|
332
|
-
- __onSave?: (file) => Promise<void> | void__
|
|
333
|
-
- __onSaved?: (result?: any) => void__
|
|
334
|
-
|
|
335
|
-
Behavior
|
|
336
|
-
|
|
337
|
-
- Loads files via `client.getProjectFiles({ folderPath })` on mount and when refreshed.
|
|
338
|
-
- Client-side search by filename.
|
|
339
|
-
- Built-in "Use" action triggers `onSelect`, optional `onSave` and/or POST to `saveUrl`.
|
|
340
|
-
|
|
341
|
-
## Configuration and Auth
|
|
342
|
-
|
|
343
|
-
- __Same-origin__ usage needs no config. Ensure your app exposes the Plugin API routes documented above.
|
|
344
|
-
- __Cross-origin plugins__ should:
|
|
345
|
-
- Set `baseUrl` to your Upfiles app origin.
|
|
346
|
-
- Provide `apiKey` and set `apiKeyHeader` as needed. If using `'authorization'` and key starts with `upk_`, `Bearer` is added automatically.
|
|
347
|
-
- Configure CORS on the Upfiles app to allow your plugin origin.
|
|
348
|
-
- __Cookies with NextAuth or session routes__:
|
|
349
|
-
- Set `withCredentials: true` in `UpfilesClient` and allow credentials server-side. Plugin API is usually API-key based instead.
|
|
350
|
-
|
|
351
|
-
## Error Handling
|
|
352
|
-
|
|
353
|
-
- Network/API errors in `getPresignedUrl`, `getThumbnails`, `getProjectFiles` throw with a friendly message when possible.
|
|
354
|
-
- In `<Uploader />`, per-file errors are surfaced via item `error` and `status: 'error'`, and the component continues uploading other files.
|
|
355
|
-
- `uploadToS3` returns a Response; check `res.ok`. The convenience `upload()` will throw if the PUT fails.
|
|
356
|
-
|
|
357
|
-
## Troubleshooting
|
|
358
|
-
|
|
359
|
-
- __`Failed to get upload URL`__
|
|
360
|
-
- Check your presign route is reachable (correct `baseUrl`/`presignUrl`).
|
|
361
|
-
- Ensure `fileSize` is provided and > 0.
|
|
362
|
-
- Verify API key header and value; confirm CORS on the server.
|
|
363
|
-
- __S3 PUT 403/SignatureDoesNotMatch__
|
|
364
|
-
- Do not modify headers other than `Content-Type`.
|
|
365
|
-
- Ensure the file name/type/size used for presign match the actual uploaded file.
|
|
366
|
-
- __CORS errors__
|
|
367
|
-
- Allow your plugin origin on the Upfiles app for Plugin API paths and S3 bucket CORS for PUT/GET.
|
|
368
|
-
- __Large files stall at 99%__
|
|
369
|
-
- Expected: progress caps at 99% until PUT resolves, then jumps to 100%.
|
|
370
|
-
- __No files listed in ProjectFilesWidget__
|
|
371
|
-
- Confirm the API key belongs to a project with files.
|
|
372
|
-
- Ensure `thumbnailsPath` is correct so `/files` is derived properly.
|
|
373
|
-
|
|
374
|
-
## FAQ
|
|
375
|
-
|
|
376
|
-
- __Can I use it without React?__ Yes—use `UpfilesClient` directly (see vanilla example).
|
|
377
|
-
- __How do I restrict uploads to a folder?__ Provide `folderPath` when presigning (`<Uploader folderPath="my-plugin/" />` or `client.upload(..., { folderPath })`).
|
|
378
|
-
- __How do I associate uploads with a project?__ Provide `projectId` when presigning or via `client.upload(..., { projectId })`.
|
|
379
|
-
- __Can I customize headers?__ Pass `headers` in `UpfilesClientOptions`.
|
|
380
|
-
|
|
381
|
-
## Example: Minimal cross-origin plugin
|
|
106
|
+
## Integration
|
|
382
107
|
|
|
383
|
-
|
|
384
|
-
import { Uploader } from '@thetechfossil/upfiles';
|
|
108
|
+
The package can be integrated into existing applications by:
|
|
385
109
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
clientOptions={{
|
|
390
|
-
baseUrl: 'https://upfiles.example.com',
|
|
391
|
-
apiKey: process.env.NEXT_PUBLIC_UPFILES_API_KEY!,
|
|
392
|
-
apiKeyHeader: 'authorization',
|
|
393
|
-
}}
|
|
394
|
-
multiple
|
|
395
|
-
accept={['image/*']}
|
|
396
|
-
maxFileSize={20 * 1024 * 1024}
|
|
397
|
-
folderPath="my-plugin/"
|
|
398
|
-
fetchThumbnails
|
|
399
|
-
onComplete={(files) => console.log('Uploaded', files)}
|
|
400
|
-
onError={(e) => console.error(e)}
|
|
401
|
-
/>
|
|
402
|
-
);
|
|
403
|
-
}
|
|
404
|
-
```
|
|
110
|
+
1. Using the dialog component for user-facing interfaces
|
|
111
|
+
2. Calling the reusable functions for programmatic operations
|
|
112
|
+
3. Implementing custom UI components that use the same underlying logic
|
|
405
113
|
|
|
406
|
-
##
|
|
114
|
+
## Security Notes
|
|
407
115
|
|
|
408
|
-
-
|
|
409
|
-
-
|
|
410
|
-
-
|
|
116
|
+
- API keys are only returned once during creation (plaintext version)
|
|
117
|
+
- All operations are authenticated and scoped to the current user
|
|
118
|
+
- Revoked keys are marked as inactive but remain in the database
|
|
411
119
|
|
|
412
120
|
## License
|
|
413
121
|
|
|
414
|
-
MIT
|
|
122
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thetechfossil/upfiles",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Lightweight client and React components for Upfiles Plugin API (presigned S3)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "UpFiles",
|
|
@@ -28,7 +28,10 @@
|
|
|
28
28
|
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
29
29
|
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
30
30
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
31
|
-
"prepublishOnly": "bun run build"
|
|
31
|
+
"prepublishOnly": "bun run build",
|
|
32
|
+
"todo:list": "node scripts/todo-manager.js list",
|
|
33
|
+
"todo:complete": "node scripts/todo-manager.js complete",
|
|
34
|
+
"todo:add": "node scripts/todo-manager.js add"
|
|
32
35
|
},
|
|
33
36
|
"peerDependencies": {
|
|
34
37
|
"react": ">=18"
|