Skip to main content
Glama

mcp-google-sheets

archive-file.ts10.6 kB
import { createAction } from '@activepieces/pieces-framework'; import { propsValidation, httpClient, HttpMethod } from '@activepieces/pieces-common'; import { cloudconvertAuth, CloudConvertClient, archiveFileSchema } from '../common'; import { Property } from '@activepieces/pieces-framework'; const archiveFileProps = () => ({ import_method: Property.StaticDropdown({ displayName: 'Import Method', description: 'How to import the files for archiving', required: true, options: { options: [ { label: 'File Upload', value: 'upload' }, { label: 'File URL', value: 'url' }, { label: 'Stored File ID', value: 'stored_file' }, ] }, defaultValue: 'upload' }), files: Property.Array({ displayName: 'Files to Archive', description: 'List of files to include in the archive', required: true, properties: { url: Property.ShortText({ displayName: 'File URL', description: 'URL of the file to archive', required: false, }), file: Property.File({ displayName: 'File', description: 'File to upload and archive', required: false, }), stored_file_id: Property.ShortText({ displayName: 'Stored File ID', description: 'ID of a previously stored file in Activepieces to archive', required: false, }), filename: Property.ShortText({ displayName: 'Filename in Archive', description: 'Optional filename for this file within the archive', required: false, }) } }), output_format: Property.StaticDropdown({ displayName: 'Archive Format', description: 'The archive format to create', required: true, options: { options: [ { label: 'ZIP', value: 'zip' }, { label: 'RAR', value: 'rar' }, { label: '7Z', value: '7z' }, { label: 'TAR', value: 'tar' }, { label: 'TAR.GZ', value: 'targz' }, { label: 'TAR.BZ2', value: 'tarbz2' }, ] }, defaultValue: 'zip' }), filename: Property.ShortText({ displayName: 'Archive Filename', description: 'Choose a filename (including extension) for the archive file', required: false, defaultValue: 'archive.zip' }), engine: Property.StaticDropdown({ displayName: 'Engine', description: 'Use a specific engine for the archiving', required: false, options: { options: [ { label: '7-Zip', value: '7z' }, { label: 'Archive Tool (Default)', value: 'archivetool' }, ] } }), engine_version: Property.ShortText({ displayName: 'Engine Version', description: 'Use a specific engine version for the archiving', required: false, }), timeout: Property.Number({ displayName: 'Timeout (seconds)', description: 'Timeout in seconds after which the task will be cancelled', required: false, }), wait_for_completion: Property.Checkbox({ displayName: 'Wait for Completion', description: 'Wait for the archive creation to complete before returning', required: true, defaultValue: true, }), store_file: Property.Checkbox({ displayName: 'Store File', description: 'Download and store the created archive in Activepieces', required: false, defaultValue: true, }), }); export const archiveFile = createAction({ name: 'archive_file', displayName: 'Archive File', description: 'Creates a ZIP, RAR, 7Z, TAR, TAR.GZ or TAR.BZ2 archive', auth: cloudconvertAuth, requireAuth: true, props: archiveFileProps(), async run(context) { await archiveFileSchema.parseAsync(context.propsValue); const { import_method, files, output_format, filename, engine, engine_version, timeout, wait_for_completion, store_file } = context.propsValue; if (!files || files.length === 0) { throw new Error('At least one file is required to create an archive'); } const client = new CloudConvertClient(context.auth); try { const jobTasks: Record<string, any> = {}; files.forEach((file: any, index: number) => { const taskName = `import-file-${index + 1}`; if (import_method === 'url') { if (!file.url) { throw new Error(`File URL is required for file ${index + 1} when using URL import method`); } jobTasks[taskName] = { operation: 'import/url', url: file.url, ...(file.filename && { filename: file.filename }) }; } else if (import_method === 'stored_file') { if (!file.stored_file_id) { throw new Error(`Stored File ID is required for file ${index + 1} when using stored file import method`); } if (!context.server?.apiUrl) { throw new Error('Server API URL is not available. Please check your Activepieces server configuration.'); } const baseUrl = context.server.apiUrl.replace(/\/$/, ''); const fileUrl = `${baseUrl}/v1/step-files/${file.stored_file_id}`; try { new URL(fileUrl); } catch (urlError) { throw new Error(`Invalid file URL constructed: ${fileUrl}. URL Error: ${urlError instanceof Error ? urlError.message : String(urlError)}`); } jobTasks[taskName] = { operation: 'import/url', url: fileUrl, ...(file.filename && { filename: file.filename }) }; } else if (import_method === 'upload') { if (!file.file || !file.file.base64) { throw new Error(`Please select a file to upload for file ${index + 1}`); } throw new Error('Upload method for multiple files is not yet supported with the new job format. Please use URL or stored file methods.'); } else { throw new Error('Invalid import method selected'); } }); // Collect all import task names const importTaskNames = files.map((_, index) => `import-file-${index + 1}`); // Archive task const archiveOptions: any = { input: importTaskNames.length === 1 ? importTaskNames[0] : importTaskNames, output_format, }; if (filename) archiveOptions.filename = filename; if (engine) archiveOptions.engine = engine; if (engine_version) archiveOptions.engine_version = engine_version; if (timeout) archiveOptions.timeout = timeout; jobTasks['archive-files'] = { operation: 'archive', ...archiveOptions }; // Export task jobTasks['export-file'] = { operation: 'export/url', input: 'archive-files' }; const job = await client.createJob(jobTasks, `archive-${Date.now()}`); if (wait_for_completion) { let attempts = 0; const maxAttempts = 60; while (attempts < maxAttempts) { const currentJob = await client.getJob(job.id); if (currentJob.status === 'finished') { // Find the export task by name in the job const exportTaskData = currentJob.tasks?.find((task: any) => task.name === 'export-file'); const downloadUrl = exportTaskData?.result?.files?.[0]?.url; const outputFilename = exportTaskData?.result?.files?.[0]?.filename || `archive.${output_format}`; let storedFileId: string | undefined; if (store_file && downloadUrl) { try { const fileResponse = await httpClient.sendRequest({ method: HttpMethod.GET, url: downloadUrl, }); if (fileResponse.status === 200 && fileResponse.body) { let fileData: Buffer; if (typeof fileResponse.body === 'string') { fileData = Buffer.from(fileResponse.body, 'binary'); } else { fileData = Buffer.from(fileResponse.body as ArrayBuffer); } storedFileId = await context.files.write({ data: fileData, fileName: outputFilename, }); } } catch (error) { // Continue without throwing } } return { job: currentJob, download_url: downloadUrl, filename: outputFilename, stored_file_id: storedFileId, file_count: files.length, output_format, size: exportTaskData?.result?.files?.[0]?.size || 0 }; } else if (currentJob.status === 'error') { throw new Error(`Archive job failed: ${currentJob.message || 'Unknown error'}`); } await new Promise(resolve => setTimeout(resolve, 5000)); attempts++; } throw new Error('Archive creation did not complete within the timeout period'); } return { job, file_count: files.length, output_format, status: 'processing' }; } catch (error) { if (error instanceof Error) { throw error; } throw new Error(`Archive creation failed: ${String(error)}`); } }, });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/activepieces/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server