mirror of
https://github.com/transloadit/uppy.git
synced 2026-07-17 16:50:22 +00:00
Merge 5.0 (#5916)
This commit is contained in:
commit
a054062b4f
483 changed files with 3029 additions and 14582 deletions
48
.changeset/huge-dingos-march.md
Normal file
48
.changeset/huge-dingos-march.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
"@uppy/dashboard": major
|
||||
---
|
||||
|
||||
### Merge @uppy/status-bar into @uppy/dashboard
|
||||
|
||||
The `@uppy/status-bar` package has been merged into `@uppy/dashboard`. The plugin gave a false promise of flexibility as a standalone plugin but was always built tightly coupled for `@uppy/dashboard`. With the new headless components and hooks, we want go all in those components and remove the confusing, inflexible ones.
|
||||
|
||||
StatusBar is now rendered as an integrated component within Dashboard rather than as a separate plugin. The standalone `@uppy/status-bar` package is no longer maintained and should be removed from your dependencies.
|
||||
|
||||
#### Migration from standalone StatusBar to Dashboard
|
||||
|
||||
If you were using StatusBar as a separate plugin, you'll need to migrate to using Dashboard with the equivalent options.
|
||||
|
||||
**Before:**
|
||||
|
||||
```javascript
|
||||
import StatusBar from '@uppy/status-bar'
|
||||
|
||||
uppy.use(StatusBar, {
|
||||
target: '#status-bar',
|
||||
showProgressDetails: true,
|
||||
hideUploadButton: false,
|
||||
hideAfterFinish: true
|
||||
})
|
||||
```
|
||||
|
||||
**Now:**
|
||||
|
||||
```javascript
|
||||
import Dashboard from '@uppy/dashboard'
|
||||
|
||||
uppy.use(Dashboard, {
|
||||
target: '#dashboard',
|
||||
hideProgressDetails: false,
|
||||
hideUploadButton: false,
|
||||
hideAfterFinish: true
|
||||
})
|
||||
```
|
||||
|
||||
All StatusBar configuration options are now available directly as Dashboard options:
|
||||
- `hideProgressDetails` - Hide detailed progress information (previously `showProgressDetails` with inverted logic)
|
||||
- `hideUploadButton` - Hide the upload button
|
||||
- `hideAfterFinish` - Hide status bar after upload completion
|
||||
- `hideRetryButton` - Hide the retry button
|
||||
- `hidePauseResumeButton` - Hide pause/resume controls
|
||||
- `hideCancelButton` - Hide the cancel button
|
||||
- `doneButtonHandler` - Custom handler for the done button
|
||||
70
.changeset/legal-yaks-decide.md
Normal file
70
.changeset/legal-yaks-decide.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
"@uppy/utils": major
|
||||
"@uppy/angular": patch
|
||||
"@uppy/google-photos-picker": patch
|
||||
"example-companion-custom-provider": patch
|
||||
"@uppy/google-drive-picker": patch
|
||||
"@uppy/thumbnail-generator": patch
|
||||
"@uppy/companion-client": patch
|
||||
"@uppy/golden-retriever": patch
|
||||
"@uppy/provider-views": patch
|
||||
"@uppy/remote-sources": patch
|
||||
"@uppy/screen-capture": patch
|
||||
"@uppy/store-default": patch
|
||||
"@uppy/google-drive": patch
|
||||
"@uppy/image-editor": patch
|
||||
"@uppy/react-native": patch
|
||||
"@uppy/drop-target": patch
|
||||
"@uppy/transloadit": patch
|
||||
"@uppy/components": patch
|
||||
"@uppy/compressor": patch
|
||||
"@uppy/xhr-upload": patch
|
||||
"@uppy/companion": patch
|
||||
"@uppy/dashboard": patch
|
||||
"@uppy/instagram": patch
|
||||
"@uppy/facebook": patch
|
||||
"@uppy/onedrive": patch
|
||||
"@uppy/unsplash": patch
|
||||
"angular": patch
|
||||
"@uppy/dropbox": patch
|
||||
"@uppy/locales": patch
|
||||
"@uppy/aws-s3": patch
|
||||
"@uppy/svelte": patch
|
||||
"@uppy/webcam": patch
|
||||
"@uppy/webdav": patch
|
||||
"example-transloadit": patch
|
||||
"@uppy/audio": patch
|
||||
"@uppy/react": patch
|
||||
"example-xhr-bundle": patch
|
||||
"@uppy/core": patch
|
||||
"@uppy/form": patch
|
||||
"@uppy/zoom": patch
|
||||
"example-sveltekit": patch
|
||||
"@uppy/box": patch
|
||||
"@uppy/tus": patch
|
||||
"@uppy/url": patch
|
||||
"@uppy/vue": patch
|
||||
"example-angular": patch
|
||||
"uppy": patch
|
||||
"example-vue": patch
|
||||
"@uppy-dev/dev": patch
|
||||
---
|
||||
|
||||
Updated export maps for @uppy/utils: removed nested subpath exports; all utilities are now exported from the root index.js.
|
||||
|
||||
|
||||
**Before :**
|
||||
|
||||
```typescript
|
||||
|
||||
import getFileTypeExtension from '@uppy/utils/lib/getFileTypeExtension'
|
||||
|
||||
```
|
||||
|
||||
**After :**
|
||||
|
||||
```typescript
|
||||
|
||||
import { getFileTypeExtension } from '@uppy/utils'
|
||||
|
||||
```
|
||||
70
.changeset/light-hounds-vanish.md
Normal file
70
.changeset/light-hounds-vanish.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
"@uppy/google-photos-picker": major
|
||||
"@uppy/google-drive-picker": major
|
||||
"@uppy/thumbnail-generator": major
|
||||
"@uppy/companion-client": major
|
||||
"@uppy/golden-retriever": major
|
||||
"@uppy/provider-views": major
|
||||
"@uppy/remote-sources": major
|
||||
"@uppy/screen-capture": major
|
||||
"@uppy/store-default": major
|
||||
"@uppy/google-drive": major
|
||||
"@uppy/image-editor": major
|
||||
"@uppy/react-native": major
|
||||
"@uppy/drop-target": major
|
||||
"@uppy/transloadit": major
|
||||
"@uppy/components": major
|
||||
"@uppy/compressor": major
|
||||
"@uppy/status-bar": major
|
||||
"@uppy/xhr-upload": major
|
||||
"@uppy/companion": major
|
||||
"@uppy/dashboard": major
|
||||
"@uppy/instagram": major
|
||||
"@uppy/facebook": major
|
||||
"@uppy/onedrive": major
|
||||
"@uppy/unsplash": major
|
||||
"@uppy/dropbox": major
|
||||
"@uppy/locales": major
|
||||
"@uppy/aws-s3": major
|
||||
"@uppy/svelte": major
|
||||
"@uppy/webcam": major
|
||||
"@uppy/audio": major
|
||||
"@uppy/react": major
|
||||
"@uppy/utils": major
|
||||
"@uppy/core": major
|
||||
"@uppy/form": major
|
||||
"@uppy/zoom": major
|
||||
"@uppy/box": major
|
||||
"@uppy/tus": major
|
||||
"@uppy/url": major
|
||||
"@uppy/vue": major
|
||||
"uppy": major
|
||||
---
|
||||
|
||||
### Export maps for all packages
|
||||
|
||||
All packages now have export maps. This is a breaking change in two cases:
|
||||
|
||||
1. The css imports have changed from `@uppy[package]/dist/styles.min.css` to `@uppy[package]/css/styles.min.css`
|
||||
2. You were importing something that wasn't exported from the root, for instance `@uppy/core/lib/foo.js`. You can now only import things we explicitly exported.
|
||||
|
||||
#### Changed imports for `@uppy/react`, `@uppy/vue`, and `@uppy/svelte`
|
||||
|
||||
Some components, like Dashboard, require a peer dependency to work but since all components were exported from a single file you were forced to install all peer dependencies. Even if you never imported, for instance, the status bar component.
|
||||
|
||||
Every component that requires a peer dependency has now been moved to a subpath, such as `@uppy/react/dashboard`, so you only need to install the peer dependencies you need.
|
||||
|
||||
**Example for `@uppy/react`:**
|
||||
|
||||
**Before:**
|
||||
|
||||
```javascript
|
||||
import { Dashboard, StatusBar } from "@uppy/react";
|
||||
```
|
||||
|
||||
**Now:**
|
||||
|
||||
```javascript
|
||||
import Dashboard from "@uppy/react/dashboard";
|
||||
import StatusBar from "@uppy/react/status-bar";
|
||||
```
|
||||
5
.changeset/mean-eels-scream.md
Normal file
5
.changeset/mean-eels-scream.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@uppy/companion": major
|
||||
---
|
||||
|
||||
Make Companion ESM-only. As of Node.js 20.19.0, you can require(esm) if you haven't transitioned yet.
|
||||
178
.github/MIGRATION.md
vendored
Normal file
178
.github/MIGRATION.md
vendored
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
# Migration
|
||||
|
||||
This is a temporary file that can be updated with any pending migration changes, before deleting them here and moving them to uppy.io. If we in the future decide to move uppy.io into this repo, then this file will not be needed anymore. See also https://github.com/transloadit/uppy/pull/5802
|
||||
|
||||
## Uppy 5.0
|
||||
|
||||
### Companion 5.x to 6.x
|
||||
|
||||
- Option `companionAllowedHosts` no longer wrapped in Regex start/end characters
|
||||
(`^` and `$`). You now need to provide these yourself if you want an exact
|
||||
match.
|
||||
- Backwards compat token decryption removed: old Uppy auth tokens (created
|
||||
before
|
||||
[uppy%404.16.0](https://github.com/transloadit/uppy/releases/tag/uppy%404.16.0)
|
||||
06d9a7c689e5123d41b38191074eb8bbd4ff5325) will become invalid and users who
|
||||
have these old toknes will have to re-authenticate.
|
||||
- Removed `token` param from `Provider` class methods: `list()`, `download()`,
|
||||
`logout()`, `thumbnail()`. Please use: `providerUserSession`.`accessToken`
|
||||
instead.
|
||||
|
||||
|
||||
### @uppy/informer merged into @uppy/dashboard
|
||||
|
||||
The `@uppy/informer` plugin has been merged into `@uppy/dashboard` to reduce bundle size and improve maintainability. The `@uppy/informer` package is no longer maintained as a standalone package and should be removed from your dependencies.
|
||||
|
||||
### @uppy/progress-bar removed
|
||||
|
||||
The `@uppy/progress-bar` plugin has been removed as it provided minimal functionality that can be easily replicated with Uppy's built-in state management.
|
||||
|
||||
**Before:**
|
||||
```js
|
||||
import ProgressBar from '@uppy/progress-bar'
|
||||
|
||||
uppy.use(ProgressBar, { target: '#progress' })
|
||||
```
|
||||
|
||||
**After:**
|
||||
```js
|
||||
// Custom progress bar using Uppy state
|
||||
uppy.on('upload-progress', (file, progress) => {
|
||||
const progressElement = document.getElementById('progress')
|
||||
progressElement.style.width = `${progress.percentage}%`
|
||||
progressElement.textContent = `${progress.percentage}%`
|
||||
})
|
||||
|
||||
// Or listen to total progress
|
||||
uppy.on('progress', (progress) => {
|
||||
const progressElement = document.getElementById('progress')
|
||||
progressElement.style.width = `${progress}%`
|
||||
progressElement.textContent = `${progress}%`
|
||||
})
|
||||
```
|
||||
|
||||
**Migration steps:**
|
||||
1. Remove `@uppy/progress-bar` from your dependencies
|
||||
2. Create a custom progress indicator using Uppy's `progress` or `upload-progress` events.
|
||||
3. Style your progress bar according to your design system.
|
||||
|
||||
### @uppy/drag-drop and @uppy/file-input removed
|
||||
|
||||
The `@uppy/drag-drop` and `@uppy/file-input` plugins have been removed in favor of more flexible, headless hooks. These hooks provide the same functionality but with maximum customization freedom.
|
||||
|
||||
**Before:**
|
||||
```js
|
||||
import DragDrop from '@uppy/drag-drop'
|
||||
import FileInput from '@uppy/file-input'
|
||||
|
||||
uppy
|
||||
.use(DragDrop, { target: '#drag-drop' })
|
||||
.use(FileInput, { target: '#file-input' })
|
||||
```
|
||||
|
||||
**After:**
|
||||
```js
|
||||
// React example
|
||||
import { useDropzone, useFileInput } from '@uppy/react'
|
||||
|
||||
function MyUploader() {
|
||||
const { getRootProps, getInputProps, isDragging } = useDropzone()
|
||||
const { getButtonProps, getInputProps: getFileInputProps } = useFileInput()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input {...getInputProps()} className="hidden" />
|
||||
<div {...getRootProps()} className={`dropzone ${isDragging ? 'dragging' : ''}`}>
|
||||
<input {...getFileInputProps()} className="hidden" />
|
||||
<button {...getButtonProps()}>Choose files</button>
|
||||
<p>or drag and drop files here</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**Alternative: Use Dashboard**
|
||||
```js
|
||||
// If you want a complete UI solution, use Dashboard instead
|
||||
import Dashboard from '@uppy/dashboard'
|
||||
|
||||
uppy.use(Dashboard, {
|
||||
target: '#uppy-dashboard',
|
||||
inline: true,
|
||||
})
|
||||
```
|
||||
|
||||
**Migration steps:**
|
||||
1. Remove `@uppy/drag-drop` and `@uppy/file-input` from your dependencies
|
||||
2. Choose one of these approaches:
|
||||
- Use the framework-specific hooks (`@uppy/react`, `@uppy/vue`, `@uppy/svelte`) for maximum flexibility
|
||||
- Use `@uppy/dashboard` for a complete, ready-to-use UI solution
|
||||
3. Replace your existing components with custom implementations using the hooks or Dashboard
|
||||
4. See [examples/](../examples/) for complete implementation examples
|
||||
|
||||
### Export maps for all packages
|
||||
|
||||
All packages now have export maps. This is a breaking change in two cases:
|
||||
|
||||
1. The css imports have changed from `@uppy[package]/dist/styles.min.css` to `@uppy[package]/css/styles.min.css`
|
||||
2. You were importing something that wasn't exported from the root, for instance `@uppy/core/lib/foo.js`. You can now only import things we explicitly exported.
|
||||
|
||||
#### Changed imports for `@uppy/react`, `@uppy/vue`, and `@uppy/svelte`
|
||||
|
||||
Some components, like Dashboard, require a peer dependency to work but since all components were exported from a single file you were forced to install all peer dependencies. Even if you never imported, for instance, the status bar component.
|
||||
|
||||
Every component that requires a peer dependency has now been moved to a subpath, such as `@uppy/react/dashboard`, so you only need to install the peer dependencies you need.
|
||||
|
||||
**Example for `@uppy/react`:**
|
||||
|
||||
**Before:**
|
||||
```javascript
|
||||
import { Dashboard, StatusBar } from '@uppy/react'
|
||||
```
|
||||
|
||||
**Now:**
|
||||
```javascript
|
||||
import Dashboard from '@uppy/react/dashboard'
|
||||
import StatusBar from '@uppy/react/status-bar'
|
||||
```
|
||||
|
||||
|
||||
### @uppy/status-bar merged into @uppy/dashboard
|
||||
|
||||
The `@uppy/status-bar` package has been merged into `@uppy/dashboard`. The plugin gave a false promise of flexibility as a standalone plugin but was always built tightly coupled for `@uppy/dashboard`. With the new headless components and hooks, we want go all in those components and remove the confusing, inflexible ones.
|
||||
|
||||
**Migration steps:**
|
||||
|
||||
1. Remove `@uppy/status-bar` from your dependencies
|
||||
2. Replace StatusBar usage with Dashboard
|
||||
3. Move all StatusBar options directly to Dashboard options
|
||||
|
||||
All StatusBar configuration options are now available as Dashboard options:
|
||||
- `hideProgressDetails` - Hide detailed progress information
|
||||
- `hideUploadButton` - Hide the upload button
|
||||
- `hideAfterFinish` - Hide status bar after upload completion
|
||||
- `hideRetryButton` - Hide the retry button
|
||||
- `hidePauseResumeButton` - Hide pause/resume controls
|
||||
- `hideCancelButton` - Hide the cancel button
|
||||
- `doneButtonHandler` - Custom handler for the done button
|
||||
|
||||
```js
|
||||
// Before - separate StatusBar plugin
|
||||
import StatusBar from '@uppy/status-bar'
|
||||
uppy.use(StatusBar, {
|
||||
target: '#status-bar',
|
||||
hideProgressDetails: true,
|
||||
hideUploadButton: false,
|
||||
hideAfterFinish: true
|
||||
})
|
||||
|
||||
// After - use Dashboard with StatusBar options
|
||||
import Dashboard from '@uppy/dashboard'
|
||||
uppy.use(Dashboard, {
|
||||
target: '#dashboard',
|
||||
hideProgressDetails: false,
|
||||
hideUploadButton: false,
|
||||
hideAfterFinish: true
|
||||
})
|
||||
```
|
||||
|
|
@ -20,10 +20,7 @@
|
|||
"@uppy/angular": "workspace:*",
|
||||
"@uppy/core": "workspace:*",
|
||||
"@uppy/dashboard": "workspace:*",
|
||||
"@uppy/drag-drop": "workspace:*",
|
||||
"@uppy/google-drive": "workspace:*",
|
||||
"@uppy/progress-bar": "workspace:*",
|
||||
"@uppy/status-bar": "workspace:*",
|
||||
"@uppy/tus": "workspace:*",
|
||||
"@uppy/utils": "workspace:*",
|
||||
"@uppy/webcam": "workspace:*",
|
||||
|
|
|
|||
|
|
@ -36,9 +36,6 @@ import Webcam from '@uppy/webcam'
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<h2>Drag Drop Area</h2>
|
||||
<uppy-drag-drop [uppy]="uppy" [props]="{}"></uppy-drag-drop>
|
||||
|
||||
<h2>Progress Bar</h2>
|
||||
<uppy-progress-bar
|
||||
[uppy]="uppy"
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ import { BrowserModule } from '@angular/platform-browser'
|
|||
import {
|
||||
UppyAngularDashboardModalModule,
|
||||
UppyAngularDashboardModule,
|
||||
UppyAngularDragDropModule,
|
||||
UppyAngularProgressBarModule,
|
||||
UppyAngularStatusBarModule,
|
||||
} from '@uppy/angular'
|
||||
import { AppComponent } from './app.component'
|
||||
|
|
@ -17,8 +15,6 @@ import { AppComponent } from './app.component'
|
|||
UppyAngularDashboardModule,
|
||||
UppyAngularStatusBarModule,
|
||||
UppyAngularDashboardModalModule,
|
||||
UppyAngularDragDropModule,
|
||||
UppyAngularProgressBarModule,
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
/* You can add global styles to this file, and also import other style files */
|
||||
@import "@uppy/core/dist/style.css";
|
||||
@import "@uppy/dashboard/dist/style.css";
|
||||
@import "@uppy/drag-drop/dist/style.css";
|
||||
@import "@uppy/progress-bar/dist/style.css";
|
||||
|
|
|
|||
|
|
@ -31,14 +31,13 @@ function adaptData(res) {
|
|||
/**
|
||||
* an example of a custom provider module. It implements @uppy/companion's Provider interface
|
||||
*/
|
||||
class MyCustomProvider {
|
||||
export default class MyCustomProvider {
|
||||
static version = 2
|
||||
|
||||
static get oauthProvider() {
|
||||
return 'myunsplash'
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
async list({ token, directory }) {
|
||||
const path = directory ? `/${directory}/photos` : ''
|
||||
|
||||
|
|
@ -55,7 +54,6 @@ class MyCustomProvider {
|
|||
return adaptData(await resp.json())
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
async download({ id, token }) {
|
||||
const resp = await fetch(`${BASE_URL}/photos/${id}`, {
|
||||
headers: {
|
||||
|
|
@ -78,5 +76,3 @@ class MyCustomProvider {
|
|||
return { stream: Readable.fromWeb(resp.body), size }
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MyCustomProvider
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"rules": {
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"no-use-before-define": "off"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
|
||||
"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
|
||||
}
|
||||
14
examples/react-native-expo/.gitignore
vendored
14
examples/react-native-expo/.gitignore
vendored
|
|
@ -1,14 +0,0 @@
|
|||
node_modules/
|
||||
.expo/
|
||||
dist/
|
||||
npm-debug.*
|
||||
*.jks
|
||||
*.p8
|
||||
*.p12
|
||||
*.key
|
||||
*.mobileprovision
|
||||
*.orig.*
|
||||
web-build/
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
168
examples/react-native-expo/App.js
vendored
168
examples/react-native-expo/App.js
vendored
|
|
@ -1,168 +0,0 @@
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
import Uppy from '@uppy/core'
|
||||
import FilePicker from '@uppy/react-native'
|
||||
import Tus from '@uppy/tus'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { Image, StyleSheet, Text, View } from 'react-native'
|
||||
import FileList from './FileList'
|
||||
import PauseResumeButton from './PauseResumeButton'
|
||||
import ProgressBar from './ProgressBar'
|
||||
import SelectFiles from './SelectFilesButton'
|
||||
import getTusFileReader from './tusFileReader'
|
||||
|
||||
export default function App() {
|
||||
const [state, _setState] = useState({
|
||||
progress: 0,
|
||||
total: 0,
|
||||
file: null,
|
||||
uploadURL: null,
|
||||
isFilePickerVisible: false,
|
||||
isPaused: false,
|
||||
uploadStarted: false,
|
||||
uploadComplete: false,
|
||||
info: null,
|
||||
totalProgress: 0,
|
||||
})
|
||||
|
||||
const setState = useCallback(
|
||||
(newState) => _setState((oldState) => ({ ...oldState, ...newState })),
|
||||
[],
|
||||
)
|
||||
|
||||
const [uppy] = useState(() =>
|
||||
new Uppy({ autoProceed: true, debug: true }).use(Tus, {
|
||||
endpoint: 'https://tusd.tusdemo.net/files/',
|
||||
urlStorage: AsyncStorage,
|
||||
fileReader: getTusFileReader,
|
||||
chunkSize: 10 * 1024 * 1024, // keep the chunk size small to avoid memory exhaustion
|
||||
}),
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
uppy.on('upload-progress', (file, progress) => {
|
||||
setState({
|
||||
progress: progress.bytesUploaded,
|
||||
total: progress.bytesTotal,
|
||||
totalProgress: uppy.state.totalProgress,
|
||||
uploadStarted: true,
|
||||
})
|
||||
})
|
||||
uppy.on('upload-success', () => {
|
||||
// console.log(file.name, response)
|
||||
})
|
||||
uppy.on('complete', (result) => {
|
||||
setState({
|
||||
status: result.successful[0]
|
||||
? 'Upload complete ✅'
|
||||
: 'Upload errored ❌',
|
||||
uploadURL: result.successful[0] ? result.successful[0].uploadURL : null,
|
||||
uploadComplete: true,
|
||||
uploadStarted: false,
|
||||
})
|
||||
console.log('Upload complete:', result)
|
||||
})
|
||||
uppy.on('info-visible', () => {
|
||||
const { info } = uppy.getState()
|
||||
setState({
|
||||
info,
|
||||
})
|
||||
console.log('uppy-info:', info)
|
||||
})
|
||||
uppy.on('info-hidden', () => {
|
||||
setState({
|
||||
info: null,
|
||||
})
|
||||
})
|
||||
}, [setState, uppy])
|
||||
|
||||
const showFilePicker = () => {
|
||||
setState({
|
||||
isFilePickerVisible: true,
|
||||
uploadStarted: false,
|
||||
uploadComplete: false,
|
||||
})
|
||||
}
|
||||
|
||||
const hideFilePicker = () => {
|
||||
setState({
|
||||
isFilePickerVisible: false,
|
||||
})
|
||||
}
|
||||
|
||||
const togglePauseResume = () => {
|
||||
if (state.isPaused) {
|
||||
uppy.resumeAll()
|
||||
setState({
|
||||
isPaused: false,
|
||||
})
|
||||
} else {
|
||||
uppy.pauseAll()
|
||||
setState({
|
||||
isPaused: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.root}>
|
||||
<Text style={styles.title}>Uppy in React Native</Text>
|
||||
<View style={{ alignItems: 'center' }}>
|
||||
<Image style={styles.logo} source={require('./assets/uppy-logo.png')} />
|
||||
</View>
|
||||
<SelectFiles showFilePicker={showFilePicker} />
|
||||
|
||||
{state.info
|
||||
? <Text
|
||||
style={{
|
||||
marginBottom: 10,
|
||||
marginTop: 10,
|
||||
color: '#b8006b',
|
||||
}}
|
||||
>
|
||||
{state.info.message}
|
||||
</Text>
|
||||
: null}
|
||||
|
||||
<ProgressBar progress={state.totalProgress} />
|
||||
|
||||
<PauseResumeButton
|
||||
isPaused={state.isPaused}
|
||||
onPress={togglePauseResume}
|
||||
uploadStarted={state.uploadStarted}
|
||||
uploadComplete={state.uploadComplete}
|
||||
/>
|
||||
|
||||
{uppy && (
|
||||
<FilePicker
|
||||
uppy={uppy}
|
||||
show={state.isFilePickerVisible}
|
||||
onRequestClose={hideFilePicker}
|
||||
companionUrl="http://localhost:3020"
|
||||
/>
|
||||
)}
|
||||
|
||||
{uppy && <FileList uppy={uppy} />}
|
||||
|
||||
{state.status && <Text>Status: {state.status}</Text>}
|
||||
<Text>
|
||||
{state.progress} of {state.total}
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
paddingTop: 100,
|
||||
paddingBottom: 20,
|
||||
paddingLeft: 50,
|
||||
paddingRight: 50,
|
||||
flex: 1,
|
||||
},
|
||||
title: {
|
||||
fontSize: 25,
|
||||
marginBottom: 20,
|
||||
textAlign: 'center',
|
||||
},
|
||||
logo: { width: 80, height: 78, marginBottom: 50 },
|
||||
})
|
||||
121
examples/react-native-expo/FileList.js
vendored
121
examples/react-native-expo/FileList.js
vendored
|
|
@ -1,121 +0,0 @@
|
|||
import getFileTypeIcon from '@uppy/dashboard/lib/utils/getFileTypeIcon.js'
|
||||
import renderStringFromJSX from 'preact-render-to-string'
|
||||
import { FlatList, Image, StyleSheet, Text, View } from 'react-native'
|
||||
|
||||
const fileIcon = require('./assets/file-icon.png')
|
||||
|
||||
const truncateString = (str) => {
|
||||
const maxChars = 20
|
||||
if (str.length > maxChars) {
|
||||
return `${str.substring(0, 25)}...`
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
function FileIcon() {
|
||||
return (
|
||||
<View style={styles.itemIconContainer}>
|
||||
<Image style={styles.itemIcon} source={fileIcon} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
function UppyDashboardFileIcon({ type }) {
|
||||
const icon = renderStringFromJSX(getFileTypeIcon(type).icon)
|
||||
if (!icon) {
|
||||
return <FileIcon />
|
||||
}
|
||||
const { color } = getFileTypeIcon(type)
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
...styles.itemIconContainer,
|
||||
backgroundColor: color,
|
||||
}}
|
||||
>
|
||||
<Text style={styles.itemType}>logo</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default function FileList({ uppy }) {
|
||||
const uppyFiles = uppy.store.state.files
|
||||
const uppyFilesArray = Object.keys(uppyFiles).map((id) => uppyFiles[id])
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<FlatList
|
||||
data={uppyFilesArray}
|
||||
keyExtractor={(item) => item.id}
|
||||
numColumns={2}
|
||||
renderItem={({ item }) => {
|
||||
return (
|
||||
<View style={styles.item}>
|
||||
{item.type === 'image'
|
||||
? <Image
|
||||
style={styles.itemImage}
|
||||
source={{ uri: item.data.uri }}
|
||||
/>
|
||||
: <UppyDashboardFileIcon type={item.type} />}
|
||||
<Text style={styles.itemName}>
|
||||
{truncateString(item.name, 20)}
|
||||
</Text>
|
||||
<Text style={styles.itemType}>{item.type}</Text>
|
||||
</View>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginTop: 20,
|
||||
marginBottom: 20,
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginRight: -25,
|
||||
},
|
||||
item: {
|
||||
width: 100,
|
||||
marginTop: 5,
|
||||
marginBottom: 15,
|
||||
marginRight: 25,
|
||||
},
|
||||
itemImage: {
|
||||
width: 100,
|
||||
height: 100,
|
||||
borderRadius: 5,
|
||||
marginBottom: 5,
|
||||
},
|
||||
itemIconContainer: {
|
||||
width: 100,
|
||||
height: 100,
|
||||
borderRadius: 5,
|
||||
marginBottom: 5,
|
||||
backgroundColor: '#cfd3d6',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
itemIcon: {
|
||||
width: 42,
|
||||
height: 56,
|
||||
},
|
||||
itemIconSVG: {
|
||||
width: 50,
|
||||
height: 50,
|
||||
},
|
||||
itemName: {
|
||||
fontSize: 13,
|
||||
color: '#2c3e50',
|
||||
fontWeight: '600',
|
||||
},
|
||||
itemType: {
|
||||
fontWeight: '600',
|
||||
fontSize: 12,
|
||||
color: '#95a5a6',
|
||||
},
|
||||
})
|
||||
30
examples/react-native-expo/PauseResumeButton.js
vendored
30
examples/react-native-expo/PauseResumeButton.js
vendored
|
|
@ -1,30 +0,0 @@
|
|||
import { StyleSheet, Text, TouchableHighlight } from 'react-native'
|
||||
|
||||
export default function PauseResumeButton({
|
||||
uploadStarted,
|
||||
uploadComplete,
|
||||
isPaused,
|
||||
onPress,
|
||||
}) {
|
||||
if (!uploadStarted || uploadComplete) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableHighlight onPress={onPress} style={styles.button}>
|
||||
<Text style={styles.text}>{isPaused ? 'Resume' : 'Pause'}</Text>
|
||||
</TouchableHighlight>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
backgroundColor: '#cc0077',
|
||||
padding: 10,
|
||||
},
|
||||
text: {
|
||||
color: '#fff',
|
||||
textAlign: 'center',
|
||||
fontSize: 17,
|
||||
},
|
||||
})
|
||||
38
examples/react-native-expo/ProgressBar.js
vendored
38
examples/react-native-expo/ProgressBar.js
vendored
|
|
@ -1,38 +0,0 @@
|
|||
import { StyleSheet, Text, View } from 'react-native'
|
||||
|
||||
const colorGreen = '#0b8600'
|
||||
const colorBlue = '#006bb7'
|
||||
|
||||
export default function ProgressBar({ progress }) {
|
||||
return (
|
||||
<View style={styles.root}>
|
||||
<View style={styles.wrapper}>
|
||||
<View
|
||||
style={[
|
||||
styles.bar,
|
||||
{
|
||||
backgroundColor: progress === 100 ? colorGreen : colorBlue,
|
||||
width: `${progress}%`,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
<Text>{progress ? `${progress}%` : null}</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
marginTop: 15,
|
||||
marginBottom: 15,
|
||||
},
|
||||
wrapper: {
|
||||
height: 5,
|
||||
overflow: 'hidden',
|
||||
backgroundColor: '#dee1e3',
|
||||
},
|
||||
bar: {
|
||||
height: 5,
|
||||
},
|
||||
})
|
||||
21
examples/react-native-expo/SelectFilesButton.js
vendored
21
examples/react-native-expo/SelectFilesButton.js
vendored
|
|
@ -1,21 +0,0 @@
|
|||
import { StyleSheet, Text, TouchableHighlight } from 'react-native'
|
||||
|
||||
export default function SelectFiles({ showFilePicker }) {
|
||||
return (
|
||||
<TouchableHighlight onPress={showFilePicker} style={styles.button}>
|
||||
<Text style={styles.text}>Select files</Text>
|
||||
</TouchableHighlight>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
backgroundColor: '#cc0077',
|
||||
padding: 15,
|
||||
},
|
||||
text: {
|
||||
color: '#fff',
|
||||
textAlign: 'center',
|
||||
fontSize: 17,
|
||||
},
|
||||
})
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"expo": {
|
||||
"name": "react-native-expo",
|
||||
"slug": "react-native-expo",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/icon.png",
|
||||
"splash": {
|
||||
"image": "./assets/splash.png",
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"updates": {
|
||||
"fallbackToCacheTimeout": 0
|
||||
},
|
||||
"assetBundlePatterns": ["**/*"],
|
||||
"ios": {
|
||||
"supportsTablet": true
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/adaptive-icon.png",
|
||||
"backgroundColor": "#FFFFFF"
|
||||
}
|
||||
},
|
||||
"web": {
|
||||
"favicon": "./assets/favicon.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.4 KiB |
|
|
@ -1,6 +0,0 @@
|
|||
module.exports = (api) => {
|
||||
api.cache(true)
|
||||
return {
|
||||
presets: ['babel-preset-expo'],
|
||||
}
|
||||
}
|
||||
8
examples/react-native-expo/index.js
vendored
8
examples/react-native-expo/index.js
vendored
|
|
@ -1,8 +0,0 @@
|
|||
import { registerRootComponent } from 'expo'
|
||||
|
||||
import App from './App'
|
||||
|
||||
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
|
||||
// It also ensures that whether you load the app in Expo Go or in a native build,
|
||||
// the environment is set up appropriately
|
||||
registerRootComponent(App)
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
// Learn more https://docs.expo.dev/guides/monorepos
|
||||
const { getDefaultConfig } = require('expo/metro-config')
|
||||
const path = require('node:path')
|
||||
|
||||
// Find the project and workspace directories
|
||||
const projectRoot = __dirname
|
||||
// This can be replaced with `find-yarn-workspace-root`
|
||||
const workspaceRoot = path.resolve(projectRoot, '../../')
|
||||
|
||||
const config = getDefaultConfig(projectRoot)
|
||||
|
||||
// 1. Watch all files within the monorepo
|
||||
config.watchFolders = [workspaceRoot]
|
||||
// 2. Let Metro know where to resolve packages and in what order
|
||||
config.resolver.nodeModulesPaths = [
|
||||
path.resolve(projectRoot, 'node_modules'),
|
||||
path.resolve(workspaceRoot, 'node_modules'),
|
||||
]
|
||||
// 3. Force Metro to resolve (sub)dependencies only from the `nodeModulesPaths`
|
||||
config.resolver.disableHierarchicalLookup = true
|
||||
|
||||
module.exports = config
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
{
|
||||
"name": "example-react-native-expo",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
"android": "expo start --android",
|
||||
"ios": "expo start --ios",
|
||||
"web": "expo start --web",
|
||||
"eject": "expo eject"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native-async-storage/async-storage": "1.23.1",
|
||||
"@uppy/core": "workspace:*",
|
||||
"@uppy/dashboard": "workspace:*",
|
||||
"@uppy/instagram": "workspace:*",
|
||||
"@uppy/react-native": "workspace:*",
|
||||
"@uppy/tus": "workspace:*",
|
||||
"@uppy/url": "workspace:*",
|
||||
"@uppy/xhr-upload": "workspace:*",
|
||||
"base64-js": "^1.3.0",
|
||||
"expo": "~52.0.0",
|
||||
"expo-file-system": "~18.0.12",
|
||||
"expo-status-bar": "~2.0.0",
|
||||
"preact": "^10.5.13",
|
||||
"preact-render-to-string": "^5.1.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-native": "0.76.9",
|
||||
"react-native-web": "~0.19.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.9"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
# Uppy in React Native Expo (Beta)
|
||||
|
||||
⚠️ In Beta
|
||||
|
||||
`@uppy/react-native` is a basic Uppy component for React Native with Expo. It is
|
||||
in Beta, and is not full-featured. You can select local images or videos, take a
|
||||
picture with a camera or add any file from a remote url with Uppy Companion.
|
||||
|
||||
## Run it
|
||||
|
||||
To run this example, make sure you've correctly installed the **repository
|
||||
root**:
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
yarn run build
|
||||
```
|
||||
|
||||
That will also install the dependencies for this example.
|
||||
|
||||
Then, start this example by doing:
|
||||
|
||||
```bash
|
||||
cd examples/react-native-expo
|
||||
yarn start
|
||||
```
|
||||
|
||||
Then you'll see a menu within your terminal where you can chose where to open
|
||||
the app (Android, iOS, device etc.)
|
||||
30
examples/react-native-expo/tusFileReader.js
vendored
30
examples/react-native-expo/tusFileReader.js
vendored
|
|
@ -1,30 +0,0 @@
|
|||
import base64 from 'base64-js'
|
||||
import * as FileSystem from 'expo-file-system'
|
||||
|
||||
export default function getTusFileReader(file, chunkSize, cb) {
|
||||
FileSystem.getInfoAsync(file.uri, { size: true })
|
||||
.then((info) => {
|
||||
cb(null, new TusFileReader(file, info.size))
|
||||
})
|
||||
.catch(cb)
|
||||
}
|
||||
|
||||
class TusFileReader {
|
||||
constructor(file, size) {
|
||||
this.file = file
|
||||
this.size = size
|
||||
}
|
||||
|
||||
slice(start, end, cb) {
|
||||
const options = {
|
||||
encoding: FileSystem.EncodingType.Base64,
|
||||
length: Math.min(end, this.size) - start,
|
||||
position: start,
|
||||
}
|
||||
FileSystem.readAsStringAsync(this.file.uri, options)
|
||||
.then((data) => {
|
||||
cb(null, base64.toByteArray(data))
|
||||
})
|
||||
.catch(cb)
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ import ScreenCapture from './ScreenCapture'
|
|||
import Webcam from './Webcam'
|
||||
|
||||
import './app.css'
|
||||
import '@uppy/react/dist/styles.css'
|
||||
import '@uppy/react/css/style.css'
|
||||
|
||||
function App() {
|
||||
const [uppy] = useState(() =>
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
# Redux
|
||||
|
||||
This example uses Uppy with a Redux store. The same Redux store is also used for
|
||||
other parts of the application, namely the counter example. Each action is
|
||||
logged to the console using
|
||||
[redux-logger](https://github.com/theaqua/redux-logger).
|
||||
|
||||
This example supports the
|
||||
[Redux Devtools extension](https://github.com/zalmoxisus/redux-devtools-extension),
|
||||
including time travel.
|
||||
|
||||
## Run it
|
||||
|
||||
To run this example, make sure you've correctly installed the **repository
|
||||
root**:
|
||||
|
||||
```sh
|
||||
corepack yarn install
|
||||
corepack yarn build
|
||||
```
|
||||
|
||||
That will also install the dependencies for this example.
|
||||
|
||||
Then, again in the **repository root**, start this example by doing:
|
||||
|
||||
```sh
|
||||
corepack yarn workspace @uppy-example/redux start
|
||||
```
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Uppy example: Redux</title>
|
||||
</head>
|
||||
<body>
|
||||
<main id="app">
|
||||
<h1>A counter</h1>
|
||||
<div>
|
||||
<p>
|
||||
Clicked: <span id="value">0</span> times
|
||||
<button id="increment">+</button>
|
||||
<button id="decrement">-</button>
|
||||
<button id="incrementIfOdd">Increment if odd</button>
|
||||
<button id="incrementAsync">Increment async</button>
|
||||
</p>
|
||||
</div>
|
||||
<h1>An Uppy</h1>
|
||||
<div id="uppy"></div>
|
||||
</main>
|
||||
|
||||
<noscript>This app requires JavaScript.</noscript>
|
||||
<script src="./main.js" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
import { configureStore } from '@reduxjs/toolkit'
|
||||
import Uppy from '@uppy/core'
|
||||
import Dashboard from '@uppy/dashboard'
|
||||
import ReduxStore, * as uppyReduxStore from '@uppy/store-redux'
|
||||
import Tus from '@uppy/tus'
|
||||
import { applyMiddleware, combineReducers, compose } from 'redux'
|
||||
import logger from 'redux-logger'
|
||||
|
||||
import '@uppy/core/dist/style.css'
|
||||
import '@uppy/dashboard/dist/style.css'
|
||||
|
||||
function counter(state = 0, action) {
|
||||
switch (action.type) {
|
||||
case 'INCREMENT':
|
||||
return state + 1
|
||||
case 'DECREMENT':
|
||||
return state - 1
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
const reducer = combineReducers({
|
||||
counter,
|
||||
// You don't have to use the `uppy` key. But if you don't,
|
||||
// you need to provide a custom `selector` to the `uppyReduxStore` call below.
|
||||
uppy: uppyReduxStore.reducer,
|
||||
})
|
||||
|
||||
let enhancer = applyMiddleware(uppyReduxStore.middleware(), logger)
|
||||
if (typeof __REDUX_DEVTOOLS_EXTENSION__ !== 'undefined') {
|
||||
enhancer = compose(enhancer, __REDUX_DEVTOOLS_EXTENSION__())
|
||||
}
|
||||
|
||||
const store = configureStore({
|
||||
reducer,
|
||||
enhancers: [enhancer],
|
||||
middleware: (getDefaultMiddleware) =>
|
||||
getDefaultMiddleware({
|
||||
serializableCheck: {
|
||||
ignoredActions: [uppyReduxStore.STATE_UPDATE],
|
||||
ignoreState: true,
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
// Counter example from https://github.com/reactjs/redux/blob/master/examples/counter-vanilla/index.html
|
||||
const valueEl = document.querySelector('#value')
|
||||
|
||||
function getCounter() {
|
||||
return store.getState().counter
|
||||
}
|
||||
function render() {
|
||||
valueEl.innerHTML = getCounter().toString()
|
||||
}
|
||||
render()
|
||||
store.subscribe(render)
|
||||
|
||||
document.querySelector('#increment').onclick = () => {
|
||||
store.dispatch({ type: 'INCREMENT' })
|
||||
}
|
||||
document.querySelector('#decrement').onclick = () => {
|
||||
store.dispatch({ type: 'DECREMENT' })
|
||||
}
|
||||
document.querySelector('#incrementIfOdd').onclick = () => {
|
||||
if (getCounter() % 2 !== 0) {
|
||||
store.dispatch({ type: 'INCREMENT' })
|
||||
}
|
||||
}
|
||||
document.querySelector('#incrementAsync').onclick = () => {
|
||||
setTimeout(() => store.dispatch({ type: 'INCREMENT' }), 1000)
|
||||
}
|
||||
|
||||
// Uppy using the same store
|
||||
const uppy = new Uppy({
|
||||
id: 'redux',
|
||||
store: new ReduxStore({ store }),
|
||||
// If we had placed our `reducer` elsewhere in Redux, eg. under an `uppy` key in the state for a profile page,
|
||||
// we'd do something like:
|
||||
//
|
||||
// store: new ReduxStore({
|
||||
// store: store,
|
||||
// id: 'avatar',
|
||||
// selector: state => state.pages.profile.uppy
|
||||
// }),
|
||||
debug: true,
|
||||
})
|
||||
uppy.use(Dashboard, {
|
||||
target: '#app',
|
||||
inline: true,
|
||||
width: 400,
|
||||
})
|
||||
uppy.use(Tus, { endpoint: 'https://tusd.tusdemo.net/files/' })
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"name": "example-redux",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@reduxjs/toolkit": "^1.9.3",
|
||||
"@uppy/core": "workspace:*",
|
||||
"@uppy/dashboard": "workspace:*",
|
||||
"@uppy/store-redux": "workspace:*",
|
||||
"@uppy/tus": "workspace:*",
|
||||
"redux": "^4.2.1",
|
||||
"redux-logger": "^3.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^7.0.6"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "vite"
|
||||
}
|
||||
}
|
||||
|
|
@ -15,8 +15,6 @@
|
|||
"dependencies": {
|
||||
"@uppy/core": "workspace:*",
|
||||
"@uppy/dashboard": "workspace:*",
|
||||
"@uppy/drag-drop": "workspace:*",
|
||||
"@uppy/progress-bar": "workspace:*",
|
||||
"@uppy/screen-capture": "workspace:*",
|
||||
"@uppy/svelte": "workspace:*",
|
||||
"@uppy/tus": "workspace:*",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
} from '@uppy/svelte'
|
||||
import Tus from '@uppy/tus'
|
||||
import UppyWebcam from '@uppy/webcam'
|
||||
import '@uppy/svelte/dist/styles.css'
|
||||
import '@uppy/svelte/css/style.css'
|
||||
|
||||
import CustomDropzone from '../components/CustomDropzone.svelte'
|
||||
import RemoteSource from '../components/RemoteSource.svelte'
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import Uppy from '@uppy/core'
|
|||
import Dashboard from '@uppy/dashboard'
|
||||
import Form from '@uppy/form'
|
||||
import ImageEditor from '@uppy/image-editor'
|
||||
import ProgressBar from '@uppy/progress-bar'
|
||||
import RemoteSources from '@uppy/remote-sources'
|
||||
import Transloadit, { COMPANION_URL } from '@uppy/transloadit'
|
||||
import Webcam from '@uppy/webcam'
|
||||
|
|
@ -10,7 +9,6 @@ import Webcam from '@uppy/webcam'
|
|||
import '@uppy/core/dist/style.css'
|
||||
import '@uppy/dashboard/dist/style.css'
|
||||
import '@uppy/image-editor/dist/style.css'
|
||||
import '@uppy/progress-bar/dist/style.css'
|
||||
|
||||
const TRANSLOADIT_KEY = '35c1aed03f5011e982b6afe82599b6a0'
|
||||
// A trivial template that resizes images, just for example purposes.
|
||||
|
|
@ -182,15 +180,13 @@ const uppyWithoutUI = new Uppy({
|
|||
restrictions: {
|
||||
allowedFileTypes: ['.png'],
|
||||
},
|
||||
}).use(Transloadit, {
|
||||
waitForEncoding: true,
|
||||
params: {
|
||||
auth: { key: TRANSLOADIT_KEY },
|
||||
template_id: TEMPLATE_ID,
|
||||
},
|
||||
})
|
||||
.use(Transloadit, {
|
||||
waitForEncoding: true,
|
||||
params: {
|
||||
auth: { key: TRANSLOADIT_KEY },
|
||||
template_id: TEMPLATE_ID,
|
||||
},
|
||||
})
|
||||
.use(ProgressBar, { target: '#upload-progress' })
|
||||
|
||||
window.doUpload = (event) => {
|
||||
const resultEl = document.querySelector('#upload-result')
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
"@uppy/drop-target": "workspace:*",
|
||||
"@uppy/form": "workspace:*",
|
||||
"@uppy/image-editor": "workspace:*",
|
||||
"@uppy/progress-bar": "workspace:*",
|
||||
"@uppy/remote-sources": "workspace:*",
|
||||
"@uppy/transloadit": "workspace:*",
|
||||
"@uppy/webcam": "workspace:*",
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@
|
|||
"dependencies": {
|
||||
"@uppy/core": "workspace:*",
|
||||
"@uppy/dashboard": "workspace:*",
|
||||
"@uppy/drag-drop": "workspace:*",
|
||||
"@uppy/progress-bar": "workspace:*",
|
||||
"@uppy/remote-sources": "workspace:*",
|
||||
"@uppy/screen-capture": "workspace:*",
|
||||
"@uppy/tus": "workspace:*",
|
||||
|
|
|
|||
|
|
@ -84,4 +84,4 @@ const uppy = computed(() =>
|
|||
)
|
||||
</script>
|
||||
|
||||
<style src="@uppy/vue/dist/styles.css"></style>
|
||||
<style src="@uppy/vue/css/style.css"></style>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ const upload = multer({
|
|||
function uploadRoute(req, res) {
|
||||
res.json({
|
||||
files: req.files.map((file) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
delete file.buffer
|
||||
return file
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
],
|
||||
"scripts": {
|
||||
"build": "turbo run --no-daemon build build:css --filter='./packages/@uppy/*' --filter='./packages/uppy'",
|
||||
"build:clean": "git clean -Xfd packages e2e .parcel-cache coverage .turbo -e '!node_modules' -e '!**/node_modules/**/*'",
|
||||
"build:watch": "turbo watch build build:css --filter='./packages/@uppy/*'",
|
||||
"build:clean": "git clean -Xfd packages e2e .parcel-cache coverage .turbo .turbo -e '!node_modules' -e '!**/node_modules/**/*'",
|
||||
"build:watch": "yarn build && turbo watch build build:css --filter='./packages/@uppy/*' --filter='./packages/uppy'",
|
||||
"migrate:components": "yarn workspace @uppy/components migrate",
|
||||
"check": "yarn exec biome check --write",
|
||||
"check:ci": "yarn exec biome ci",
|
||||
|
|
|
|||
|
|
@ -29,9 +29,6 @@
|
|||
"@angular/core": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0",
|
||||
"@uppy/core": "workspace:^",
|
||||
"@uppy/dashboard": "workspace:^",
|
||||
"@uppy/drag-drop": "workspace:^",
|
||||
"@uppy/progress-bar": "workspace:^",
|
||||
"@uppy/status-bar": "workspace:^",
|
||||
"@uppy/utils": "workspace:^"
|
||||
},
|
||||
"sideEffects": false
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { ChangeDetectionStrategy, Component } from "@angular/core";
|
||||
import { Uppy } from "@uppy/core";
|
||||
import type * as Dashboard from "@uppy/dashboard";
|
||||
import type { Body, Meta } from "@uppy/utils/lib/UppyFile";
|
||||
import type { Body, Meta } from "@uppy/utils";
|
||||
import { DashboardModalComponent } from "./dashboard-modal.component";
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
import { Uppy } from "@uppy/core";
|
||||
import type { DashboardOptions } from "@uppy/dashboard";
|
||||
import Dashboard from "@uppy/dashboard";
|
||||
import type { Body, Meta } from "@uppy/utils/lib/UppyFile";
|
||||
import type { Body, Meta } from "@uppy/utils";
|
||||
import { UppyAngularWrapper } from "../../utils/wrapper";
|
||||
|
||||
@Component({
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { ChangeDetectionStrategy, Component } from "@angular/core";
|
||||
import { Uppy } from "@uppy/core";
|
||||
import type * as Dashboard from "@uppy/dashboard";
|
||||
import type { Body, Meta } from "@uppy/utils/lib/UppyFile";
|
||||
import type { Body, Meta } from "@uppy/utils";
|
||||
import { DashboardComponent } from "./dashboard.component";
|
||||
|
||||
@Component({
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
import { Uppy } from "@uppy/core";
|
||||
import type { DashboardOptions } from "@uppy/dashboard";
|
||||
import Dashboard from "@uppy/dashboard";
|
||||
import type { Body, Meta } from "@uppy/utils/lib/UppyFile";
|
||||
import type { Body, Meta } from "@uppy/utils";
|
||||
import { UppyAngularWrapper } from "../../utils/wrapper";
|
||||
|
||||
@Component({
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
import { ChangeDetectionStrategy, Component } from "@angular/core";
|
||||
import { Uppy } from "@uppy/core";
|
||||
import type * as DragDrop from "@uppy/drag-drop";
|
||||
import type { Body, Meta } from "@uppy/utils/lib/UppyFile";
|
||||
import { DragDropComponent } from "./drag-drop.component";
|
||||
|
||||
|
||||
@Component({
|
||||
selector: "uppy-drag-drop-demo",
|
||||
template: ` <uppy-drag-drop [uppy]="uppy" [props]="props"></uppy-drag-drop> `,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [DragDropComponent],
|
||||
})
|
||||
export class DragDropDemoComponent<M extends Meta, B extends Body> {
|
||||
uppy: Uppy<M, B> = new Uppy({ debug: true, autoProceed: true });
|
||||
props: DragDrop.DragDropOptions = {};
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
import { async, type ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
|
||||
import { DragDropComponent } from "./drag-drop.component";
|
||||
|
||||
describe("DragDropComponent", () => {
|
||||
let component: DragDropComponent;
|
||||
let fixture: ComponentFixture<DragDropComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [DragDropComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DragDropComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it("should create", () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
Input,
|
||||
inject,
|
||||
type OnChanges,
|
||||
type OnDestroy,
|
||||
type SimpleChanges,
|
||||
} from "@angular/core";
|
||||
import { Uppy } from "@uppy/core";
|
||||
import type { DragDropOptions } from "@uppy/drag-drop";
|
||||
import DragDrop from "@uppy/drag-drop";
|
||||
import type { Body, Meta } from "@uppy/utils/lib/UppyFile";
|
||||
import { UppyAngularWrapper } from "../../utils/wrapper";
|
||||
|
||||
@Component({
|
||||
selector: "uppy-drag-drop",
|
||||
template: "",
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
})
|
||||
export class DragDropComponent<M extends Meta, B extends Body>
|
||||
extends UppyAngularWrapper<M, B, DragDropOptions>
|
||||
implements OnDestroy, OnChanges
|
||||
{
|
||||
el = inject(ElementRef);
|
||||
|
||||
@Input() uppy: Uppy<M, B> = new Uppy();
|
||||
@Input() props: DragDropOptions = {};
|
||||
|
||||
/** Inserted by Angular inject() migration for backwards compatibility */
|
||||
constructor(...args: unknown[]);
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.onMount(
|
||||
{ id: "angular:DragDrop", target: this.el.nativeElement },
|
||||
DragDrop,
|
||||
);
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
this.handleChanges(changes, DragDrop);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.uninstall();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
import { moduleMetadata } from "@storybook/angular";
|
||||
import { DragDropDemoComponent } from "./drag-drop-demo.component";
|
||||
|
||||
export default {
|
||||
title: "Drag Drop",
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
declarations: [DragDropDemoComponent],
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export const Default = () => ({
|
||||
component: DragDropDemoComponent,
|
||||
});
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
inject,
|
||||
type OnInit,
|
||||
} from "@angular/core";
|
||||
import { Uppy } from "@uppy/core";
|
||||
import type { ProgressBarOptions } from "@uppy/progress-bar";
|
||||
import Tus from "@uppy/tus";
|
||||
import type { Body, Meta } from "@uppy/utils/lib/UppyFile";
|
||||
import { ProgressBarComponent } from "./progress-bar.component";
|
||||
import { DragDropComponent } from "../drag-drop/drag-drop.component";
|
||||
import { CommonModule } from "@angular/common";
|
||||
|
||||
@Component({
|
||||
selector: "uppy-progress-bar-demo",
|
||||
template: `
|
||||
<section class="example-one">
|
||||
<h5>autoProceed is on</h5>
|
||||
|
||||
<!-- Target DOM node #1 -->
|
||||
<uppy-drag-drop [uppy]="uppyOne"></uppy-drag-drop>
|
||||
|
||||
<!-- Progress bar #1 -->
|
||||
<uppy-progress-bar [uppy]="uppyOne" [props]="props"></uppy-progress-bar>
|
||||
|
||||
<!-- Uploaded files list #1 -->
|
||||
<div class="uploaded-files" *ngIf="fileListOne?.length">
|
||||
<h5>Uploaded files:</h5>
|
||||
<ol>
|
||||
<li *ngFor="let item of fileListOne">
|
||||
<a [href]="item.url" target="_blank"> {{ item.fileName }}</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="example-two">
|
||||
<h5>autoProceed is off</h5>
|
||||
|
||||
<!-- Target DOM node #1 -->
|
||||
<uppy-drag-drop [uppy]="uppyTwo"></uppy-drag-drop>
|
||||
|
||||
<!-- Progress bar #1 -->
|
||||
<uppy-progress-bar [uppy]="uppyTwo" [props]="props"></uppy-progress-bar>
|
||||
|
||||
<button (click)="upload()" class="upload-button">Upload</button>
|
||||
|
||||
<!-- Uploaded files list #2 -->
|
||||
<div class="uploaded-files" *ngIf="fileListTwo?.length">
|
||||
<h5>Uploaded files:</h5>
|
||||
<ol>
|
||||
<li *ngFor="let item of fileListTwo">
|
||||
<a [href]="item.url" target="_blank"> {{ item.fileName }}</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [ProgressBarComponent, DragDropComponent, CommonModule],
|
||||
})
|
||||
export class ProgressBarDemoComponent<M extends Meta, B extends Body>
|
||||
implements OnInit
|
||||
{
|
||||
private cdr = inject(ChangeDetectorRef);
|
||||
|
||||
uppyOne!: Uppy<M, B>;
|
||||
uppyTwo!: Uppy<M, B>;
|
||||
fileListOne: { url: string; fileName: string }[] = [];
|
||||
fileListTwo: { url: string; fileName: string }[] = [];
|
||||
props: ProgressBarOptions = {
|
||||
hideAfterFinish: false,
|
||||
};
|
||||
|
||||
upload(): void {
|
||||
this.uppyTwo.upload();
|
||||
}
|
||||
|
||||
/** Inserted by Angular inject() migration for backwards compatibility */
|
||||
constructor(...args: unknown[]);
|
||||
|
||||
constructor() {}
|
||||
|
||||
updateFileList =
|
||||
(target: string) =>
|
||||
(file: any, response: any): void => {
|
||||
(this as any)[target] = [
|
||||
...(this as any)[target],
|
||||
{ url: response.uploadURL, fileName: file.name },
|
||||
];
|
||||
this.cdr.markForCheck();
|
||||
};
|
||||
|
||||
ngOnInit(): void {
|
||||
this.uppyOne = new Uppy<M, B>({ debug: true, autoProceed: true })
|
||||
.use(Tus, { endpoint: "https://master.tus.io/files/" })
|
||||
.on("upload-success", this.updateFileList("fileListOne"));
|
||||
this.uppyTwo = new Uppy<M, B>({ debug: true, autoProceed: false })
|
||||
.use(Tus, { endpoint: "https://master.tus.io/files/" })
|
||||
.on("upload-success", this.updateFileList("fileListTwo"));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
import { async, type ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
|
||||
import { ProgressBarComponent } from "./progress-bar.component";
|
||||
|
||||
describe("ProgressBarComponent", () => {
|
||||
let component: ProgressBarComponent;
|
||||
let fixture: ComponentFixture<ProgressBarComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ProgressBarComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ProgressBarComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it("should create", () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
Input,
|
||||
inject,
|
||||
type OnChanges,
|
||||
type OnDestroy,
|
||||
type SimpleChanges,
|
||||
} from "@angular/core";
|
||||
import { Uppy } from "@uppy/core";
|
||||
import type { ProgressBarOptions } from "@uppy/progress-bar";
|
||||
import ProgressBar from "@uppy/progress-bar";
|
||||
import type { Body, Meta } from "@uppy/utils/lib/UppyFile";
|
||||
import { UppyAngularWrapper } from "../../utils/wrapper";
|
||||
|
||||
@Component({
|
||||
selector: "uppy-progress-bar",
|
||||
template: "",
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
})
|
||||
export class ProgressBarComponent<M extends Meta, B extends Body>
|
||||
extends UppyAngularWrapper<M, B, ProgressBarOptions>
|
||||
implements OnDestroy, OnChanges
|
||||
{
|
||||
el = inject(ElementRef);
|
||||
|
||||
@Input() uppy: Uppy<M, B> = new Uppy();
|
||||
@Input() props: ProgressBarOptions = {};
|
||||
|
||||
/** Inserted by Angular inject() migration for backwards compatibility */
|
||||
constructor(...args: unknown[]);
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.onMount(
|
||||
{ id: "angular:ProgressBar", target: this.el.nativeElement },
|
||||
ProgressBar,
|
||||
);
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
this.handleChanges(changes, ProgressBar);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.uninstall();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
import { CommonModule } from "@angular/common";
|
||||
import { moduleMetadata } from "@storybook/angular";
|
||||
import { ProgressBarDemoComponent } from "./progress-bar-demo.component";
|
||||
|
||||
export default {
|
||||
title: "Progress Bar",
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [CommonModule],
|
||||
declarations: [ProgressBarDemoComponent],
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export const Default = () => ({
|
||||
component: ProgressBarDemoComponent,
|
||||
});
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import { ChangeDetectionStrategy, Component, type OnInit } from "@angular/core";
|
||||
import { Uppy } from "@uppy/core";
|
||||
import FileInput from "@uppy/file-input";
|
||||
import type * as StatusBar from "@uppy/status-bar";
|
||||
import Tus from "@uppy/tus";
|
||||
import type { Body, Meta } from "@uppy/utils/lib/UppyFile";
|
||||
import { StatusBarComponent } from "./status-bar.component";
|
||||
|
||||
@Component({
|
||||
selector: "uppy-status-bar-demo",
|
||||
template: `
|
||||
<div class="UppyInput"></div>
|
||||
<uppy-status-bar [uppy]="uppy" [props]="props"></uppy-status-bar>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [StatusBarComponent],
|
||||
})
|
||||
export class StatusBarDemoComponent<M extends Meta, B extends Body>
|
||||
implements OnInit
|
||||
{
|
||||
uppy: Uppy<M, B> = new Uppy({ debug: true, autoProceed: true });
|
||||
props: StatusBar.StatusBarOptions = {
|
||||
hideUploadButton: true,
|
||||
hideAfterFinish: false,
|
||||
};
|
||||
|
||||
ngOnInit(): void {
|
||||
this.uppy
|
||||
.use(FileInput, { target: ".UppyInput", pretty: false })
|
||||
.use(Tus, { endpoint: "https://master.tus.io/files/" });
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
import { async, type ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
|
||||
import { StatusBarComponent } from "./status-bar.component";
|
||||
|
||||
describe("StatusBarComponent", () => {
|
||||
let component: StatusBarComponent;
|
||||
let fixture: ComponentFixture<StatusBarComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [StatusBarComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(StatusBarComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it("should create", () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
Input,
|
||||
inject,
|
||||
type OnChanges,
|
||||
type OnDestroy,
|
||||
type SimpleChanges,
|
||||
} from "@angular/core";
|
||||
import { Uppy } from "@uppy/core";
|
||||
import type { StatusBarOptions } from "@uppy/status-bar";
|
||||
import StatusBar from "@uppy/status-bar";
|
||||
import type { Body, Meta } from "@uppy/utils/lib/UppyFile";
|
||||
import { UppyAngularWrapper } from "../../utils/wrapper";
|
||||
|
||||
@Component({
|
||||
selector: "uppy-status-bar",
|
||||
template: "",
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
})
|
||||
export class StatusBarComponent<M extends Meta, B extends Body>
|
||||
extends UppyAngularWrapper<M, B, StatusBarOptions>
|
||||
implements OnDestroy, OnChanges
|
||||
{
|
||||
el = inject(ElementRef);
|
||||
|
||||
@Input() uppy: Uppy<M, B> = new Uppy();
|
||||
@Input() props: StatusBarOptions = {};
|
||||
|
||||
/** Inserted by Angular inject() migration for backwards compatibility */
|
||||
constructor(...args: unknown[]);
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.onMount(
|
||||
{ id: "angular:StatusBar", target: this.el.nativeElement },
|
||||
StatusBar,
|
||||
);
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
this.handleChanges(changes, StatusBar);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.uninstall();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
import { moduleMetadata } from "@storybook/angular";
|
||||
import { StatusBarDemoComponent } from "./status-bar-demo.component";
|
||||
|
||||
export default {
|
||||
title: "Status Bar",
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
declarations: [StatusBarDemoComponent],
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export const Default = () => ({
|
||||
component: StatusBarDemoComponent,
|
||||
});
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
import type { ElementRef, SimpleChanges } from "@angular/core";
|
||||
import type { UIPlugin, UIPluginOptions, Uppy } from "@uppy/core";
|
||||
import type { DragDropOptions } from "@uppy/drag-drop";
|
||||
import type { ProgressBarOptions } from "@uppy/progress-bar";
|
||||
import type { StatusBarOptions } from "@uppy/status-bar";
|
||||
import type { Body, Meta } from "@uppy/utils/lib/UppyFile";
|
||||
import type { DashboardOptions } from "@uppy/dashboard";
|
||||
import type { Body, Meta } from "@uppy/utils";
|
||||
|
||||
export abstract class UppyAngularWrapper<
|
||||
M extends Meta,
|
||||
|
|
@ -11,7 +9,7 @@ export abstract class UppyAngularWrapper<
|
|||
Opts extends UIPluginOptions,
|
||||
PluginType extends UIPlugin<Opts, M, B> = UIPlugin<Opts, M, B>,
|
||||
> {
|
||||
abstract props: DragDropOptions | StatusBarOptions | ProgressBarOptions;
|
||||
abstract props: DashboardOptions<M, B>;
|
||||
abstract el: ElementRef;
|
||||
abstract uppy: Uppy<M, B>;
|
||||
private options: any;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,3 @@
|
|||
|
||||
export { DashboardComponent } from './lib/components/dashboard/dashboard.component'
|
||||
export { DashboardModalComponent } from './lib/components/dashboard-modal/dashboard-modal.component'
|
||||
export { DragDropComponent } from './lib/components/drag-drop/drag-drop.component'
|
||||
export { ProgressBarComponent } from './lib/components/progress-bar/progress-bar.component'
|
||||
export { StatusBarComponent } from './lib/components/status-bar/status-bar.component'
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@
|
|||
"dependsOn": [
|
||||
"@uppy/core#build",
|
||||
"@uppy/dashboard#build",
|
||||
"@uppy/drag-drop#build",
|
||||
"@uppy/progress-bar#build",
|
||||
"@uppy/status-bar#build",
|
||||
"@uppy/utils#build"
|
||||
],
|
||||
"inputs": [
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
"mediarecorder"
|
||||
],
|
||||
"type": "module",
|
||||
"sideEffects": [
|
||||
"*.css"
|
||||
],
|
||||
"homepage": "https://uppy.io",
|
||||
"bugs": {
|
||||
"url": "https://github.com/transloadit/uppy/issues"
|
||||
|
|
@ -30,6 +33,12 @@
|
|||
"dist",
|
||||
"CHANGELOG.md"
|
||||
],
|
||||
"exports": {
|
||||
".": "./lib/index.js",
|
||||
"./css/style.css": "./dist/style.css",
|
||||
"./css/style.min.css": "./dist/style.min.css",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uppy/utils": "workspace:^",
|
||||
"preact": "^10.5.13"
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ import type {
|
|||
} from '@uppy/core'
|
||||
|
||||
import { UIPlugin } from '@uppy/core'
|
||||
import getFileTypeExtension from '@uppy/utils/lib/getFileTypeExtension'
|
||||
|
||||
import type { LocaleStrings } from '@uppy/utils/lib/Translator'
|
||||
import type { LocaleStrings } from '@uppy/utils'
|
||||
import { getFileTypeExtension } from '@uppy/utils'
|
||||
import packageJson from '../package.json' with { type: 'json' }
|
||||
import locale from './locale.js'
|
||||
import PermissionsScreen from './PermissionsScreen.js'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { I18n } from '@uppy/utils/lib/Translator'
|
||||
import type { I18n } from '@uppy/utils'
|
||||
|
||||
interface DiscardButtonProps {
|
||||
onDiscard: () => void
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { I18n } from '@uppy/utils/lib/Translator'
|
||||
import type { I18n } from '@uppy/utils'
|
||||
import type { h } from 'preact'
|
||||
|
||||
interface PermissionsScreenProps {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { I18n } from '@uppy/utils/lib/Translator'
|
||||
import type { I18n } from '@uppy/utils'
|
||||
|
||||
interface RecordButtonProps {
|
||||
recording: boolean
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { I18n } from '@uppy/utils/lib/Translator'
|
||||
import type { I18n } from '@uppy/utils'
|
||||
import { useEffect, useRef } from 'preact/hooks'
|
||||
import AudioSourceSelect, {
|
||||
type AudioSourceSelectProps,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { I18n } from '@uppy/utils/lib/Translator'
|
||||
import type { I18n } from '@uppy/utils'
|
||||
|
||||
interface SubmitButtonProps {
|
||||
onSubmit: () => void
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
# @uppy/aws-s3-multipart
|
||||
|
||||
## 4.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1b1a9e3: Define "files" in package.json
|
||||
- Updated dependencies [1b1a9e3]
|
||||
- @uppy/aws-s3@4.3.2
|
||||
|
||||
## 4.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 0c24c5a: Use TypeScript compiler instead of Babel
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [0c24c5a]
|
||||
- @uppy/aws-s3@4.3.0
|
||||
|
||||
## 4.0.0-beta.5
|
||||
|
||||
Released: 2024-05-03
|
||||
Included in: Uppy v4.0.0-beta.5
|
||||
|
||||
- @uppy/aws-s3-multipart: Format (Murderlon)
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 Transloadit
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
# @uppy/aws-s3-multipart
|
||||
|
||||
This package is deprecated. Use
|
||||
[`@uppy/aws-s3`](https://npmjs.org/package/@uppy/aws-s3) instead.
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
{
|
||||
"name": "@uppy/aws-s3-multipart",
|
||||
"description": "Upload to Amazon S3 with Uppy and S3's Multipart upload strategy",
|
||||
"version": "4.1.2",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"type": "module",
|
||||
"keywords": [
|
||||
"file uploader",
|
||||
"aws s3",
|
||||
"amazon s3",
|
||||
"s3",
|
||||
"uppy",
|
||||
"uppy-plugin",
|
||||
"multipart"
|
||||
],
|
||||
"homepage": "https://uppy.io",
|
||||
"bugs": {
|
||||
"url": "https://github.com/transloadit/uppy/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/transloadit/uppy.git"
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"lib",
|
||||
"dist",
|
||||
"CHANGELOG.md"
|
||||
],
|
||||
"dependencies": {
|
||||
"@uppy/aws-s3": "workspace:^"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@uppy/core": "workspace:^",
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
export * from '@uppy/aws-s3'
|
||||
export { default } from '@uppy/aws-s3'
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"build": "tsc --build tsconfig.build.json",
|
||||
"typecheck": "tsc --build",
|
||||
|
|
@ -33,6 +34,10 @@
|
|||
"dist",
|
||||
"CHANGELOG.md"
|
||||
],
|
||||
"exports": {
|
||||
".": "./lib/index.js",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uppy/companion-client": "workspace:^",
|
||||
"@uppy/utils": "workspace:^"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import type { Body, Meta, UppyFile } from '@uppy/core'
|
||||
import type {
|
||||
RateLimitedQueue,
|
||||
WrapPromiseFunctionType,
|
||||
} from '@uppy/utils/lib/RateLimitedQueue'
|
||||
import type { RateLimitedQueue, WrapPromiseFunctionType } from '@uppy/utils'
|
||||
import type AwsS3Multipart from './index.js'
|
||||
import type {
|
||||
AwsS3MultipartOptions,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { Uppy } from '@uppy/core'
|
||||
import { AbortController } from '@uppy/utils/lib/AbortController'
|
||||
import type { Body, Meta, UppyFile } from '@uppy/utils/lib/UppyFile'
|
||||
import type { Body, Meta, UppyFile } from '@uppy/utils'
|
||||
import { AbortController } from '@uppy/utils'
|
||||
import type { HTTPCommunicationQueue } from './HTTPCommunicationQueue.js'
|
||||
|
||||
const MB = 1024 * 1024
|
||||
|
|
|
|||
|
|
@ -2,19 +2,18 @@ import { RequestClient } from '@uppy/companion-client'
|
|||
import {
|
||||
BasePlugin,
|
||||
type DefinePluginOpts,
|
||||
EventManager,
|
||||
type PluginOpts,
|
||||
type Uppy,
|
||||
} from '@uppy/core'
|
||||
import EventManager from '@uppy/core/lib/EventManager.js'
|
||||
import { createAbortError } from '@uppy/utils/lib/AbortController'
|
||||
import type { RequestOptions } from '@uppy/utils/lib/CompanionClientProvider'
|
||||
import type { Body, Meta, RequestOptions, UppyFile } from '@uppy/utils'
|
||||
import {
|
||||
createAbortError,
|
||||
filterFilesToEmitUploadStarted,
|
||||
filterNonFailedFiles,
|
||||
} from '@uppy/utils/lib/fileFilters'
|
||||
import getAllowedMetaFields from '@uppy/utils/lib/getAllowedMetaFields'
|
||||
import { RateLimitedQueue } from '@uppy/utils/lib/RateLimitedQueue'
|
||||
import type { Body, Meta, UppyFile } from '@uppy/utils/lib/UppyFile'
|
||||
getAllowedMetaFields,
|
||||
RateLimitedQueue,
|
||||
} from '@uppy/utils'
|
||||
import packageJson from '../package.json' with { type: 'json' }
|
||||
import createSignedURL from './createSignedURL.js'
|
||||
import { HTTPCommunicationQueue } from './HTTPCommunicationQueue.js'
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { createAbortError } from '@uppy/utils/lib/AbortController'
|
||||
import type { Body } from '@uppy/utils/lib/UppyFile'
|
||||
import type { Body } from '@uppy/utils'
|
||||
import { createAbortError } from '@uppy/utils'
|
||||
|
||||
import type { AwsS3Part } from './index.js'
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"build": "tsc --build tsconfig.build.json",
|
||||
"typecheck": "tsc --build"
|
||||
|
|
@ -29,6 +30,10 @@
|
|||
"dist",
|
||||
"CHANGELOG.md"
|
||||
],
|
||||
"exports": {
|
||||
".": "./lib/index.js",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uppy/companion-client": "workspace:^",
|
||||
"@uppy/provider-views": "workspace:^",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import type {
|
|||
import { UIPlugin, type Uppy } from '@uppy/core'
|
||||
import { ProviderViews } from '@uppy/provider-views'
|
||||
|
||||
import type { LocaleStrings } from '@uppy/utils/lib/Translator'
|
||||
import type { LocaleStrings } from '@uppy/utils'
|
||||
// biome-ignore lint/style/useImportType: h is not a type
|
||||
import { type ComponentChild, h } from 'preact'
|
||||
import packageJson from '../package.json' with { type: 'json' }
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"build": "tsc --build tsconfig.build.json",
|
||||
"typecheck": "tsc --build",
|
||||
|
|
@ -31,6 +32,10 @@
|
|||
"dist",
|
||||
"CHANGELOG.md"
|
||||
],
|
||||
"exports": {
|
||||
".": "./lib/index.js",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uppy/utils": "workspace:^",
|
||||
"namespace-emitter": "^2.0.1",
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ import type {
|
|||
UnknownProviderPlugin,
|
||||
Uppy,
|
||||
} from '@uppy/core'
|
||||
import type {
|
||||
CompanionClientProvider,
|
||||
RequestOptions,
|
||||
} from '@uppy/utils/lib/CompanionClientProvider'
|
||||
import type { CompanionClientProvider, RequestOptions } from '@uppy/utils'
|
||||
import { isOriginAllowed } from './getAllowedHosts.js'
|
||||
import type { CompanionPluginOptions } from './index.js'
|
||||
import RequestClient, { authErrorStatusCode } from './RequestClient.js'
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import type Uppy from '@uppy/core'
|
||||
import type { RequestOptions } from '@uppy/utils/lib/CompanionClientProvider'
|
||||
import ErrorWithCause from '@uppy/utils/lib/ErrorWithCause'
|
||||
import fetchWithNetworkError from '@uppy/utils/lib/fetchWithNetworkError'
|
||||
import getSocketHost from '@uppy/utils/lib/getSocketHost'
|
||||
import type { Body, Meta, UppyFile } from '@uppy/utils/lib/UppyFile'
|
||||
import UserFacingApiError from '@uppy/utils/lib/UserFacingApiError'
|
||||
import type { Body, Meta, RequestOptions, UppyFile } from '@uppy/utils'
|
||||
import {
|
||||
ErrorWithCause,
|
||||
fetchWithNetworkError,
|
||||
getSocketHost,
|
||||
UserFacingApiError,
|
||||
} from '@uppy/utils'
|
||||
import pRetry, { AbortError } from 'p-retry'
|
||||
import packageJson from '../package.json' with { type: 'json' }
|
||||
import AuthError from './AuthError.js'
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Body, Meta, Uppy } from '@uppy/core'
|
||||
import type { CompanionClientSearchProvider } from '@uppy/utils/lib/CompanionClientProvider'
|
||||
import type { CompanionClientSearchProvider } from '@uppy/utils'
|
||||
import RequestClient, { type Opts } from './RequestClient.js'
|
||||
|
||||
const getName = (id: string): string => {
|
||||
|
|
|
|||
|
|
@ -36,13 +36,14 @@ describe('isOriginAllowed', () => {
|
|||
expect(isOriginAllowed('a', [/^.+$/])).toBeTruthy()
|
||||
expect(isOriginAllowed('a', ['^.+$'])).toBeTruthy()
|
||||
expect(
|
||||
isOriginAllowed('www.transloadit.com', ['www\\.transloadit\\.com']),
|
||||
isOriginAllowed('www.transloadit.com', ['^www\\.transloadit\\.com$']),
|
||||
).toBeTruthy()
|
||||
expect(
|
||||
isOriginAllowed('www.transloadit.com', ['transloadit\\.com']),
|
||||
isOriginAllowed('www.transloadit.com', ['^transloadit\\.com$']),
|
||||
).toBeFalsy()
|
||||
expect(isOriginAllowed('match', ['fail', 'match'])).toBeTruthy()
|
||||
// todo maybe next major:
|
||||
// expect(isOriginAllowed('www.transloadit.com', ['\\.transloadit\\.com$'])).toBeTruthy()
|
||||
expect(
|
||||
isOriginAllowed('www.transloadit.com', ['\\.transloadit\\.com$']),
|
||||
).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ function escapeRegex(string: string) {
|
|||
|
||||
function wrapInRegex(value?: string | RegExp): RegExp | undefined {
|
||||
if (typeof value === 'string') {
|
||||
// TODO in the next major we should change this to `new RegExp(value)` so that the user can control start/end characters
|
||||
return new RegExp(`^${value}$`) // throws if invalid regex
|
||||
return new RegExp(value) // throws if invalid regex
|
||||
}
|
||||
if (value instanceof RegExp) {
|
||||
return value
|
||||
|
|
|
|||
22
packages/@uppy/companion/__mocks__/express-prom-bundle.js
Normal file
22
packages/@uppy/companion/__mocks__/express-prom-bundle.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
class Gauge {
|
||||
set = () => {}
|
||||
}
|
||||
|
||||
export default function () {
|
||||
const middleware = (req, res, next) => {
|
||||
// simulate prometheus metrics endpoint:
|
||||
if (req.url === '/metrics') {
|
||||
res.setHeader('Content-Type', 'text/plain')
|
||||
res.end('# Dummy metrics\n')
|
||||
return
|
||||
}
|
||||
next()
|
||||
}
|
||||
|
||||
middleware.promClient = {
|
||||
collectDefaultMetrics: () => {},
|
||||
Gauge,
|
||||
}
|
||||
|
||||
return middleware
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
class Upload {
|
||||
export class Upload {
|
||||
constructor(file, options) {
|
||||
this.url = 'https://tus.endpoint/files/foo-bar'
|
||||
this.options = options
|
||||
|
|
@ -18,4 +18,4 @@ class Upload {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = { Upload }
|
||||
export default { Upload }
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
require('../lib/standalone/start-server')
|
||||
import '../lib/standalone/start-server.js'
|
||||
|
|
|
|||
|
|
@ -6,11 +6,18 @@
|
|||
"types": "lib/companion.d.ts",
|
||||
"author": "Transloadit.com",
|
||||
"license": "MIT",
|
||||
"sideEffects": false,
|
||||
"homepage": "https://github.com/transloadit/uppy#readme",
|
||||
"type": "module",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/transloadit/uppy.git"
|
||||
},
|
||||
"exports": {
|
||||
".": "./lib/companion.js",
|
||||
"./standalone": "./lib/standalone/index.js",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"keywords": [
|
||||
"file uploader",
|
||||
"progress",
|
||||
|
|
@ -43,12 +50,12 @@
|
|||
"escape-string-regexp": "4.0.0",
|
||||
"express": "4.21.2",
|
||||
"express-interceptor": "1.2.0",
|
||||
"express-prom-bundle": "7.0.0",
|
||||
"express-prom-bundle": "7",
|
||||
"express-session": "1.18.1",
|
||||
"fast-safe-stringify": "^2.1.1",
|
||||
"formdata-node": "^6.0.3",
|
||||
"got": "^13.0.0",
|
||||
"grant": "5.4.22",
|
||||
"grant": "^5.4.24",
|
||||
"helmet": "^7.1.0",
|
||||
"ioredis": "^5.3.2",
|
||||
"ipaddr.js": "^2.0.1",
|
||||
|
|
@ -67,7 +74,7 @@
|
|||
"supports-color": "8.x",
|
||||
"tus-js-client": "^4.1.0",
|
||||
"validator": "^13.0.0",
|
||||
"webdav": "5.7.1",
|
||||
"webdav": "^5.8.0",
|
||||
"ws": "8.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -88,7 +95,6 @@
|
|||
"@types/ws": "8.5.3",
|
||||
"execa": "^9.6.0",
|
||||
"http-proxy": "^1.18.1",
|
||||
"jest": "^29.0.0",
|
||||
"nock": "^13.1.3",
|
||||
"supertest": "6.2.4",
|
||||
"typescript": "^5.8.3",
|
||||
|
|
@ -96,23 +102,20 @@
|
|||
},
|
||||
"files": [
|
||||
"bin/",
|
||||
"lib/"
|
||||
"lib/",
|
||||
"src/",
|
||||
"CHANGELOG.md"
|
||||
],
|
||||
"jest": {
|
||||
"testEnvironment": "node",
|
||||
"testTimeout": 10000,
|
||||
"automock": false
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc -p .",
|
||||
"build": "tsc --build tsconfig.build.json",
|
||||
"deploy": "kubectl apply -f infra/kube/companion-kube.yml",
|
||||
"start": "node ./lib/standalone/start-server.js",
|
||||
"start:dev": "bash start-dev",
|
||||
"test": "NODE_OPTIONS=--experimental-vm-modules jest --runInBand --silent",
|
||||
"typecheck": "tsc --build"
|
||||
"typecheck": "tsc --build",
|
||||
"test": "vitest run --silent='passed-only'"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.20.0 || ^20.15.0 || >=22.0.0"
|
||||
"node": "^20.19.3 || >=22.0.0"
|
||||
},
|
||||
"installConfig": {
|
||||
"hoistingLimits": "workspaces"
|
||||
|
|
|
|||
|
|
@ -1,40 +1,42 @@
|
|||
const express = require('express')
|
||||
const Grant = require('grant').default.express()
|
||||
const merge = require('lodash/merge')
|
||||
const cookieParser = require('cookie-parser')
|
||||
const interceptor = require('express-interceptor')
|
||||
const { randomUUID } = require('node:crypto')
|
||||
|
||||
const grantConfig = require('./config/grant')()
|
||||
const providerManager = require('./server/provider')
|
||||
const controllers = require('./server/controllers')
|
||||
const s3 = require('./server/controllers/s3')
|
||||
const url = require('./server/controllers/url')
|
||||
const googlePicker = require('./server/controllers/googlePicker')
|
||||
const createEmitter = require('./server/emitter')
|
||||
const redis = require('./server/redis')
|
||||
const jobs = require('./server/jobs')
|
||||
const logger = require('./server/logger')
|
||||
const middlewares = require('./server/middlewares')
|
||||
const {
|
||||
getMaskableSecrets,
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import cookieParser from 'cookie-parser'
|
||||
import express from 'express'
|
||||
import interceptor from 'express-interceptor'
|
||||
import grant from 'grant'
|
||||
import merge from 'lodash/merge.js'
|
||||
import packageJson from '../package.json' with { type: 'json' }
|
||||
import {
|
||||
defaultOptions,
|
||||
getMaskableSecrets,
|
||||
validateConfig,
|
||||
} = require('./config/companion')
|
||||
const {
|
||||
} from './config/companion.js'
|
||||
import grantConfigFn from './config/grant.js'
|
||||
import googlePicker from './server/controllers/googlePicker.js'
|
||||
import * as controllers from './server/controllers/index.js'
|
||||
import s3 from './server/controllers/s3.js'
|
||||
import url from './server/controllers/url.js'
|
||||
import createEmitter from './server/emitter/index.js'
|
||||
import { getURLBuilder } from './server/helpers/utils.js'
|
||||
import * as jobs from './server/jobs.js'
|
||||
import logger from './server/logger.js'
|
||||
import * as middlewares from './server/middlewares.js'
|
||||
import { getCredentialsOverrideMiddleware } from './server/provider/credentials.js'
|
||||
import {
|
||||
ProviderApiError,
|
||||
ProviderUserError,
|
||||
ProviderAuthError,
|
||||
} = require('./server/provider/error')
|
||||
const {
|
||||
getCredentialsOverrideMiddleware,
|
||||
} = require('./server/provider/credentials')
|
||||
const { getURLBuilder } = require('./server/helpers/utils')
|
||||
// @ts-ignore
|
||||
const { version } = require('../package.json')
|
||||
const { isOAuthProvider } = require('./server/provider/Provider')
|
||||
ProviderUserError,
|
||||
} from './server/provider/error.js'
|
||||
import * as providerManager from './server/provider/index.js'
|
||||
import { isOAuthProvider } from './server/provider/Provider.js'
|
||||
import * as redis from './server/redis.js'
|
||||
|
||||
function setLoggerProcessName({ loggerProcessName }) {
|
||||
import socket from './server/socket.js'
|
||||
|
||||
export { socket }
|
||||
|
||||
const grantConfig = grantConfigFn()
|
||||
|
||||
export function setLoggerProcessName({ loggerProcessName }) {
|
||||
if (loggerProcessName != null) logger.setProcessName(loggerProcessName)
|
||||
}
|
||||
|
||||
|
|
@ -72,14 +74,11 @@ const interceptGrantErrorResponse = interceptor((req, res) => {
|
|||
})
|
||||
|
||||
// make the errors available publicly for custom providers
|
||||
module.exports.errors = {
|
||||
export const errors = {
|
||||
ProviderApiError,
|
||||
ProviderUserError,
|
||||
ProviderAuthError,
|
||||
}
|
||||
module.exports.socket = require('./server/socket')
|
||||
|
||||
module.exports.setLoggerProcessName = setLoggerProcessName
|
||||
|
||||
/**
|
||||
* Entry point into initializing the Companion app.
|
||||
|
|
@ -87,7 +86,7 @@ module.exports.setLoggerProcessName = setLoggerProcessName
|
|||
* @param {object} optionsArg
|
||||
* @returns {{ app: import('express').Express, emitter: any }}}
|
||||
*/
|
||||
module.exports.app = (optionsArg = {}) => {
|
||||
export function app(optionsArg = {}) {
|
||||
setLoggerProcessName(optionsArg)
|
||||
|
||||
validateConfig(optionsArg)
|
||||
|
|
@ -131,7 +130,7 @@ module.exports.app = (optionsArg = {}) => {
|
|||
express.urlencoded({ extended: false }),
|
||||
getCredentialsOverrideMiddleware(providers, options),
|
||||
)
|
||||
app.use(Grant(grantConfig))
|
||||
app.use(grant.default.express(grantConfig))
|
||||
|
||||
app.use((req, res, next) => {
|
||||
if (options.sendSelfEndpoint) {
|
||||
|
|
@ -307,7 +306,7 @@ module.exports.app = (optionsArg = {}) => {
|
|||
interval: options.periodicPingInterval,
|
||||
count: options.periodicPingCount,
|
||||
staticPayload: options.periodicPingStaticPayload,
|
||||
version,
|
||||
version: packageJson.version,
|
||||
processId,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
const fs = require('node:fs')
|
||||
const { isURL } = require('validator')
|
||||
const logger = require('../server/logger')
|
||||
const { defaultGetKey } = require('../server/helpers/utils')
|
||||
import fs from 'node:fs'
|
||||
import validator from 'validator'
|
||||
import { defaultGetKey } from '../server/helpers/utils.js'
|
||||
import logger from '../server/logger.js'
|
||||
|
||||
const defaultOptions = {
|
||||
export const defaultOptions = {
|
||||
server: {
|
||||
protocol: 'http',
|
||||
path: '',
|
||||
|
|
@ -28,7 +28,7 @@ const defaultOptions = {
|
|||
/**
|
||||
* @param {object} companionOptions
|
||||
*/
|
||||
function getMaskableSecrets(companionOptions) {
|
||||
export function getMaskableSecrets(companionOptions) {
|
||||
const secrets = []
|
||||
const { providerOptions, customProviders, s3 } = companionOptions
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ function getMaskableSecrets(companionOptions) {
|
|||
*
|
||||
* @param {object} companionOptions
|
||||
*/
|
||||
const validateConfig = (companionOptions) => {
|
||||
export const validateConfig = (companionOptions) => {
|
||||
const mandatoryOptions = ['secret', 'filePath', 'server.host']
|
||||
/** @type {string[]} */
|
||||
const unspecified = []
|
||||
|
|
@ -148,7 +148,7 @@ const validateConfig = (companionOptions) => {
|
|||
(!Array.isArray(periodicPingUrls) ||
|
||||
periodicPingUrls.some(
|
||||
(url2) =>
|
||||
!isURL(url2, {
|
||||
!validator.isURL(url2, {
|
||||
protocols: ['http', 'https'],
|
||||
require_protocol: true,
|
||||
require_tld: false,
|
||||
|
|
@ -162,9 +162,3 @@ const validateConfig = (companionOptions) => {
|
|||
throw new TypeError('Option maxFilenameLength must be greater than 0')
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
defaultOptions,
|
||||
getMaskableSecrets,
|
||||
validateConfig,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ const defaults = {
|
|||
}
|
||||
|
||||
// oauth configuration for provider services that are used.
|
||||
module.exports = () => {
|
||||
export default () => {
|
||||
return {
|
||||
// we need separate auth providers because scopes are different,
|
||||
// and because it would be a too big rewrite to allow reuse of the same provider.
|
||||
|
|
|
|||
|
|
@ -1,31 +1,27 @@
|
|||
const tus = require('tus-js-client')
|
||||
const { randomUUID } = require('node:crypto')
|
||||
const validator = require('validator')
|
||||
const { pipeline } = require('node:stream/promises')
|
||||
const { join } = require('node:path')
|
||||
const fs = require('node:fs')
|
||||
const throttle = require('lodash/throttle')
|
||||
const { once } = require('node:events')
|
||||
const { FormData } = require('formdata-node')
|
||||
|
||||
const { Upload } = require('@aws-sdk/lib-storage')
|
||||
|
||||
const {
|
||||
rfc2047EncodeMetadata,
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { once } from 'node:events'
|
||||
import { createReadStream, createWriteStream, ReadStream } from 'node:fs'
|
||||
import { stat, unlink } from 'node:fs/promises'
|
||||
import { join } from 'node:path'
|
||||
import { pipeline } from 'node:stream/promises'
|
||||
import { Upload } from '@aws-sdk/lib-storage'
|
||||
import { FormData } from 'formdata-node'
|
||||
import got from 'got'
|
||||
import throttle from 'lodash/throttle.js'
|
||||
import { serializeError } from 'serialize-error'
|
||||
import tus from 'tus-js-client'
|
||||
import validator from 'validator'
|
||||
import emitter from './emitter/index.js'
|
||||
import headerSanitize from './header-blacklist.js'
|
||||
import {
|
||||
getBucket,
|
||||
hasMatch,
|
||||
jsonStringify,
|
||||
rfc2047EncodeMetadata,
|
||||
truncateFilename,
|
||||
} = require('./helpers/utils')
|
||||
|
||||
const got = require('./got')
|
||||
|
||||
const { createReadStream, createWriteStream, ReadStream } = fs
|
||||
const { stat, unlink } = fs.promises
|
||||
|
||||
const emitter = require('./emitter')
|
||||
const { jsonStringify, hasMatch } = require('./helpers/utils')
|
||||
const logger = require('./logger')
|
||||
const headerSanitize = require('./header-blacklist')
|
||||
const redis = require('./redis')
|
||||
} from './helpers/utils.js'
|
||||
import * as logger from './logger.js'
|
||||
import * as redis from './redis.js'
|
||||
|
||||
// Need to limit length or we can get
|
||||
// "MetadataTooLarge: Your metadata headers exceed the maximum allowed metadata size" in tus / S3
|
||||
|
|
@ -40,7 +36,7 @@ function exceedsMaxFileSize(maxFileSize, size) {
|
|||
return maxFileSize && size && size > maxFileSize
|
||||
}
|
||||
|
||||
class ValidationError extends Error {
|
||||
export class ValidationError extends Error {
|
||||
name = 'ValidationError'
|
||||
}
|
||||
|
||||
|
|
@ -82,7 +78,6 @@ function validateOptions(options) {
|
|||
}
|
||||
|
||||
// validate protocol
|
||||
// @todo this validation should not be conditional once the protocol field is mandatory
|
||||
if (
|
||||
options.protocol &&
|
||||
!Object.keys(PROTOCOLS).some((key) => PROTOCOLS[key] === options.protocol)
|
||||
|
|
@ -127,7 +122,7 @@ const states = {
|
|||
done: 'done',
|
||||
}
|
||||
|
||||
class Uploader {
|
||||
export default class Uploader {
|
||||
/** @type {import('ioredis').Redis} */
|
||||
storage
|
||||
|
||||
|
|
@ -227,8 +222,6 @@ class Uploader {
|
|||
}
|
||||
|
||||
_getUploadProtocol() {
|
||||
// todo a default protocol should not be set. We should ensure that the user specifies their protocol.
|
||||
// after we drop old versions of uppy client we can remove this
|
||||
return this.options.protocol || PROTOCOLS.multipart
|
||||
}
|
||||
|
||||
|
|
@ -530,8 +523,6 @@ class Uploader {
|
|||
async #emitError(err) {
|
||||
// delete stack to avoid sending server info to client
|
||||
// see PR discussion https://github.com/transloadit/uppy/pull/3832
|
||||
// @ts-ignore
|
||||
const { serializeError } = await import('serialize-error')
|
||||
const { stack, ...serializedErr } = serializeError(err)
|
||||
const dataToEmit = {
|
||||
action: 'error',
|
||||
|
|
@ -691,7 +682,7 @@ class Uploader {
|
|||
try {
|
||||
const httpMethod =
|
||||
(this.options.httpMethod || '').toUpperCase() === 'PUT' ? 'put' : 'post'
|
||||
const runRequest = (await got)[httpMethod]
|
||||
const runRequest = await got[httpMethod]
|
||||
|
||||
const response = await runRequest(url, reqOptions)
|
||||
|
||||
|
|
@ -782,6 +773,3 @@ class Uploader {
|
|||
|
||||
Uploader.FILE_NAME_PREFIX = 'uppy-file'
|
||||
Uploader.STORAGE_PREFIX = 'companion'
|
||||
|
||||
module.exports = Uploader
|
||||
module.exports.ValidationError = ValidationError
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
/**
|
||||
* oAuth callback. Encrypts the access token and sends the new token with the response,
|
||||
*/
|
||||
const serialize = require('serialize-javascript')
|
||||
|
||||
const tokenService = require('../helpers/jwt')
|
||||
const logger = require('../logger')
|
||||
const oAuthState = require('../helpers/oauth-state')
|
||||
import serialize from 'serialize-javascript'
|
||||
import * as tokenService from '../helpers/jwt.js'
|
||||
import * as oAuthState from '../helpers/oauth-state.js'
|
||||
import logger from '../logger.js'
|
||||
|
||||
const closePageHtml = (origin) => `
|
||||
<!DOCTYPE html>
|
||||
|
|
@ -28,7 +27,7 @@ const closePageHtml = (origin) => `
|
|||
* @param {object} res
|
||||
* @param {Function} next
|
||||
*/
|
||||
module.exports = function callback(req, res, next) {
|
||||
export default function callback(req, res, next) {
|
||||
const { providerName } = req.params
|
||||
|
||||
const grant = req.session.grant || {}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
const oAuthState = require('../helpers/oauth-state')
|
||||
import * as oAuthState from '../helpers/oauth-state.js'
|
||||
|
||||
/**
|
||||
* Derived from `cors` npm package.
|
||||
|
|
@ -82,7 +82,7 @@ function getClientOrigin(base64EncodedState) {
|
|||
* @param {object} req
|
||||
* @param {object} res
|
||||
*/
|
||||
module.exports = function connect(req, res, next) {
|
||||
export default function connect(req, res, next) {
|
||||
const stateObj = oAuthState.generateState()
|
||||
|
||||
if (req.companion.options.server.oauthDomain) {
|
||||
|
|
@ -116,4 +116,5 @@ module.exports = function connect(req, res, next) {
|
|||
}
|
||||
encodeStateAndRedirect(req, res, stateObj)
|
||||
}
|
||||
module.exports.isOriginAllowed = isOriginAllowed
|
||||
|
||||
export { isOriginAllowed }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
const { respondWithError } = require('../provider/error')
|
||||
import { respondWithError } from '../provider/error.js'
|
||||
|
||||
async function deauthCallback({ body, companion, headers }, res, next) {
|
||||
export default async function deauthCallback(
|
||||
{ body, companion, headers },
|
||||
res,
|
||||
next,
|
||||
) {
|
||||
// we need the provider instance to decide status codes because
|
||||
// this endpoint does not cater to a uniform client.
|
||||
// It doesn't respond to Uppy client like other endpoints.
|
||||
|
|
@ -17,5 +21,3 @@ async function deauthCallback({ body, companion, headers }, res, next) {
|
|||
next(err)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = deauthCallback
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue