@composio/core
Version:

220 lines (218 loc) • 8.23 kB
JavaScript
import { c as TEMP_FILES_DIRECTORY_NAME, n as logger_default, r as COMPOSIO_DIR } from "./ComposioError-ChkSdxqU.mjs";
import { i as getRandomShortId, n as base64ToUint8Array, r as uint8ArrayToBase64 } from "./buffer-yOtEsT4J.mjs";
import { platform } from "#platform";
import crypto from "node:crypto";
//#region src/utils/fileUtils.node.ts
const getExtensionFromMimeType = (mimeType) => {
const mimeToExt = {
"text/plain": "txt",
"text/html": "html",
"text/css": "css",
"text/javascript": "js",
"application/json": "json",
"application/xml": "xml",
"application/pdf": "pdf",
"application/zip": "zip",
"application/x-zip-compressed": "zip",
"application/gzip": "gz",
"application/x-tar": "tar",
"application/msword": "doc",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
"application/vnd.ms-excel": "xls",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
"application/vnd.ms-powerpoint": "ppt",
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
"image/jpeg": "jpg",
"image/jpg": "jpg",
"image/png": "png",
"image/gif": "gif",
"image/svg+xml": "svg",
"image/webp": "webp",
"image/bmp": "bmp",
"image/tiff": "tiff",
"audio/mpeg": "mp3",
"audio/wav": "wav",
"audio/ogg": "ogg",
"video/mp4": "mp4",
"video/mpeg": "mpeg",
"video/quicktime": "mov",
"video/x-msvideo": "avi",
"video/webm": "webm"
};
const cleanMimeType = mimeType.split(";")[0].toLowerCase().trim();
if (mimeToExt[cleanMimeType]) return mimeToExt[cleanMimeType];
const parts = cleanMimeType.split("/");
if (parts.length === 2) {
const cleanSubtype = parts[1].toLowerCase();
if (cleanSubtype.includes("+")) {
const plusParts = cleanSubtype.split("+");
const prefix = plusParts[0];
const suffix = plusParts[plusParts.length - 1];
if ([
"svg",
"atom",
"rss"
].includes(prefix)) return prefix;
if ([
"json",
"xml",
"yaml",
"zip",
"gzip"
].includes(suffix)) return suffix;
return suffix;
}
return cleanSubtype || "txt";
}
return "txt";
};
const generateTimestampedFilename = (extension, prefix) => {
return `${prefix || "file_ts"}${Date.now()}${getRandomShortId()}.${extension}`;
};
const readFileContent = async (filePath) => {
try {
if (!platform.supportsFileSystem) throw new Error("File system operations are not supported in this runtime environment");
const content = platform.readFileSync(filePath);
return {
fileName: generateTimestampedFilename(filePath.split(".").pop() || "txt"),
content: content instanceof Uint8Array ? uint8ArrayToBase64(content) : uint8ArrayToBase64(new TextEncoder().encode(content)),
mimeType: "application/octet-stream"
};
} catch (error) {
throw new Error(`Error reading file at ${filePath}: ${error}`);
}
};
const readFileContentFromURL = async (path) => {
const response = await fetch(path);
if (!response.ok) throw new Error(`Failed to fetch file: ${response.statusText}`);
const arrayBuffer = await response.arrayBuffer();
const content = new Uint8Array(arrayBuffer);
const mimeType = response.headers.get("content-type") || "application/octet-stream";
const pathname = new URL(path).pathname;
let fileName = platform.basename(pathname);
if (!fileName || fileName === "/") fileName = generateTimestampedFilename(getExtensionFromMimeType(mimeType));
else if (!fileName.includes(".")) fileName = generateTimestampedFilename(getExtensionFromMimeType(mimeType));
return {
content: uint8ArrayToBase64(content),
mimeType,
fileName
};
};
const uploadFileToS3 = async (fileName, content, toolSlug, toolkitSlug, mimeType, client) => {
const contentBytes = base64ToUint8Array(content);
const { key, new_presigned_url: signedURL } = await client.files.createPresignedURL({
filename: fileName,
mimetype: mimeType,
md5: crypto.createHash("md5").update(contentBytes).digest("hex"),
tool_slug: toolSlug,
toolkit_slug: toolkitSlug
});
logger_default.debug(`Uploading ${key} file to S3: ${key}`);
const uploadBuffer = new Uint8Array(contentBytes.byteLength);
uploadBuffer.set(contentBytes);
const uploadResponse = await fetch(signedURL, {
method: "PUT",
body: uploadBuffer,
headers: {
"Content-Type": mimeType,
"Content-Length": contentBytes.length.toString()
}
});
if (!uploadResponse.ok) throw new Error(`Failed to upload file to S3: ${uploadResponse.statusText}`);
return key;
};
const readFile = async (file) => {
if (file instanceof File) {
const content = await file.arrayBuffer();
return {
fileName: file.name,
content: uint8ArrayToBase64(new Uint8Array(content)),
mimeType: file.type
};
} else if (typeof file === "string") if (file.startsWith("http")) return await readFileContentFromURL(file);
else return await readFileContent(file);
throw new Error("Invalid file type");
};
const getFileDataAfterUploadingToS3 = async (file, { toolSlug, toolkitSlug, client }) => {
if (!file) throw new Error("Either path or blob must be provided");
const fileData = await readFile(file);
logger_default.debug(`Uploading file to S3...`);
const s3key = await uploadFileToS3(platform.basename(fileData.fileName), fileData.content, toolSlug, toolkitSlug, fileData.mimeType, client);
logger_default.debug(`Done! File uploaded to S3: ${s3key}`, JSON.stringify(fileData, null, 2));
return {
name: fileData.fileName,
mimetype: fileData.mimeType,
s3key
};
};
const downloadFileFromS3 = async ({ toolSlug, s3Url, mimeType }) => {
const response = await fetch(s3Url);
if (!response.ok) throw new Error(`Failed to download file: ${response.statusText}`);
const data = await response.arrayBuffer();
const fileName = generateTimestampedFilename(getExtensionFromMimeType(mimeType), `${toolSlug}_`);
return {
name: fileName,
mimeType,
s3Url,
filePath: saveFile(fileName, new Uint8Array(data), true)
};
};
/**
* Gets the Composio directory.
* @param createDirIfNotExists - Whether to create the directory if it doesn't exist.
* @returns The path to the Composio directory.
*/
const getComposioDir = (createDirIfNotExists = false) => {
try {
const homeDir = platform.homedir();
if (!homeDir) return null;
const composioDir = platform.joinPath(homeDir, COMPOSIO_DIR);
if (createDirIfNotExists && platform.supportsFileSystem && !platform.existsSync(composioDir)) platform.mkdirSync(composioDir);
return composioDir;
} catch (_error) {
return null;
}
};
/**
* Gets the Composio temporary files directory.
* @param createDirIfNotExists - Whether to create the directory if it doesn't exist.
* @returns The path to the Composio temporary files directory.
*/
const getComposioTempFilesDir = (createDirIfNotExists = false) => {
try {
const homeDir = platform.homedir();
if (!homeDir) return null;
const composioFilesDir = platform.joinPath(homeDir, COMPOSIO_DIR, TEMP_FILES_DIRECTORY_NAME);
if (createDirIfNotExists && platform.supportsFileSystem && !platform.existsSync(composioFilesDir)) platform.mkdirSync(composioFilesDir);
return composioFilesDir;
} catch (_error) {
return null;
}
};
/**
* Saves a file to the Composio directory.
* @param file - The name of the file to save.
* @param content - The content of the file to save. Can be a string or Uint8Array.
* @param isTempFile - Whether the file is a temporary file.
* @returns The path to the saved file.
*/
const saveFile = (file, content, isTempFile = false) => {
try {
if (!platform.supportsFileSystem) {
logger_default.debug("File system operations are not supported in this runtime environment");
return null;
}
const composioFilesDir = isTempFile ? getComposioTempFilesDir(true) : getComposioDir(true);
if (!composioFilesDir) return null;
const filePath = platform.joinPath(composioFilesDir, platform.basename(file));
logger_default.info(`Saving file to: ${filePath}`);
if (content instanceof Uint8Array) platform.writeFileSync(filePath, content);
else platform.writeFileSync(filePath, content, "utf8");
return filePath;
} catch (_error) {
logger_default.debug(`Error saving file: ${_error}`);
return null;
}
};
//#endregion
export { getFileDataAfterUploadingToS3 as n, downloadFileFromS3 as t };