@geenius/adapters 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -42
- package/package.json +23 -4
- package/packages/convex/README.md +1 -1
- package/packages/convex/dist/index.cjs +300 -0
- package/packages/convex/dist/index.cjs.map +1 -0
- package/packages/convex/dist/index.d.cts +231 -0
- package/packages/convex/dist/index.d.ts +231 -0
- package/packages/convex/dist/index.js +263 -0
- package/packages/convex/dist/index.js.map +1 -0
- package/packages/react/README.md +1 -1
- package/packages/react/dist/index.d.mts +106 -0
- package/packages/react/dist/index.d.ts +106 -0
- package/packages/react/dist/index.js +611 -0
- package/packages/react/dist/index.js.map +1 -0
- package/packages/react/dist/index.mjs +570 -0
- package/packages/react/dist/index.mjs.map +1 -0
- package/packages/react-css/README.md +1 -1
- package/packages/react-css/dist/index.cjs +515 -0
- package/packages/react-css/dist/index.cjs.map +1 -0
- package/packages/react-css/dist/index.d.cts +105 -0
- package/packages/react-css/dist/index.d.ts +105 -0
- package/packages/react-css/dist/index.js +467 -0
- package/packages/react-css/dist/index.js.map +1 -0
- package/packages/shared/README.md +1 -1
- package/packages/shared/dist/index.d.mts +625 -0
- package/packages/shared/dist/index.d.ts +625 -0
- package/packages/shared/dist/index.js +1567 -0
- package/packages/shared/dist/index.js.map +1 -0
- package/packages/shared/dist/index.mjs +1489 -0
- package/packages/shared/dist/index.mjs.map +1 -0
- package/packages/solidjs/README.md +1 -1
- package/packages/solidjs/dist/index.d.mts +97 -0
- package/packages/solidjs/dist/index.d.ts +97 -0
- package/packages/solidjs/dist/index.js +250 -0
- package/packages/solidjs/dist/index.js.map +1 -0
- package/packages/solidjs/dist/index.mjs +202 -0
- package/packages/solidjs/dist/index.mjs.map +1 -0
- package/packages/solidjs-css/README.md +1 -1
- package/packages/solidjs-css/dist/index.cjs +343 -0
- package/packages/solidjs-css/dist/index.cjs.map +1 -0
- package/packages/solidjs-css/dist/index.d.cts +67 -0
- package/packages/solidjs-css/dist/index.d.ts +67 -0
- package/packages/solidjs-css/dist/index.js +326 -0
- package/packages/solidjs-css/dist/index.js.map +1 -0
- package/.changeset/config.json +0 -11
- package/.github/CODEOWNERS +0 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -11
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -10
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/ci.yml +0 -23
- package/.github/workflows/release.yml +0 -29
- package/.nvmrc +0 -1
- package/.project/ACCOUNT.yaml +0 -4
- package/.project/IDEAS.yaml +0 -7
- package/.project/PROJECT.yaml +0 -11
- package/.project/ROADMAP.yaml +0 -15
- package/CODE_OF_CONDUCT.md +0 -16
- package/CONTRIBUTING.md +0 -26
- package/SECURITY.md +0 -15
- package/SUPPORT.md +0 -8
- package/packages/convex/package.json +0 -42
- package/packages/convex/src/adapter.ts +0 -39
- package/packages/convex/src/index.ts +0 -19
- package/packages/convex/src/mutations.ts +0 -142
- package/packages/convex/src/queries.ts +0 -106
- package/packages/convex/src/schema.ts +0 -54
- package/packages/convex/src/types.ts +0 -20
- package/packages/convex/tsconfig.json +0 -11
- package/packages/convex/tsup.config.ts +0 -10
- package/packages/react/package.json +0 -45
- package/packages/react/src/components/AdapterCard.tsx +0 -49
- package/packages/react/src/components/AdapterConfigForm.tsx +0 -118
- package/packages/react/src/components/AdapterList.tsx +0 -84
- package/packages/react/src/components/AdapterStatusBadge.tsx +0 -30
- package/packages/react/src/components/index.ts +0 -4
- package/packages/react/src/hooks/index.ts +0 -75
- package/packages/react/src/index.tsx +0 -44
- package/packages/react/src/pages/AdapterDetailPage.tsx +0 -133
- package/packages/react/src/pages/AdaptersPage.tsx +0 -111
- package/packages/react/src/pages/index.ts +0 -2
- package/packages/react/src/provider/AdapterProvider.tsx +0 -115
- package/packages/react/src/provider/index.ts +0 -2
- package/packages/react/tsconfig.json +0 -18
- package/packages/react/tsup.config.ts +0 -10
- package/packages/react-css/package.json +0 -44
- package/packages/react-css/src/adapters.css +0 -1576
- package/packages/react-css/src/components/AdapterCard.tsx +0 -34
- package/packages/react-css/src/components/AdapterConfigForm.tsx +0 -63
- package/packages/react-css/src/components/AdapterList.tsx +0 -40
- package/packages/react-css/src/components/AdapterStatusBadge.tsx +0 -21
- package/packages/react-css/src/components/index.ts +0 -4
- package/packages/react-css/src/hooks/index.ts +0 -75
- package/packages/react-css/src/index.tsx +0 -25
- package/packages/react-css/src/pages/AdapterDetailPage.tsx +0 -133
- package/packages/react-css/src/pages/AdaptersPage.tsx +0 -111
- package/packages/react-css/src/pages/index.ts +0 -2
- package/packages/react-css/src/provider/AdapterProvider.tsx +0 -115
- package/packages/react-css/src/provider/index.ts +0 -2
- package/packages/react-css/src/styles.css +0 -494
- package/packages/react-css/tsconfig.json +0 -19
- package/packages/react-css/tsup.config.ts +0 -2
- package/packages/shared/package.json +0 -39
- package/packages/shared/src/__tests__/adapters.test.ts +0 -545
- package/packages/shared/src/admin/index.ts +0 -2
- package/packages/shared/src/admin/interface.ts +0 -34
- package/packages/shared/src/admin/localStorage.ts +0 -109
- package/packages/shared/src/ai/anthropic.ts +0 -123
- package/packages/shared/src/ai/cloudflare-gateway.ts +0 -130
- package/packages/shared/src/ai/gemini.ts +0 -181
- package/packages/shared/src/ai/index.ts +0 -14
- package/packages/shared/src/ai/interface.ts +0 -11
- package/packages/shared/src/ai/localStorage.ts +0 -78
- package/packages/shared/src/ai/ollama.ts +0 -143
- package/packages/shared/src/ai/openai.ts +0 -120
- package/packages/shared/src/ai/vercel-ai.ts +0 -101
- package/packages/shared/src/auth/better-auth.ts +0 -118
- package/packages/shared/src/auth/clerk.ts +0 -151
- package/packages/shared/src/auth/convex-auth.ts +0 -125
- package/packages/shared/src/auth/index.ts +0 -10
- package/packages/shared/src/auth/interface.ts +0 -17
- package/packages/shared/src/auth/localStorage.ts +0 -125
- package/packages/shared/src/auth/supabase-auth.ts +0 -136
- package/packages/shared/src/config.ts +0 -57
- package/packages/shared/src/constants.ts +0 -122
- package/packages/shared/src/db/convex.ts +0 -146
- package/packages/shared/src/db/index.ts +0 -10
- package/packages/shared/src/db/interface.ts +0 -13
- package/packages/shared/src/db/localStorage.ts +0 -91
- package/packages/shared/src/db/mongodb.ts +0 -125
- package/packages/shared/src/db/neon.ts +0 -171
- package/packages/shared/src/db/supabase.ts +0 -158
- package/packages/shared/src/index.ts +0 -117
- package/packages/shared/src/payments/index.ts +0 -4
- package/packages/shared/src/payments/interface.ts +0 -11
- package/packages/shared/src/payments/localStorage.ts +0 -81
- package/packages/shared/src/payments/stripe.ts +0 -177
- package/packages/shared/src/storage/convex.ts +0 -113
- package/packages/shared/src/storage/index.ts +0 -14
- package/packages/shared/src/storage/interface.ts +0 -11
- package/packages/shared/src/storage/localStorage.ts +0 -95
- package/packages/shared/src/storage/minio.ts +0 -47
- package/packages/shared/src/storage/r2.ts +0 -123
- package/packages/shared/src/storage/s3.ts +0 -128
- package/packages/shared/src/storage/supabase-storage.ts +0 -116
- package/packages/shared/src/storage/uploadthing.ts +0 -126
- package/packages/shared/src/styles/adapters.css +0 -494
- package/packages/shared/src/tier-gate.ts +0 -119
- package/packages/shared/src/types.ts +0 -162
- package/packages/shared/tsconfig.json +0 -18
- package/packages/shared/tsup.config.ts +0 -9
- package/packages/shared/vitest.config.ts +0 -14
- package/packages/solidjs/package.json +0 -44
- package/packages/solidjs/src/components/AdapterCard.tsx +0 -24
- package/packages/solidjs/src/components/AdapterConfigForm.tsx +0 -54
- package/packages/solidjs/src/components/AdapterList.tsx +0 -28
- package/packages/solidjs/src/components/AdapterStatusBadge.tsx +0 -20
- package/packages/solidjs/src/components/index.ts +0 -4
- package/packages/solidjs/src/index.tsx +0 -17
- package/packages/solidjs/src/pages/AdapterDetailPage.tsx +0 -38
- package/packages/solidjs/src/pages/AdaptersPage.tsx +0 -39
- package/packages/solidjs/src/pages/index.ts +0 -2
- package/packages/solidjs/src/primitives/index.ts +0 -78
- package/packages/solidjs/src/provider/AdapterProvider.tsx +0 -62
- package/packages/solidjs/src/provider/index.ts +0 -2
- package/packages/solidjs/tsconfig.json +0 -20
- package/packages/solidjs/tsup.config.ts +0 -10
- package/packages/solidjs-css/package.json +0 -43
- package/packages/solidjs-css/src/adapters.css +0 -1576
- package/packages/solidjs-css/src/components/AdapterCard.tsx +0 -43
- package/packages/solidjs-css/src/components/AdapterConfigForm.tsx +0 -119
- package/packages/solidjs-css/src/components/AdapterList.tsx +0 -68
- package/packages/solidjs-css/src/components/AdapterStatusBadge.tsx +0 -24
- package/packages/solidjs-css/src/components/index.ts +0 -8
- package/packages/solidjs-css/src/index.tsx +0 -30
- package/packages/solidjs-css/src/pages/AdapterDetailPage.tsx +0 -107
- package/packages/solidjs-css/src/pages/AdaptersPage.tsx +0 -94
- package/packages/solidjs-css/src/pages/index.ts +0 -4
- package/packages/solidjs-css/src/primitives/index.ts +0 -1
- package/packages/solidjs-css/src/provider/AdapterProvider.tsx +0 -61
- package/packages/solidjs-css/src/provider/index.ts +0 -2
- package/packages/solidjs-css/tsconfig.json +0 -20
- package/packages/solidjs-css/tsup.config.ts +0 -2
- package/pnpm-workspace.yaml +0 -2
- package/tsconfig.json +0 -17
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
// @geenius/adapters — AWS S3 file storage adapter
|
|
2
|
-
// Requires: @aws-sdk/client-s3, @aws-sdk/s3-request-presigner
|
|
3
|
-
|
|
4
|
-
import type { StoredFile } from '../types'
|
|
5
|
-
import type { FileStorageAdapter } from './interface'
|
|
6
|
-
|
|
7
|
-
export interface S3FileAdapterOptions {
|
|
8
|
-
/** AWS region */
|
|
9
|
-
region: string
|
|
10
|
-
/** S3 bucket name */
|
|
11
|
-
bucket: string
|
|
12
|
-
/** AWS access key ID (optional if using IAM roles) */
|
|
13
|
-
accessKeyId?: string
|
|
14
|
-
/** AWS secret access key (optional if using IAM roles) */
|
|
15
|
-
secretAccessKey?: string
|
|
16
|
-
/** Custom endpoint (for S3-compatible services) */
|
|
17
|
-
endpoint?: string
|
|
18
|
-
/** Custom public URL prefix (e.g. CloudFront distribution) */
|
|
19
|
-
publicUrl?: string
|
|
20
|
-
/** Presigned URL expiry in seconds (default: 3600) */
|
|
21
|
-
presignedExpiry?: number
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function createS3FileAdapter(options: S3FileAdapterOptions): FileStorageAdapter {
|
|
25
|
-
const { region, bucket, accessKeyId, secretAccessKey, endpoint, publicUrl, presignedExpiry = 3600 } = options
|
|
26
|
-
|
|
27
|
-
let s3Client: any = null
|
|
28
|
-
let getSignedUrl: any = null
|
|
29
|
-
let commands: any = null
|
|
30
|
-
|
|
31
|
-
async function getClient() {
|
|
32
|
-
if (!s3Client) {
|
|
33
|
-
const { S3Client } = await import('@aws-sdk/client-s3')
|
|
34
|
-
const presigner = await import('@aws-sdk/s3-request-presigner')
|
|
35
|
-
const s3Commands = await import('@aws-sdk/client-s3')
|
|
36
|
-
|
|
37
|
-
const clientConfig: any = { region, endpoint }
|
|
38
|
-
if (accessKeyId && secretAccessKey) {
|
|
39
|
-
clientConfig.credentials = { accessKeyId, secretAccessKey }
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
s3Client = new S3Client(clientConfig)
|
|
43
|
-
getSignedUrl = presigner.getSignedUrl
|
|
44
|
-
commands = s3Commands
|
|
45
|
-
}
|
|
46
|
-
return { client: s3Client, getSignedUrl, commands }
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
async upload(file, path, name?) {
|
|
51
|
-
const { client, commands: cmd } = await getClient()
|
|
52
|
-
const id = crypto.randomUUID()
|
|
53
|
-
const fileName = name || (file instanceof File ? file.name : `file-${id.slice(0, 8)}`)
|
|
54
|
-
const key = path ? `${path}/${fileName}` : fileName
|
|
55
|
-
const buffer = new Uint8Array(await file.arrayBuffer())
|
|
56
|
-
|
|
57
|
-
await client.send(new cmd.PutObjectCommand({
|
|
58
|
-
Bucket: bucket,
|
|
59
|
-
Key: key,
|
|
60
|
-
Body: buffer,
|
|
61
|
-
ContentType: file.type || 'application/octet-stream',
|
|
62
|
-
Metadata: { 'original-name': fileName, 'file-id': id },
|
|
63
|
-
}))
|
|
64
|
-
|
|
65
|
-
const url = publicUrl
|
|
66
|
-
? `${publicUrl}/${key}`
|
|
67
|
-
: `https://${bucket}.s3.${region}.amazonaws.com/${key}`
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
id,
|
|
71
|
-
name: fileName,
|
|
72
|
-
path: key,
|
|
73
|
-
size: file.size,
|
|
74
|
-
mimeType: file.type || 'application/octet-stream',
|
|
75
|
-
url,
|
|
76
|
-
createdAt: new Date().toISOString(),
|
|
77
|
-
}
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
async download(fileId) {
|
|
81
|
-
const { client, commands: cmd } = await getClient()
|
|
82
|
-
const response = await client.send(new cmd.GetObjectCommand({
|
|
83
|
-
Bucket: bucket,
|
|
84
|
-
Key: fileId,
|
|
85
|
-
}))
|
|
86
|
-
const bytes = await response.Body?.transformToByteArray()
|
|
87
|
-
if (!bytes) throw new Error(`Failed to download file: ${fileId}`)
|
|
88
|
-
return new Blob([bytes], { type: response.ContentType || 'application/octet-stream' })
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
async delete(fileId) {
|
|
92
|
-
const { client, commands: cmd } = await getClient()
|
|
93
|
-
try {
|
|
94
|
-
await client.send(new cmd.DeleteObjectCommand({ Bucket: bucket, Key: fileId }))
|
|
95
|
-
return true
|
|
96
|
-
} catch {
|
|
97
|
-
return false
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
|
|
101
|
-
async list(prefix?) {
|
|
102
|
-
const { client, commands: cmd } = await getClient()
|
|
103
|
-
const response = await client.send(new cmd.ListObjectsV2Command({
|
|
104
|
-
Bucket: bucket,
|
|
105
|
-
Prefix: prefix || undefined,
|
|
106
|
-
}))
|
|
107
|
-
|
|
108
|
-
return (response.Contents || []).map((obj: any): StoredFile => ({
|
|
109
|
-
id: obj.Key,
|
|
110
|
-
name: obj.Key.split('/').pop() || obj.Key,
|
|
111
|
-
path: obj.Key,
|
|
112
|
-
size: obj.Size || 0,
|
|
113
|
-
mimeType: 'application/octet-stream',
|
|
114
|
-
url: publicUrl
|
|
115
|
-
? `${publicUrl}/${obj.Key}`
|
|
116
|
-
: `https://${bucket}.s3.${region}.amazonaws.com/${obj.Key}`,
|
|
117
|
-
createdAt: obj.LastModified?.toISOString() || new Date().toISOString(),
|
|
118
|
-
}))
|
|
119
|
-
},
|
|
120
|
-
|
|
121
|
-
async getUrl(fileId) {
|
|
122
|
-
if (publicUrl) return `${publicUrl}/${fileId}`
|
|
123
|
-
const { client, getSignedUrl: sign, commands: cmd } = await getClient()
|
|
124
|
-
const command = new cmd.GetObjectCommand({ Bucket: bucket, Key: fileId })
|
|
125
|
-
return sign(client, command, { expiresIn: presignedExpiry })
|
|
126
|
-
},
|
|
127
|
-
}
|
|
128
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
// @geenius/adapters — Supabase Storage file adapter
|
|
2
|
-
// Requires: @supabase/supabase-js
|
|
3
|
-
|
|
4
|
-
import type { StoredFile } from '../types'
|
|
5
|
-
import type { FileStorageAdapter } from './interface'
|
|
6
|
-
|
|
7
|
-
export interface SupabaseFileAdapterOptions {
|
|
8
|
-
/** Supabase project URL */
|
|
9
|
-
supabaseUrl: string
|
|
10
|
-
/** Supabase service role key or anon key */
|
|
11
|
-
supabaseKey: string
|
|
12
|
-
/** Storage bucket name (default: 'files') */
|
|
13
|
-
bucket?: string
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function createSupabaseFileAdapter(options: SupabaseFileAdapterOptions): FileStorageAdapter {
|
|
17
|
-
const { supabaseUrl, supabaseKey, bucket = 'files' } = options
|
|
18
|
-
|
|
19
|
-
let supabase: any = null
|
|
20
|
-
|
|
21
|
-
async function getClient() {
|
|
22
|
-
if (!supabase) {
|
|
23
|
-
const { createClient } = await import('@supabase/supabase-js')
|
|
24
|
-
supabase = createClient(supabaseUrl, supabaseKey)
|
|
25
|
-
}
|
|
26
|
-
return supabase
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
async upload(file, path, name?) {
|
|
31
|
-
const client = await getClient()
|
|
32
|
-
const id = crypto.randomUUID()
|
|
33
|
-
const fileName = name || (file instanceof File ? file.name : `file-${id.slice(0, 8)}`)
|
|
34
|
-
const filePath = path ? `${path}/${fileName}` : fileName
|
|
35
|
-
|
|
36
|
-
const { error } = await client.storage
|
|
37
|
-
.from(bucket)
|
|
38
|
-
.upload(filePath, file, {
|
|
39
|
-
contentType: file.type || 'application/octet-stream',
|
|
40
|
-
upsert: false,
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
if (error) throw new Error(`Supabase upload failed: ${error.message}`)
|
|
44
|
-
|
|
45
|
-
const { data: urlData } = client.storage
|
|
46
|
-
.from(bucket)
|
|
47
|
-
.getPublicUrl(filePath)
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
id,
|
|
51
|
-
name: fileName,
|
|
52
|
-
path: filePath,
|
|
53
|
-
size: file.size,
|
|
54
|
-
mimeType: file.type || 'application/octet-stream',
|
|
55
|
-
url: urlData.publicUrl,
|
|
56
|
-
createdAt: new Date().toISOString(),
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
async download(fileId) {
|
|
61
|
-
const client = await getClient()
|
|
62
|
-
const { data, error } = await client.storage
|
|
63
|
-
.from(bucket)
|
|
64
|
-
.download(fileId)
|
|
65
|
-
|
|
66
|
-
if (error || !data) throw new Error(`Supabase download failed: ${error?.message || 'No data'}`)
|
|
67
|
-
return data
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
async delete(fileId) {
|
|
71
|
-
const client = await getClient()
|
|
72
|
-
const { error } = await client.storage
|
|
73
|
-
.from(bucket)
|
|
74
|
-
.remove([fileId])
|
|
75
|
-
|
|
76
|
-
return !error
|
|
77
|
-
},
|
|
78
|
-
|
|
79
|
-
async list(prefix?) {
|
|
80
|
-
const client = await getClient()
|
|
81
|
-
const { data, error } = await client.storage
|
|
82
|
-
.from(bucket)
|
|
83
|
-
.list(prefix || '', { limit: 1000, sortBy: { column: 'created_at', order: 'desc' } })
|
|
84
|
-
|
|
85
|
-
if (error || !data) return []
|
|
86
|
-
|
|
87
|
-
return data
|
|
88
|
-
.filter((f: any) => f.name) // filter out folders
|
|
89
|
-
.map((f: any): StoredFile => {
|
|
90
|
-
const filePath = prefix ? `${prefix}/${f.name}` : f.name
|
|
91
|
-
const { data: urlData } = client.storage
|
|
92
|
-
.from(bucket)
|
|
93
|
-
.getPublicUrl(filePath)
|
|
94
|
-
|
|
95
|
-
return {
|
|
96
|
-
id: f.id || filePath,
|
|
97
|
-
name: f.name,
|
|
98
|
-
path: filePath,
|
|
99
|
-
size: f.metadata?.size || 0,
|
|
100
|
-
mimeType: f.metadata?.mimetype || 'application/octet-stream',
|
|
101
|
-
url: urlData.publicUrl,
|
|
102
|
-
createdAt: f.created_at || new Date().toISOString(),
|
|
103
|
-
}
|
|
104
|
-
})
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
async getUrl(fileId) {
|
|
108
|
-
const client = await getClient()
|
|
109
|
-
const { data } = client.storage
|
|
110
|
-
.from(bucket)
|
|
111
|
-
.getPublicUrl(fileId)
|
|
112
|
-
|
|
113
|
-
return data.publicUrl
|
|
114
|
-
},
|
|
115
|
-
}
|
|
116
|
-
}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
// @geenius/adapters — Uploadthing file storage adapter
|
|
2
|
-
// Requires: uploadthing
|
|
3
|
-
|
|
4
|
-
import type { StoredFile } from '../types'
|
|
5
|
-
import type { FileStorageAdapter } from './interface'
|
|
6
|
-
|
|
7
|
-
export interface UploadthingFileAdapterOptions {
|
|
8
|
-
/** Uploadthing API token */
|
|
9
|
-
token: string
|
|
10
|
-
/** Base URL for the Uploadthing API (default: https://api.uploadthing.com) */
|
|
11
|
-
apiUrl?: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function createUploadthingFileAdapter(options: UploadthingFileAdapterOptions): FileStorageAdapter {
|
|
15
|
-
const { token, apiUrl = 'https://api.uploadthing.com' } = options
|
|
16
|
-
|
|
17
|
-
const headers = {
|
|
18
|
-
'Content-Type': 'application/json',
|
|
19
|
-
'x-uploadthing-api-key': token,
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return {
|
|
23
|
-
async upload(file, path, name?) {
|
|
24
|
-
const id = crypto.randomUUID()
|
|
25
|
-
const fileName = name || (file instanceof File ? file.name : `file-${id.slice(0, 8)}`)
|
|
26
|
-
|
|
27
|
-
// Request a presigned URL from Uploadthing
|
|
28
|
-
const presignResponse = await fetch(`${apiUrl}/v6/uploadFiles`, {
|
|
29
|
-
method: 'POST',
|
|
30
|
-
headers,
|
|
31
|
-
body: JSON.stringify({
|
|
32
|
-
files: [{
|
|
33
|
-
name: fileName,
|
|
34
|
-
size: file.size,
|
|
35
|
-
type: file.type || 'application/octet-stream',
|
|
36
|
-
customId: id,
|
|
37
|
-
}],
|
|
38
|
-
acl: 'public-read',
|
|
39
|
-
contentDisposition: 'inline',
|
|
40
|
-
}),
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
if (!presignResponse.ok) {
|
|
44
|
-
throw new Error(`Uploadthing presign failed: ${presignResponse.statusText}`)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const presignData = await presignResponse.json()
|
|
48
|
-
const upload = presignData.data?.[0]
|
|
49
|
-
|
|
50
|
-
if (!upload?.url) {
|
|
51
|
-
throw new Error('Uploadthing did not return an upload URL')
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Upload the file to the presigned URL
|
|
55
|
-
const formData = new FormData()
|
|
56
|
-
for (const [key, value] of Object.entries(upload.fields || {})) {
|
|
57
|
-
formData.append(key, value as string)
|
|
58
|
-
}
|
|
59
|
-
formData.append('file', file)
|
|
60
|
-
|
|
61
|
-
const uploadResponse = await fetch(upload.url, {
|
|
62
|
-
method: 'POST',
|
|
63
|
-
body: formData,
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
if (!uploadResponse.ok) {
|
|
67
|
-
throw new Error(`Uploadthing upload failed: ${uploadResponse.statusText}`)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return {
|
|
71
|
-
id: upload.key || id,
|
|
72
|
-
name: fileName,
|
|
73
|
-
path: path ? `${path}/${fileName}` : fileName,
|
|
74
|
-
size: file.size,
|
|
75
|
-
mimeType: file.type || 'application/octet-stream',
|
|
76
|
-
url: upload.fileUrl || `https://utfs.io/f/${upload.key}`,
|
|
77
|
-
createdAt: new Date().toISOString(),
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
async download(fileId) {
|
|
82
|
-
const url = fileId.startsWith('http') ? fileId : `https://utfs.io/f/${fileId}`
|
|
83
|
-
const response = await fetch(url)
|
|
84
|
-
if (!response.ok) throw new Error(`Failed to download file: ${fileId}`)
|
|
85
|
-
return response.blob()
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
async delete(fileId) {
|
|
89
|
-
try {
|
|
90
|
-
const response = await fetch(`${apiUrl}/v6/deleteFiles`, {
|
|
91
|
-
method: 'POST',
|
|
92
|
-
headers,
|
|
93
|
-
body: JSON.stringify({ fileKeys: [fileId] }),
|
|
94
|
-
})
|
|
95
|
-
return response.ok
|
|
96
|
-
} catch {
|
|
97
|
-
return false
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
|
|
101
|
-
async list(prefix?) {
|
|
102
|
-
const response = await fetch(`${apiUrl}/v6/listFiles`, {
|
|
103
|
-
method: 'POST',
|
|
104
|
-
headers,
|
|
105
|
-
body: JSON.stringify({ prefix }),
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
if (!response.ok) return []
|
|
109
|
-
|
|
110
|
-
const data = await response.json()
|
|
111
|
-
return (data.files || []).map((f: any): StoredFile => ({
|
|
112
|
-
id: f.key,
|
|
113
|
-
name: f.name || f.key,
|
|
114
|
-
path: f.key,
|
|
115
|
-
size: f.size || 0,
|
|
116
|
-
mimeType: f.type || 'application/octet-stream',
|
|
117
|
-
url: f.url || `https://utfs.io/f/${f.key}`,
|
|
118
|
-
createdAt: f.uploadedAt || new Date().toISOString(),
|
|
119
|
-
}))
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
async getUrl(fileId) {
|
|
123
|
-
return fileId.startsWith('http') ? fileId : `https://utfs.io/f/${fileId}`
|
|
124
|
-
},
|
|
125
|
-
}
|
|
126
|
-
}
|