| import { downloadFile, commit, listFiles, RepoType, CommitOperation } from "@huggingface/hub"; |
|
|
| interface CommitBody { |
| path: string; |
| content?: string; |
| message?: string; |
| lfs?: boolean; |
| } |
|
|
| export const onRequest = async (context: RouteContext): Promise<Response> => { |
| const request = context.request; |
| const env = context.env as Env; |
|
|
| |
| const authHeader = request.headers.get('Authorization'); |
| if (!authHeader || !authHeader.startsWith('Bearer ')) { |
| return new Response(JSON.stringify({ error: '未提供有效的授权令牌' }), { |
| status: 401, |
| headers: { 'Content-Type': 'application/json' } |
| }); |
| } |
| const hfToken = authHeader.replace('Bearer ', ''); |
|
|
| console.log('Request URL:', request.url); |
| try { |
| const url = new URL(request.url); |
| const pathParts = url.pathname.split('/').filter(Boolean); |
|
|
| |
| const owner = pathParts[2] || url.searchParams.get('owner'); |
| const repo = pathParts[3] || url.searchParams.get('repo'); |
| const operation = pathParts[4] || url.searchParams.get('op'); |
| const ref = pathParts[5] || url.searchParams.get('ref') || 'main'; |
|
|
| if (!owner || !repo) { |
| return new Response(JSON.stringify({ error: '缺少仓库所有者或仓库名称' }), { |
| status: 400, |
| headers: { 'Content-Type': 'application/json' } |
| }); |
| } |
|
|
| const apiParams = { |
| repo: { |
| name: `${owner}/${repo}`, |
| type: 'dataset' as RepoType |
| }, |
| accessToken: hfToken, |
| revision: ref |
| }; |
|
|
| |
| if (operation === 'raw' && request.method === 'GET') { |
| const path = pathParts.length > 6 ? pathParts.slice(6).join('/') : ''; |
| |
| try { |
| const response = await downloadFile({ |
| ...apiParams, |
| path: path |
| }); |
|
|
| if (!response) { |
| return new Response(JSON.stringify({ error: '文件不存在' }), { |
| status: 404, |
| headers: { 'Content-Type': 'application/json' } |
| }); |
| } |
| return response; |
| } catch (error: any) { |
| return new Response(JSON.stringify({ error: '获取文件失败', details: error.message }), { |
| status: 500, |
| headers: { 'Content-Type': 'application/json' } |
| }); |
| } |
| } |
|
|
| if (operation === 'tree' && request.method === 'GET') { |
| const path = pathParts.length > 6 ? pathParts.slice(6).join('/') : ''; |
| try { |
| const cursor = listFiles({ |
| ...apiParams, |
| path: path |
| }); |
|
|
| const files = []; |
| for await (const entry of cursor) { |
| files.push(entry); |
| } |
|
|
| return new Response(JSON.stringify(files), { |
| headers: { 'Content-Type': 'application/json' } |
| }); |
| } catch (error: any) { |
| return new Response(JSON.stringify({ error: '列出文件失败', details: error.message }), { |
| status: 500, |
| headers: { 'Content-Type': 'application/json' } |
| }); |
| } |
| } |
|
|
| |
| if (operation === 'commit' && (request.method === 'POST' || request.method === 'PUT' || request.method === 'DELETE')) { |
| const body = await request.json() as CommitBody; |
|
|
| try { |
| let operation: CommitOperation; |
|
|
| if (request.method === 'DELETE') { |
| operation = { |
| operation: 'delete', |
| path: body.path |
| }; |
| } else { |
| const content = body.content || ''; |
| let blobContent: Blob; |
|
|
| if (body.lfs === true && body.content) { |
| const binary = atob(body.content); |
| const bytes = new Uint8Array(binary.length); |
| for (let i = 0; i < binary.length; i++) { |
| bytes[i] = binary.charCodeAt(i); |
| } |
| blobContent = new Blob([bytes]); |
| } else { |
| blobContent = new Blob([content]); |
| } |
|
|
| operation = { |
| operation: 'addOrUpdate', |
| path: body.path, |
| content: blobContent |
| }; |
| } |
|
|
| const response = await commit({ |
| ...apiParams, |
| operations: [operation], |
| title: `${request.method === 'DELETE' ? 'Delete' : 'Update'} ${body.path}`, |
| description: body.message || `Changed via API` |
| }); |
|
|
| return new Response(JSON.stringify(response), { |
| status: 200, |
| headers: { 'Content-Type': 'application/json' } |
| }); |
| } catch (error: any) { |
| return new Response(JSON.stringify({ error: '提交更改失败', details: error.message }), { |
| status: 500, |
| headers: { 'Content-Type': 'application/json' } |
| }); |
| } |
| } |
|
|
| |
| return new Response(JSON.stringify({ error: '不支持的请求方法或路径' }), { |
| status: 400, |
| headers: { 'Content-Type': 'application/json' } |
| }); |
| } catch (error: any) { |
| console.error('Error:', error); |
| return new Response(JSON.stringify({ error: '服务器内部错误', details: error.message }), { |
| status: 500, |
| headers: { 'Content-Type': 'application/json' } |
| }); |
| } |
| }; |
|
|