Browse Source

example: fix `custom-provider` example (#3854)

Antoine du Hamel 2 years ago
parent
commit
4347b9b906

+ 6 - 2
.eslintrc.js

@@ -122,7 +122,7 @@ module.exports = {
     'jsdoc/check-examples': 'off', // cannot yet be supported for ESLint 8, see https://github.com/eslint/eslint/issues/14745
     'jsdoc/check-param-names': ['warn'],
     'jsdoc/check-syntax': ['warn'],
-    'jsdoc/check-tag-names': 'error',
+    'jsdoc/check-tag-names': ['error', { jsxTags: true }],
     'jsdoc/check-types': 'error',
     'jsdoc/newline-after-description': 'error',
     'jsdoc/valid-types': 'error',
@@ -191,6 +191,7 @@ module.exports = {
         'e2e/clients/**/*.js',
         'examples/aws-presigned-url/*.js',
         'examples/bundled/*.js',
+        'examples/custom-provider/client/*.js',
         'private/dev/*.js',
         'private/release/*.js',
         'private/remark-lint-uppy/*.js',
@@ -249,6 +250,8 @@ module.exports = {
       },
       rules: {
         'import/named': 'off', // Disabled because that rule tries and fails to parse JSX dependencies.
+        'import/no-named-as-default': 'off', // Disabled because that rule tries and fails to parse JSX dependencies.
+        'import/no-named-as-default-member': 'off', // Disabled because that rule tries and fails to parse JSX dependencies.
         'no-restricted-globals': [
           'error',
           {
@@ -358,7 +361,8 @@ module.exports = {
       files: [
         'bin/**.js',
         'bin/**.mjs',
-        'examples/**/*.js',
+        'examples/**/*.config.js',
+        'examples/**/*.cjs',
         'packages/@uppy/companion/test/**/*.js',
         'test/**/*.js',
         'test/**/*.ts',

+ 0 - 4
examples/custom-provider/.gitignore

@@ -1,4 +0,0 @@
-uppy.min.css
-node_modules
-output/*
-!output/.empty

+ 25 - 0
examples/custom-provider/README.md

@@ -0,0 +1,25 @@
+# Uppy + Companion + Custom Provider Example
+
+This example uses @uppy/companion with a dummy custom provider.
+This serves as an illustration on how integrating custom providers would work
+
+## Run it
+
+**Note**: this example is using `fetch`, which is only available on Node.js 18+.
+
+First, you want to set up your environment variable. You can copy the content of
+`.env.example` and save it in a file named `.env`. You can modify in there all
+the information needed for the app to work that should not be committed
+(Google keys, Unsplash keys, etc.).
+
+```sh
+[ -f .env ] || cp .env.example .env
+```
+
+To run the example, from the root directory of this repo, run the following commands:
+
+```sh
+corepack yarn install
+corepack yarn build
+corepack yarn workspace @uppy-example/custom-provider start
+```

+ 0 - 14
examples/custom-provider/babel.config.js

@@ -1,14 +0,0 @@
-module.exports = (api) => {
-  api.env('test')
-  return {
-    presets: [
-      ['@babel/preset-env', {
-        modules: false,
-        loose: true,
-      }],
-    ],
-    plugins: [
-      ['@babel/plugin-transform-react-jsx', { pragma: 'h' }],
-    ].filter(Boolean),
-  }
-}

+ 14 - 11
examples/custom-provider/client/MyCustomProvider.js → examples/custom-provider/client/MyCustomProvider.jsx

@@ -1,9 +1,13 @@
-const { UIPlugin } = require('@uppy/core')
-const { Provider } = require('@uppy/companion-client')
-const { ProviderViews } = require('@uppy/provider-views')
-const { h } = require('preact')
+/** @jsx h */
 
-module.exports = class MyCustomProvider extends UIPlugin {
+import { UIPlugin } from '@uppy/core'
+import { Provider } from '@uppy/companion-client'
+import { ProviderViews } from '@uppy/provider-views'
+import { h } from 'preact'
+
+const defaultOptions = {}
+
+export default class MyCustomProvider extends UIPlugin {
   constructor (uppy, opts) {
     super(uppy, opts)
     this.type = 'acquirer'
@@ -28,15 +32,14 @@ module.exports = class MyCustomProvider extends UIPlugin {
         pluginNameMyUnsplash: 'MyUnsplash',
       },
     }
+
+    // merge default options with the ones set by user
+    this.opts = { ...defaultOptions, ...opts }
+
     this.i18nInit()
-    this.title = this.i18n('MyUnsplash')
+    this.title = this.i18n('pluginNameMyUnsplash')
 
     this.files = []
-    this.onFirstRender = this.onFirstRender.bind(this)
-    this.render = this.render.bind(this)
-
-    // merge default options with the ones set by user
-    this.opts = { ...opts }
   }
 
   install () {

+ 8 - 5
examples/custom-provider/client/main.js

@@ -1,8 +1,11 @@
-const Uppy = require('@uppy/core')
-const GoogleDrive = require('@uppy/google-drive')
-const Tus = require('@uppy/tus')
-const Dashboard = require('@uppy/dashboard')
-const MyCustomProvider = require('./MyCustomProvider')
+import Uppy from '@uppy/core'
+import GoogleDrive from '@uppy/google-drive'
+import Tus from '@uppy/tus'
+import Dashboard from '@uppy/dashboard'
+import MyCustomProvider from './MyCustomProvider.jsx'
+
+import '@uppy/core/dist/style.css'
+import '@uppy/dashboard/dist/style.css'
 
 const uppy = new Uppy({
   debug: true,

+ 1 - 2
examples/custom-provider/index.html

@@ -4,9 +4,8 @@
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Uppy Custom provider Example</title>
-    <link href="uppy.min.css" rel="stylesheet">
   </head>
   <body>
-    <script src="bundle.js"></script>
+    <script src="./client/main.js" type="module"></script>
   </body>
 </html>

+ 0 - 0
examples/custom-provider/output/.empty


+ 13 - 9
examples/custom-provider/package.json

@@ -1,28 +1,32 @@
 {
   "name": "@uppy-example/custom-provider",
   "version": "0.0.0",
+  "type": "module",
   "dependencies": {
-    "@babel/core": "^7.2.2",
     "@uppy/companion-client": "workspace:*",
     "@uppy/core": "workspace:*",
     "@uppy/dashboard": "workspace:*",
     "@uppy/google-drive": "workspace:*",
     "@uppy/provider-views": "workspace:*",
     "@uppy/tus": "workspace:*",
-    "babelify": "^10.0.0",
+    "preact": "^10.5.13"
+  },
+  "engines": {
+    "node": ">=18.0.0"
+  },
+  "devDependencies": {
+    "@uppy/companion": "workspace:*",
     "body-parser": "^1.18.2",
-    "budo": "^11.3.2",
+    "dotenv": "^16.0.1",
     "express": "^4.16.2",
     "express-session": "^1.15.6",
     "npm-run-all": "^4.1.2",
-    "preact": "^10.5.13",
-    "request": "2.88.2"
+    "vite": "^2.7.1"
   },
   "private": true,
   "scripts": {
-    "copy": "cp ../../packages/uppy/dist/uppy.min.css .",
-    "start": "npm-run-all --serial copy --parallel start:*",
-    "start:client": "budo client/main.js:bundle.js -- -t babelify",
-    "start:server": "node server/index.js"
+    "start": "npm-run-all --parallel start:server start:client",
+    "start:client": "vite",
+    "start:server": "node server/index.cjs"
   }
 }

+ 0 - 21
examples/custom-provider/readme.md

@@ -1,21 +0,0 @@
-# Uppy + Companion + Custom Provider  Example
-
-This example uses @uppy/companion with a dummy custom provider.
-This serves as an illustration on how integrating custom providers would work
-
-## Run it
-
-To run this example, make sure you've correctly installed the **repository root**:
-
-```bash
-npm install
-npm run build
-```
-
-That will also install the dependencies for this example.
-
-Then, again in the **repository root**, start this example by doing:
-
-```bash
-npm run example custom-provider
-```

+ 85 - 0
examples/custom-provider/server/CustomProvider.cjs

@@ -0,0 +1,85 @@
+const { Readable } = require('node:stream')
+
+const BASE_URL = 'https://api.unsplash.com'
+
+function adaptData (res) {
+  const data = {
+    username: null,
+    items: [],
+    nextPagePath: null,
+  }
+
+  const items = res
+  items.forEach((item) => {
+    const isFolder = !!item.published_at
+    data.items.push({
+      isFolder,
+      icon: isFolder ? item.cover_photo.urls.thumb : item.urls.thumb,
+      name: item.title || item.description,
+      mimeType: isFolder ? null : 'image/jpeg',
+      id: item.id,
+      thumbnail: isFolder ? item.cover_photo.urls.thumb : item.urls.thumb,
+      requestPath: item.id,
+      modifiedDate: item.updated_at,
+      size: null,
+    })
+  })
+
+  return data
+}
+
+/**
+ * an example of a custom provider module. It implements @uppy/companion's Provider interface
+ */
+class MyCustomProvider {
+  static version = 2
+
+  authProvider = 'myunsplash'
+
+  // eslint-disable-next-line class-methods-use-this
+  async list ({ token, directory }) {
+    const path = directory ? `/${directory}/photos` : ''
+
+    const resp = await fetch(`${BASE_URL}/collections${path}`, {
+      headers:{
+        Authorization: `Bearer ${token}`,
+      },
+    })
+    if (!resp.ok) {
+      throw new Error(`Errornous HTTP response (${resp.status} ${resp.statusText})`)
+    }
+    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: {
+        Authorization: `Bearer ${token}`,
+      },
+    })
+
+    if (!resp.ok) {
+      throw new Error(`Errornous HTTP response (${resp.status} ${resp.statusText})`)
+    }
+    return { stream: Readable.fromWeb(resp.body) }
+  }
+
+  // eslint-disable-next-line class-methods-use-this
+  async size ({ id, token }) {
+    const resp = await fetch(`${BASE_URL}/photos/${id}`, {
+      headers: {
+        Authorization: `Bearer ${token}`,
+      },
+    })
+
+    if (!resp.ok) {
+      throw new Error(`Errornous HTTP response (${resp.status} ${resp.statusText})`)
+    }
+
+    const { size } = await resp.json()
+    return size
+  }
+}
+
+module.exports = MyCustomProvider

+ 0 - 122
examples/custom-provider/server/customprovider.js

@@ -1,122 +0,0 @@
-const request = require('request')
-
-const BASE_URL = 'https://api.unsplash.com'
-
-function adaptData (res) {
-  const data = {
-    username: null,
-    items: [],
-    nextPagePath: null,
-  }
-
-  const items = res
-  items.forEach((item) => {
-    const isFolder = !!item.published_at
-    data.items.push({
-      isFolder,
-      icon: isFolder ? item.cover_photo.urls.thumb : item.urls.thumb,
-      name: item.title || item.description,
-      mimeType: isFolder ? null : 'image/jpeg',
-      id: item.id,
-      thumbnail: isFolder ? item.cover_photo.urls.thumb : item.urls.thumb,
-      requestPath: item.id,
-      modifiedDate: item.updated_at,
-      size: null,
-    })
-  })
-
-  return data
-}
-
-/**
- * an example of a custom provider module. It implements @uppy/companion's Provider interface
- */
-class MyCustomProvider {
-  static version = 2
-
-  constructor () {
-    this.authProvider = 'myunsplash'
-  }
-
-  // eslint-disable-next-line class-methods-use-this
-  async list ({ token, directory }) {
-    const path = directory ? `/${directory}/photos` : ''
-    const options = {
-      url: `${BASE_URL}/collections${path}`,
-      method: 'GET',
-      json: true,
-      headers: {
-        Authorization: `Bearer ${token}`,
-      },
-    }
-
-    return new Promise((resolve, reject) => (
-      request(options, (err, resp, body) => {
-        if (err) {
-          console.log(err)
-          reject(err)
-          return
-        }
-
-        resolve(adaptData(body))
-      })))
-  }
-
-  // eslint-disable-next-line class-methods-use-this
-  async download ({ id, token }) {
-    const options = {
-      url: `${BASE_URL}/photos/${id}`,
-      method: 'GET',
-      json: true,
-      headers: {
-        Authorization: `Bearer ${token}`,
-      },
-    }
-
-    const resp = await new Promise((resolve, reject) => {
-      const req = request(options)
-        .on('response', (response) => {
-          // Don't allow any more data to flow yet.
-          // https://github.com/request/request/issues/1990#issuecomment-184712275
-          response.pause()
-
-          if (resp.statusCode !== 200) {
-            req.abort() // Or we will leak memory
-            reject(new Error(`HTTP response ${resp.statusCode}`))
-            return
-          }
-
-          resolve(response)
-        })
-        .on('error', reject)
-    })
-
-    // The returned stream will be consumed and uploaded from the current position
-    return { stream: resp }
-  }
-
-  // eslint-disable-next-line class-methods-use-this
-  async size ({ id, token }) {
-    const options = {
-      url: `${BASE_URL}/photos/${id}`,
-      method: 'GET',
-      json: true,
-      headers: {
-        Authorization: `Bearer ${token}`,
-      },
-    }
-
-    return new Promise((resolve, reject) => (
-      request(options, (err, resp, body) => {
-        if (err) {
-          console.log(err)
-          reject(err)
-          return
-        }
-
-        resolve(body.size)
-      })))
-  }
-}
-
-module.exports = MyCustomProvider

+ 13 - 8
examples/custom-provider/server/index.js → examples/custom-provider/server/index.cjs

@@ -1,10 +1,15 @@
+const { mkdtempSync } = require('node:fs')
+const os = require('node:os')
+const path = require('node:path')
+
+require('dotenv').config({ path: path.join(__dirname, '..', '..', '..', '.env') })
 const express = require('express')
 // the ../../../packages is just to use the local version
 // instead of the npm version—in a real app use `require('@uppy/companion')`
 const bodyParser = require('body-parser')
 const session = require('express-session')
-const uppy = require('../../../packages/@uppy/companion')
-const MyCustomProvider = require('./customprovider')
+const uppy = require('@uppy/companion')
+const MyCustomProvider = require('./CustomProvider.cjs')
 
 const app = express()
 
@@ -29,8 +34,8 @@ const ACCESS_URL = 'https://unsplash.com/oauth/token'
 const uppyOptions = {
   providerOptions: {
     drive: {
-      key: 'your google drive key',
-      secret: 'your google drive secret',
+      key: process.env.COMPANION_GOOGLE_KEY,
+      secret: process.env.COMPANION_GOOGLE_SECRET,
     },
   },
   customProviders: {
@@ -40,8 +45,8 @@ const uppyOptions = {
         authorize_url: AUTHORIZE_URL,
         access_url: ACCESS_URL,
         oauth: 2,
-        key: 'your unsplash key here',
-        secret: 'your unsplash secret here',
+        key: process.env.COMPANION_UNSPLASH_KEY,
+        secret: process.env.COMPANION_UNSPLASH_SECRET,
       },
       // you provider class/module:
       module: MyCustomProvider,
@@ -51,12 +56,12 @@ const uppyOptions = {
     host: 'localhost:3020',
     protocol: 'http',
   },
-  filePath: './output',
+  filePath: mkdtempSync(path.join(os.tmpdir(), 'companion-')),
   secret: 'some-secret',
   debug: true,
 }
 
-app.use(uppy.app(uppyOptions))
+app.use(uppy.app(uppyOptions).app)
 
 // handle 404
 app.use((req, res) => {

+ 11 - 5
yarn.lock

@@ -9669,21 +9669,20 @@ __metadata:
   version: 0.0.0-use.local
   resolution: "@uppy-example/custom-provider@workspace:examples/custom-provider"
   dependencies:
-    "@babel/core": ^7.2.2
+    "@uppy/companion": "workspace:*"
     "@uppy/companion-client": "workspace:*"
     "@uppy/core": "workspace:*"
     "@uppy/dashboard": "workspace:*"
     "@uppy/google-drive": "workspace:*"
     "@uppy/provider-views": "workspace:*"
     "@uppy/tus": "workspace:*"
-    babelify: ^10.0.0
     body-parser: ^1.18.2
-    budo: ^11.3.2
+    dotenv: ^16.0.1
     express: ^4.16.2
     express-session: ^1.15.6
     npm-run-all: ^4.1.2
     preact: ^10.5.13
-    request: 2.88.2
+    vite: ^2.7.1
   languageName: unknown
   linkType: soft
 
@@ -10019,7 +10018,7 @@ __metadata:
   languageName: unknown
   linkType: soft
 
-"@uppy/companion@workspace:^, @uppy/companion@workspace:packages/@uppy/companion":
+"@uppy/companion@workspace:*, @uppy/companion@workspace:^, @uppy/companion@workspace:packages/@uppy/companion":
   version: 0.0.0-use.local
   resolution: "@uppy/companion@workspace:packages/@uppy/companion"
   dependencies:
@@ -17312,6 +17311,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"dotenv@npm:^16.0.1":
+  version: 16.0.1
+  resolution: "dotenv@npm:16.0.1"
+  checksum: f459ffce07b977b7f15d8cc4ee69cdff77d4dd8c5dc8c85d2d485ee84655352c2415f9dd09d42b5b5985ced3be186130871b34e2f3e2569ebc72fbc2e8096792
+  languageName: node
+  linkType: hard
+
 "dotenv@npm:^7.0.0":
   version: 7.0.0
   resolution: "dotenv@npm:7.0.0"