upload base64
This commit is contained in:
@@ -471,23 +471,23 @@ const PengaduanRoute = new Elysia({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Konversi file ke base64
|
// Konversi file ke base64
|
||||||
const buffer = await file.arrayBuffer();
|
// const buffer = await file.arrayBuffer();
|
||||||
const base64String = Buffer.from(buffer).toString("base64");
|
// const base64String = Buffer.from(buffer).toString("base64");
|
||||||
|
|
||||||
// (Opsional) jika perlu dikirim ke Seafile sebagai base64
|
// (Opsional) jika perlu dikirim ke Seafile sebagai base64
|
||||||
const result = await uploadFileBase64(defaultConfigSF, { name: file.name, data: base64String });
|
const result = await uploadFileBase64(defaultConfigSF, { name: 'contoh', data: file });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: "Upload berhasil",
|
message: "Upload berhasil",
|
||||||
filename: file.name,
|
// filename: file.name,
|
||||||
size: file.size,
|
// size: file.size,
|
||||||
base64Preview: base64String.slice(0, 100) + "...", // hanya preview
|
// base64Preview: base64String.slice(0, 100) + "...", // hanya preview
|
||||||
seafileResult: result
|
seafileResult: result
|
||||||
};
|
};
|
||||||
}, {
|
}, {
|
||||||
body: t.Object({
|
body: t.Object({
|
||||||
file: t.File({ format: "binary" })
|
file: t.String()
|
||||||
}),
|
}),
|
||||||
detail: {
|
detail: {
|
||||||
summary: "Upload File (Base64)",
|
summary: "Upload File (Base64)",
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
|
IMAGE_BASE64=$(base64 image.png | tr -d '\n')
|
||||||
|
|
||||||
curl -X POST http://localhost:3000/api/pengaduan/upload-base64 \
|
curl -X POST http://localhost:3000/api/pengaduan/upload-base64 \
|
||||||
-F file=@package.json
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"file\": \"$IMAGE_BASE64\"}"
|
||||||
|
|||||||
151
x.ts
151
x.ts
@@ -1,133 +1,38 @@
|
|||||||
/**
|
import fs from "fs";
|
||||||
* src/utils/swagger-to-mcp.ts
|
|
||||||
*
|
|
||||||
* Auto-converter: Swagger (OpenAPI) → MCP manifest (real-time)
|
|
||||||
*
|
|
||||||
* - Fetch swagger JSON dynamically from process.env.BUN_PUBLIC_BASE_URL + "/docs/json"
|
|
||||||
* - Generate MCP manifest for AI discovery (/.well-known/mcp.json)
|
|
||||||
* - Can be used as Bun CLI or integrated in Elysia route
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { writeFileSync } from "fs"
|
// 1️⃣ File yang mau diupload
|
||||||
|
const filePath = "image.png";
|
||||||
|
const apiUrl = "http://localhost:3000/api/pengaduan/upload-base64";
|
||||||
|
|
||||||
interface OpenAPI {
|
// 2️⃣ Baca file dan ubah ke base64
|
||||||
info: { title?: string; description?: string; version?: string }
|
const fileBuffer = fs.readFileSync(filePath);
|
||||||
paths: Record<string, any>
|
const base64Data = fileBuffer.toString("base64");
|
||||||
}
|
|
||||||
|
|
||||||
interface McpManifest {
|
// 3️⃣ Buat payload JSON
|
||||||
schema_version: string
|
const payload = {
|
||||||
name: string
|
file: base64Data,
|
||||||
description: string
|
};
|
||||||
version?: string
|
|
||||||
endpoints: Record<string, string>
|
|
||||||
capabilities: Record<string, any>
|
|
||||||
contact?: { email?: string }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// 4️⃣ Kirim ke server pakai fetch
|
||||||
* Convert OpenAPI JSON to MCP manifest format
|
async function uploadBase64() {
|
||||||
*/
|
try {
|
||||||
async function convertOpenApiToMcp(baseUrl: string): Promise<McpManifest> {
|
const res = await fetch(apiUrl, {
|
||||||
const res = await fetch(`${baseUrl}/docs/json`)
|
method: "POST",
|
||||||
if (!res.ok) throw new Error(`Failed to fetch Swagger JSON from ${baseUrl}/docs/json`)
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
const openapi: OpenAPI = await res.json()
|
|
||||||
|
|
||||||
const manifest: McpManifest = {
|
|
||||||
schema_version: "1.0",
|
|
||||||
name: openapi.info?.title ?? "MCP Server",
|
|
||||||
description: openapi.info?.description ?? "Auto-generated MCP manifest from Swagger",
|
|
||||||
version: openapi.info?.version ?? "0.0.0",
|
|
||||||
endpoints: {
|
|
||||||
openapi: `${baseUrl}/docs/json`,
|
|
||||||
mcp: `${baseUrl}/.well-known/mcp.json`
|
|
||||||
},
|
},
|
||||||
capabilities: {}
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(`Request failed: ${res.status} ${res.statusText}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [path, methods] of Object.entries(openapi.paths || {})) {
|
const result = await res.json();
|
||||||
for (const [method, def] of Object.entries<any>(methods)) {
|
console.log("✅ Upload sukses:", result);
|
||||||
const tags = def.tags || ["default"]
|
} catch (err) {
|
||||||
const tag = tags[0]
|
console.error("❌ Upload gagal:", err);
|
||||||
const operationId = def.operationId || `${method}_${path.replace(/[\/{}]/g, "_")}`
|
|
||||||
|
|
||||||
manifest.capabilities[tag] ??= {}
|
|
||||||
|
|
||||||
// Extract parameters and body schema
|
|
||||||
const params: Record<string, string> = {}
|
|
||||||
const required: string[] = []
|
|
||||||
|
|
||||||
if (Array.isArray(def.parameters)) {
|
|
||||||
for (const p of def.parameters) {
|
|
||||||
const type = p.schema?.type || "string"
|
|
||||||
params[p.name] = type
|
|
||||||
if (p.required) required.push(p.name)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bodySchema = def.requestBody?.content?.["application/json"]?.schema
|
uploadBase64();
|
||||||
if (bodySchema?.properties) {
|
|
||||||
for (const [key, prop] of Object.entries<any>(bodySchema.properties)) {
|
|
||||||
params[key] = prop.type || "string"
|
|
||||||
}
|
|
||||||
if (Array.isArray(bodySchema.required))
|
|
||||||
required.push(...bodySchema.required)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate example cURL
|
|
||||||
const sampleCurl = [
|
|
||||||
`curl -X ${method.toUpperCase()} ${baseUrl}${path}`,
|
|
||||||
Object.keys(params).length > 0
|
|
||||||
? ` -H 'Content-Type: application/json' -d '${JSON.stringify(
|
|
||||||
Object.fromEntries(Object.keys(params).map(k => [k, params[k] === "string" ? k : "value"]))
|
|
||||||
)}'`
|
|
||||||
: ""
|
|
||||||
]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(" \\\n")
|
|
||||||
|
|
||||||
manifest.capabilities[tag][operationId] = {
|
|
||||||
method: method.toUpperCase(),
|
|
||||||
path,
|
|
||||||
summary: def.summary || def.description || "",
|
|
||||||
parameters: Object.keys(params).length > 0 ? params : undefined,
|
|
||||||
required: required.length > 0 ? required : undefined,
|
|
||||||
command: sampleCurl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return manifest
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CLI entry
|
|
||||||
* bun run src/utils/swagger-to-mcp.ts
|
|
||||||
*/
|
|
||||||
if (import.meta.main) {
|
|
||||||
const baseUrl = process.env.BUN_PUBLIC_BASE_URL
|
|
||||||
if (!baseUrl) {
|
|
||||||
console.error("❌ Missing BUN_PUBLIC_BASE_URL environment variable.")
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
convertOpenApiToMcp(baseUrl)
|
|
||||||
.then(manifest => {
|
|
||||||
writeFileSync(".well-known/mcp.json", JSON.stringify(manifest, null, 2))
|
|
||||||
console.log("✅ Generated .well-known/mcp.json")
|
|
||||||
})
|
|
||||||
.catch(err => console.error("❌ Failed to convert Swagger → MCP:", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional: Elysia integration
|
|
||||||
* Automatically serve /.well-known/mcp.json
|
|
||||||
*/
|
|
||||||
// import Elysia from "elysia"
|
|
||||||
// new Elysia()
|
|
||||||
// .get("/.well-known/mcp.json", async () => {
|
|
||||||
// const baseUrl = process.env.BUN_PUBLIC_BASE_URL!
|
|
||||||
// return await convertOpenApiToMcp(baseUrl)
|
|
||||||
// })
|
|
||||||
// .listen(3000)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user