mirror of
https://github.com/unjs/unstorage.git
synced 2025-12-08 21:26:09 +00:00
feat: add uploadthing driver (#390)
Co-authored-by: Pooya Parsa <pooya@pi0.io>
This commit is contained in:
parent
ce9685e8f0
commit
e049ce65d3
@ -6,3 +6,5 @@ VITE_VERCEL_BLOB_READ_WRITE_TOKEN=
|
||||
VITE_CLOUDFLARE_ACC_ID=
|
||||
VITE_CLOUDFLARE_KV_NS_ID=
|
||||
VITE_CLOUDFLARE_TOKEN=
|
||||
|
||||
VITE_UPLOADTHING_TOKEN=
|
||||
|
||||
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@ -38,6 +38,7 @@ jobs:
|
||||
VITE_CLOUDFLARE_ACC_ID: ${{ secrets.VITE_CLOUDFLARE_ACC_ID }}
|
||||
VITE_CLOUDFLARE_KV_NS_ID: ${{ secrets.VITE_CLOUDFLARE_KV_NS_ID }}
|
||||
VITE_CLOUDFLARE_TOKEN: ${{ secrets.VITE_CLOUDFLARE_TOKEN }}
|
||||
VITE_UPLOADTHING_TOKEN: ${{ secrets.VITE_UPLOADTHING_TOKEN }}
|
||||
- uses: codecov/codecov-action@v5
|
||||
- name: nightly release
|
||||
if: |
|
||||
|
||||
38
docs/2.drivers/uploadthing.md
Normal file
38
docs/2.drivers/uploadthing.md
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
icon: qlementine-icons:cloud-16
|
||||
---
|
||||
|
||||
# UploadThing
|
||||
|
||||
> Store data using UploadThing.
|
||||
|
||||
::note{to="https://uploadthing.com/"}
|
||||
Learn more about UploadThing.
|
||||
::
|
||||
|
||||
::warning
|
||||
UploadThing support is currently experimental!
|
||||
<br>
|
||||
There is a known issue that same key, if deleted cannot be used again [tracker issue](https://github.com/pingdotgg/uploadthing/issues/948).
|
||||
::
|
||||
|
||||
## Usage
|
||||
|
||||
To use, you will need to install `uploadthing` dependency in your project:
|
||||
|
||||
:pm-install{name="uploadthing"}
|
||||
|
||||
```js
|
||||
import { createStorage } from "unstorage";
|
||||
import uploadthingDriver from "unstorage/drivers/uploadthing";
|
||||
|
||||
const storage = createStorage({
|
||||
driver: uploadthingDriver({
|
||||
// token: "<your token>", // UPLOADTHING_SECRET environment variable will be used if not provided.
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `token`: Your UploadThing API key. Will be automatically inferred from the `UPLOADTHING_SECRET` environment variable if not provided.
|
||||
@ -100,6 +100,7 @@
|
||||
"types-cloudflare-worker": "^1.2.0",
|
||||
"typescript": "^5.7.2",
|
||||
"unbuild": "^3.0.1",
|
||||
"uploadthing": "^7.4.1",
|
||||
"vite": "^6.0.3",
|
||||
"vitest": "^2.1.8",
|
||||
"wrangler": "^3.97.0"
|
||||
@ -121,7 +122,8 @@
|
||||
"aws4fetch": "^1.0.20",
|
||||
"db0": ">=0.2.1",
|
||||
"idb-keyval": "^6.2.1",
|
||||
"ioredis": "^5.4.1"
|
||||
"ioredis": "^5.4.1",
|
||||
"uploadthing": "^7.4.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@azure/app-configuration": {
|
||||
@ -174,6 +176,9 @@
|
||||
},
|
||||
"ioredis": {
|
||||
"optional": true
|
||||
},
|
||||
"uploadthing": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"packageManager": "pnpm@9.15.0"
|
||||
|
||||
100
pnpm-lock.yaml
generated
100
pnpm-lock.yaml
generated
@ -171,6 +171,9 @@ importers:
|
||||
unbuild:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1(typescript@5.7.2)
|
||||
uploadthing:
|
||||
specifier: ^7.4.1
|
||||
version: 7.4.1(express@4.21.2)(h3@1.13.0)
|
||||
vite:
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.3(@types/node@22.10.2)(jiti@2.4.1)(yaml@2.6.1)
|
||||
@ -439,6 +442,11 @@ packages:
|
||||
'@deno/kv@0.8.4':
|
||||
resolution: {integrity: sha512-5q2izU1tp6wv8rDIwMb6GXe/B+aO/sjAjRAOIigEtX+qOiTLsPE++ibJbfafVb0LmjEdlA18Kpfo23fln73OtQ==}
|
||||
|
||||
'@effect/platform@0.70.7':
|
||||
resolution: {integrity: sha512-TbNwj/mOJhycPygbmicGBS7CNtv5Z8WVheRbLUdP3oPAe/nbSOJVLc8ZPvOejhquF/1vJMKuqY5MWfkcBpvi/g==}
|
||||
peerDependencies:
|
||||
effect: ^3.11.5
|
||||
|
||||
'@electric-sql/pglite@0.2.15':
|
||||
resolution: {integrity: sha512-Jiq31Dnk+rg8rMhcSxs4lQvHTyizNo5b269c1gCC3ldQ0sCLrNVPGzy+KnmonKy1ZArTUuXZf23/UamzFMKVaA==}
|
||||
|
||||
@ -1280,6 +1288,9 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@standard-schema/spec@1.0.0-beta.3':
|
||||
resolution: {integrity: sha512-0ifF3BjA1E8SY9C+nUew8RefNOIq0cDlYALPty4rhUm8Rrl6tCM8hBT4bhGhx7I7iXD0uAgt50lgo8dD73ACMw==}
|
||||
|
||||
'@trysound/sax@0.2.0':
|
||||
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
@ -1391,6 +1402,12 @@ packages:
|
||||
resolution: {integrity: sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@uploadthing/mime-types@0.3.2':
|
||||
resolution: {integrity: sha512-WP/K75S/649lM0GUcd9jq4RjeTIc/0bO2UmLx4+usTSNy/x0K8gV0JdLWeUUbmTQtJoHd4ZTSvAdG7ZQgcmXvA==}
|
||||
|
||||
'@uploadthing/shared@7.1.3':
|
||||
resolution: {integrity: sha512-JlYz/JLZPrMAZRg7YPDUICodvIXLW9xS32aErqDvD76juq6nPRwFdwG5V089CY2kS5Ju9I0rGAu94hbJFqd9qQ==}
|
||||
|
||||
'@upstash/redis@1.34.3':
|
||||
resolution: {integrity: sha512-VT25TyODGy/8ljl7GADnJoMmtmJ1F8d84UXfGonRRF8fWYJz7+2J6GzW+a6ETGtk4OyuRTt7FRSvFG5GvrfSdQ==}
|
||||
|
||||
@ -2074,6 +2091,9 @@ packages:
|
||||
ee-first@1.1.1:
|
||||
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||
|
||||
effect@3.11.5:
|
||||
resolution: {integrity: sha512-oSzaR/S/2A/qDTnDqMWxQUNSjCG2sRLB4NEvTu+l9RqE122MTgKXOWzw0x4MHsdovRTzAihfkpgBj2aLFnH2+w==}
|
||||
|
||||
electron-to-chromium@1.5.73:
|
||||
resolution: {integrity: sha512-8wGNxG9tAG5KhGd3eeA0o6ixhiNdgr0DcHWm85XPCphwZgD1lIEoi6t3VERayWao7SF7AAZTw6oARGJeVjH8Kg==}
|
||||
|
||||
@ -2270,6 +2290,10 @@ packages:
|
||||
resolution: {integrity: sha512-YEboHE5VfopUclOck7LncgIqskAqnv4q0EWbYCaxKKjAvO93c+TJIaBuGy8CBFdbg9nKdpN3AuPRwVBJ4k7NrQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
fast-check@3.23.2:
|
||||
resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
||||
fast-deep-equal@3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
|
||||
@ -2335,6 +2359,9 @@ packages:
|
||||
resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
find-my-way-ts@0.1.5:
|
||||
resolution: {integrity: sha512-4GOTMrpGQVzsCH2ruUn2vmwzV/02zF4q+ybhCIrw/Rkt3L8KWcycdC6aJMctJzwN4fXD4SD5F/4B9Sksh5rE0A==}
|
||||
|
||||
find-up@4.1.0:
|
||||
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
|
||||
engines: {node: '>=8'}
|
||||
@ -3242,6 +3269,9 @@ packages:
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
multipasta@0.2.5:
|
||||
resolution: {integrity: sha512-c8eMDb1WwZcE02WVjHoOmUVk7fnKU/RmUcosHACglrWAuPQsEJv+E8430sXj6jNc1jHw0zrS16aCjQh4BcEb4A==}
|
||||
|
||||
multistream@2.1.1:
|
||||
resolution: {integrity: sha512-xasv76hl6nr1dEy3lPvy7Ej7K/Lx3O/FCvwge8PeVJpciPPoNCbaANcNiBug3IpdvTveZUcAV0DJzdnUDMesNQ==}
|
||||
|
||||
@ -3732,6 +3762,9 @@ packages:
|
||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
pure-rand@6.1.0:
|
||||
resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==}
|
||||
|
||||
qs@6.13.0:
|
||||
resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
|
||||
engines: {node: '>=0.6'}
|
||||
@ -4052,6 +4085,9 @@ packages:
|
||||
sprintf-js@1.1.3:
|
||||
resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
|
||||
|
||||
sqids@0.3.0:
|
||||
resolution: {integrity: sha512-lOQK1ucVg+W6n3FhRwwSeUijxe93b51Bfz5PMRMihVf1iVkl82ePQG7V5vwrhzB11v0NtsR25PSZRGiSomJaJw==}
|
||||
|
||||
sqlstring@2.3.3:
|
||||
resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@ -4387,6 +4423,27 @@ packages:
|
||||
peerDependencies:
|
||||
browserslist: '>= 4.21.0'
|
||||
|
||||
uploadthing@7.4.1:
|
||||
resolution: {integrity: sha512-an/ENGUJ06Rg9eI2/bWOUsm+6iDlufDRggUsw6HR4mqhNa/aqLHj5KrWP1CuVHP70fXMCsSM+BgVm00y5wt6wg==}
|
||||
engines: {node: '>=18.13.0'}
|
||||
peerDependencies:
|
||||
express: '*'
|
||||
fastify: '*'
|
||||
h3: '*'
|
||||
next: '*'
|
||||
tailwindcss: '*'
|
||||
peerDependenciesMeta:
|
||||
express:
|
||||
optional: true
|
||||
fastify:
|
||||
optional: true
|
||||
h3:
|
||||
optional: true
|
||||
next:
|
||||
optional: true
|
||||
tailwindcss:
|
||||
optional: true
|
||||
|
||||
uqr@0.1.2:
|
||||
resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==}
|
||||
|
||||
@ -5096,6 +5153,12 @@ snapshots:
|
||||
'@deno/kv-linux-x64-gnu': 0.8.4
|
||||
'@deno/kv-win32-x64-msvc': 0.8.4
|
||||
|
||||
'@effect/platform@0.70.7(effect@3.11.5)':
|
||||
dependencies:
|
||||
effect: 3.11.5
|
||||
find-my-way-ts: 0.1.5
|
||||
multipasta: 0.2.5
|
||||
|
||||
'@electric-sql/pglite@0.2.15': {}
|
||||
|
||||
'@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)':
|
||||
@ -5660,6 +5723,8 @@ snapshots:
|
||||
'@rollup/rollup-win32-x64-msvc@4.28.1':
|
||||
optional: true
|
||||
|
||||
'@standard-schema/spec@1.0.0-beta.3': {}
|
||||
|
||||
'@trysound/sax@0.2.0': {}
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
@ -5803,6 +5868,14 @@ snapshots:
|
||||
'@typescript-eslint/types': 8.18.0
|
||||
eslint-visitor-keys: 4.2.0
|
||||
|
||||
'@uploadthing/mime-types@0.3.2': {}
|
||||
|
||||
'@uploadthing/shared@7.1.3':
|
||||
dependencies:
|
||||
'@uploadthing/mime-types': 0.3.2
|
||||
effect: 3.11.5
|
||||
sqids: 0.3.0
|
||||
|
||||
'@upstash/redis@1.34.3':
|
||||
dependencies:
|
||||
crypto-js: 4.2.0
|
||||
@ -6574,6 +6647,10 @@ snapshots:
|
||||
|
||||
ee-first@1.1.1: {}
|
||||
|
||||
effect@3.11.5:
|
||||
dependencies:
|
||||
fast-check: 3.23.2
|
||||
|
||||
electron-to-chromium@1.5.73: {}
|
||||
|
||||
emoji-regex@8.0.0: {}
|
||||
@ -6941,6 +7018,10 @@ snapshots:
|
||||
|
||||
fake-indexeddb@6.0.0: {}
|
||||
|
||||
fast-check@3.23.2:
|
||||
dependencies:
|
||||
pure-rand: 6.1.0
|
||||
|
||||
fast-deep-equal@3.1.3: {}
|
||||
|
||||
fast-fifo@1.3.2: {}
|
||||
@ -7014,6 +7095,8 @@ snapshots:
|
||||
make-dir: 3.1.0
|
||||
pkg-dir: 4.2.0
|
||||
|
||||
find-my-way-ts@0.1.5: {}
|
||||
|
||||
find-up@4.1.0:
|
||||
dependencies:
|
||||
locate-path: 5.0.0
|
||||
@ -7962,6 +8045,8 @@ snapshots:
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
multipasta@0.2.5: {}
|
||||
|
||||
multistream@2.1.1:
|
||||
dependencies:
|
||||
inherits: 2.0.4
|
||||
@ -8432,6 +8517,8 @@ snapshots:
|
||||
|
||||
punycode@2.3.1: {}
|
||||
|
||||
pure-rand@6.1.0: {}
|
||||
|
||||
qs@6.13.0:
|
||||
dependencies:
|
||||
side-channel: 1.1.0
|
||||
@ -8803,6 +8890,8 @@ snapshots:
|
||||
|
||||
sprintf-js@1.1.3: {}
|
||||
|
||||
sqids@0.3.0: {}
|
||||
|
||||
sqlstring@2.3.3: {}
|
||||
|
||||
stack-trace@0.0.10: {}
|
||||
@ -9210,6 +9299,17 @@ snapshots:
|
||||
escalade: 3.2.0
|
||||
picocolors: 1.1.1
|
||||
|
||||
uploadthing@7.4.1(express@4.21.2)(h3@1.13.0):
|
||||
dependencies:
|
||||
'@effect/platform': 0.70.7(effect@3.11.5)
|
||||
'@standard-schema/spec': 1.0.0-beta.3
|
||||
'@uploadthing/mime-types': 0.3.2
|
||||
'@uploadthing/shared': 7.1.3
|
||||
effect: 3.11.5
|
||||
optionalDependencies:
|
||||
express: 4.21.2
|
||||
h3: 1.13.0
|
||||
|
||||
uqr@0.1.2: {}
|
||||
|
||||
uri-js@4.4.1:
|
||||
|
||||
@ -27,11 +27,12 @@ import type { PlanetscaleDriverOptions as PlanetscaleOptions } from "unstorage/d
|
||||
import type { RedisOptions as RedisOptions } from "unstorage/drivers/redis";
|
||||
import type { S3DriverOptions as S3Options } from "unstorage/drivers/s3";
|
||||
import type { SessionStorageOptions as SessionStorageOptions } from "unstorage/drivers/session-storage";
|
||||
import type { UploadThingOptions as UploadthingOptions } from "unstorage/drivers/uploadthing";
|
||||
import type { UpstashOptions as UpstashOptions } from "unstorage/drivers/upstash";
|
||||
import type { VercelBlobOptions as VercelBlobOptions } from "unstorage/drivers/vercel-blob";
|
||||
import type { VercelKVOptions as VercelKVOptions } from "unstorage/drivers/vercel-kv";
|
||||
|
||||
export type BuiltinDriverName = "azure-app-configuration" | "azureAppConfiguration" | "azure-cosmos" | "azureCosmos" | "azure-key-vault" | "azureKeyVault" | "azure-storage-blob" | "azureStorageBlob" | "azure-storage-table" | "azureStorageTable" | "capacitor-preferences" | "capacitorPreferences" | "cloudflare-kv-binding" | "cloudflareKVBinding" | "cloudflare-kv-http" | "cloudflareKVHttp" | "cloudflare-r2-binding" | "cloudflareR2Binding" | "db0" | "deno-kv-node" | "denoKVNode" | "deno-kv" | "denoKV" | "fs-lite" | "fsLite" | "fs" | "github" | "http" | "indexedb" | "localstorage" | "lru-cache" | "lruCache" | "memory" | "mongodb" | "netlify-blobs" | "netlifyBlobs" | "null" | "overlay" | "planetscale" | "redis" | "s3" | "session-storage" | "sessionStorage" | "upstash" | "vercel-blob" | "vercelBlob" | "vercel-kv" | "vercelKV";
|
||||
export type BuiltinDriverName = "azure-app-configuration" | "azureAppConfiguration" | "azure-cosmos" | "azureCosmos" | "azure-key-vault" | "azureKeyVault" | "azure-storage-blob" | "azureStorageBlob" | "azure-storage-table" | "azureStorageTable" | "capacitor-preferences" | "capacitorPreferences" | "cloudflare-kv-binding" | "cloudflareKVBinding" | "cloudflare-kv-http" | "cloudflareKVHttp" | "cloudflare-r2-binding" | "cloudflareR2Binding" | "db0" | "deno-kv-node" | "denoKVNode" | "deno-kv" | "denoKV" | "fs-lite" | "fsLite" | "fs" | "github" | "http" | "indexedb" | "localstorage" | "lru-cache" | "lruCache" | "memory" | "mongodb" | "netlify-blobs" | "netlifyBlobs" | "null" | "overlay" | "planetscale" | "redis" | "s3" | "session-storage" | "sessionStorage" | "uploadthing" | "upstash" | "vercel-blob" | "vercelBlob" | "vercel-kv" | "vercelKV";
|
||||
|
||||
export type BuiltinDriverOptions = {
|
||||
"azure-app-configuration": AzureAppConfigurationOptions;
|
||||
@ -75,6 +76,7 @@ export type BuiltinDriverOptions = {
|
||||
"s3": S3Options;
|
||||
"session-storage": SessionStorageOptions;
|
||||
"sessionStorage": SessionStorageOptions;
|
||||
"uploadthing": UploadthingOptions;
|
||||
"upstash": UpstashOptions;
|
||||
"vercel-blob": VercelBlobOptions;
|
||||
"vercelBlob": VercelBlobOptions;
|
||||
@ -126,6 +128,7 @@ export const builtinDrivers = {
|
||||
"s3": "unstorage/drivers/s3",
|
||||
"session-storage": "unstorage/drivers/session-storage",
|
||||
"sessionStorage": "unstorage/drivers/session-storage",
|
||||
"uploadthing": "unstorage/drivers/uploadthing",
|
||||
"upstash": "unstorage/drivers/upstash",
|
||||
"vercel-blob": "unstorage/drivers/vercel-blob",
|
||||
"vercelBlob": "unstorage/drivers/vercel-blob",
|
||||
|
||||
104
src/drivers/uploadthing.ts
Normal file
104
src/drivers/uploadthing.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { defineDriver, normalizeKey } from "./utils";
|
||||
import { UTApi } from "uploadthing/server";
|
||||
|
||||
// Reference: https://docs.uploadthing.com
|
||||
|
||||
type UTApiOptions = Omit<
|
||||
Exclude<ConstructorParameters<typeof UTApi>[0], undefined>,
|
||||
"defaultKeyType"
|
||||
>;
|
||||
|
||||
type FileEsque = Parameters<UTApi["uploadFiles"]>[0][0];
|
||||
|
||||
export interface UploadThingOptions extends UTApiOptions {
|
||||
/** base key to add to keys */
|
||||
base?: string;
|
||||
}
|
||||
|
||||
const DRIVER_NAME = "uploadthing";
|
||||
|
||||
export default defineDriver<UploadThingOptions, UTApi>((opts = {}) => {
|
||||
let client: UTApi;
|
||||
|
||||
const base = opts.base ? normalizeKey(opts.base) : "";
|
||||
const r = (key: string) => (base ? `${base}:${key}` : key);
|
||||
|
||||
const getClient = () => {
|
||||
return (client ??= new UTApi({
|
||||
...opts,
|
||||
defaultKeyType: "customId",
|
||||
}));
|
||||
};
|
||||
|
||||
const getKeys = async (base: string) => {
|
||||
const client = getClient();
|
||||
const { files } = await client.listFiles({});
|
||||
return files
|
||||
.map((file) => file.customId)
|
||||
.filter((k) => k && k.startsWith(base)) as string[];
|
||||
};
|
||||
|
||||
const toFile = (key: string, value: BlobPart) => {
|
||||
return Object.assign(new Blob([value]), <FileEsque>{
|
||||
name: key,
|
||||
customId: key,
|
||||
}) satisfies FileEsque;
|
||||
};
|
||||
|
||||
return {
|
||||
name: DRIVER_NAME,
|
||||
getInstance() {
|
||||
return getClient();
|
||||
},
|
||||
getKeys(base) {
|
||||
return getKeys(r(base));
|
||||
},
|
||||
async hasItem(key) {
|
||||
const client = getClient();
|
||||
const res = await client.getFileUrls(r(key));
|
||||
return res.data.length > 0;
|
||||
},
|
||||
async getItem(key) {
|
||||
const client = getClient();
|
||||
const url = await client
|
||||
.getFileUrls(r(key))
|
||||
.then((res) => res.data[0]?.url);
|
||||
if (!url) return null;
|
||||
return fetch(url).then((res) => res.text());
|
||||
},
|
||||
async getItemRaw(key) {
|
||||
const client = getClient();
|
||||
const url = await client
|
||||
.getFileUrls(r(key))
|
||||
.then((res) => res.data[0]?.url);
|
||||
if (!url) return null;
|
||||
return fetch(url).then((res) => res.arrayBuffer());
|
||||
},
|
||||
async setItem(key, value) {
|
||||
const client = getClient();
|
||||
await client.uploadFiles(toFile(r(key), value));
|
||||
},
|
||||
async setItemRaw(key, value) {
|
||||
const client = getClient();
|
||||
await client.uploadFiles(toFile(r(key), value));
|
||||
},
|
||||
async setItems(items) {
|
||||
const client = getClient();
|
||||
await client.uploadFiles(
|
||||
items.map((item) => toFile(r(item.key), item.value))
|
||||
);
|
||||
},
|
||||
async removeItem(key) {
|
||||
const client = getClient();
|
||||
await client.deleteFiles([r(key)]);
|
||||
},
|
||||
async clear(base) {
|
||||
const client = getClient();
|
||||
const keys = await getKeys(r(base));
|
||||
await client.deleteFiles(keys);
|
||||
},
|
||||
// getMeta(key, opts) {
|
||||
// // TODO: We don't currently have an endpoint to fetch metadata, but it does exist
|
||||
// },
|
||||
};
|
||||
});
|
||||
14
test/drivers/uploadthing.test.ts
Normal file
14
test/drivers/uploadthing.test.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { describe } from "vitest";
|
||||
import driver from "../../src/drivers/uploadthing";
|
||||
import { testDriver } from "./utils";
|
||||
|
||||
const utfsToken = process.env.VITE_UPLOADTHING_TOKEN;
|
||||
|
||||
describe.skipIf(!utfsToken)("drivers: uploadthing", { timeout: 30e3 }, () => {
|
||||
process.env.UPLOADTHING_TOKEN = utfsToken;
|
||||
testDriver({
|
||||
driver: driver({
|
||||
base: Math.round(Math.random() * 1_000_000).toString(16),
|
||||
}),
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user