262 lines
7.6 KiB
Plaintext
262 lines
7.6 KiB
Plaintext
import { IExecuteFunctions, IDataObject } from 'n8n-workflow';
|
|
import {
|
|
kdriveApiRequest,
|
|
resolvePathToId,
|
|
normalizePath,
|
|
parsePath,
|
|
getFileInfoById,
|
|
resolveIdToPath
|
|
} from './GenericFunctions';
|
|
|
|
export interface KDriveCredentials {
|
|
apiKey: string;
|
|
driveId: string;
|
|
}
|
|
|
|
export interface KDriveFile {
|
|
id: string;
|
|
name: string;
|
|
type: string;
|
|
path: string;
|
|
size?: number;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
[key: string]: any;
|
|
}
|
|
|
|
export class KDriveApi {
|
|
private credentials: KDriveCredentials;
|
|
private executeFunctions: IExecuteFunctions;
|
|
|
|
constructor(credentials: KDriveCredentials, executeFunctions?: IExecuteFunctions) {
|
|
this.credentials = credentials;
|
|
this.executeFunctions = executeFunctions || this.createMockExecuteFunctions();
|
|
}
|
|
|
|
private createMockExecuteFunctions(): IExecuteFunctions {
|
|
// Créer un mock minimal pour les tests
|
|
return {
|
|
helpers: {
|
|
request: async (options: any) => {
|
|
// Implémentation minimale pour les tests
|
|
const response = await this.makeApiRequest(options);
|
|
return response;
|
|
}
|
|
}
|
|
} as any;
|
|
}
|
|
|
|
private async makeApiRequest(options: any): Promise<any> {
|
|
// Implémentation directe de la requête API pour les tests
|
|
return new Promise((resolve, reject) => {
|
|
const request = require('request');
|
|
const FormData = require('form-data');
|
|
|
|
|
|
|
|
// Handle formData for file uploads using form-data package
|
|
if (options.formData) {
|
|
const form = new FormData();
|
|
|
|
|
|
|
|
// Add file to form
|
|
if (options.formData.file) {
|
|
const fileData = options.formData.file;
|
|
const fileValue = fileData.value || fileData;
|
|
const filename = options.formData.file_name || options.formData.filename || 'file';
|
|
const contentType = options.formData.contentType || 'application/octet-stream';
|
|
|
|
form.append('file', fileValue, {
|
|
filename: filename,
|
|
contentType: contentType
|
|
});
|
|
}
|
|
|
|
// Add other fields with correct kDrive API field names
|
|
if (options.formData.file_name) {
|
|
form.append('file_name', options.formData.file_name);
|
|
}
|
|
if (options.formData.directory_id) {
|
|
form.append('directory_id', options.formData.directory_id);
|
|
}
|
|
if (options.formData.total_size) {
|
|
form.append('total_size', options.formData.total_size);
|
|
}
|
|
|
|
// Update options to use the form
|
|
const formHeaders = form.getHeaders();
|
|
options.headers = {
|
|
...options.headers, // Keep existing headers (including auth)
|
|
...formHeaders
|
|
};
|
|
options.body = form;
|
|
delete options.formData;
|
|
delete options.json;
|
|
}
|
|
|
|
request(options, (error: any, response: any, body: any) => {
|
|
if (error) {
|
|
reject(error);
|
|
} else if (response.statusCode >= 400) {
|
|
reject(new Error(`API Error: ${response.statusCode} - ${body?.message || body}`));
|
|
} else {
|
|
resolve(body);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
public async listFilesByPath(path: string): Promise<KDriveFile[]> {
|
|
const normalizedPath = normalizePath(path);
|
|
const fileId = await resolvePathToId.call(
|
|
this.executeFunctions,
|
|
normalizedPath,
|
|
this.credentials.driveId,
|
|
this.createCredentialsObject()
|
|
);
|
|
|
|
// Get files in the directory
|
|
const endpoint = fileId === 'root'
|
|
? `/3/drive/${this.credentials.driveId}/files/1/files`
|
|
: `/3/drive/${this.credentials.driveId}/files/${fileId}/files`;
|
|
|
|
const response = await kdriveApiRequest.call(
|
|
this.executeFunctions,
|
|
'GET',
|
|
endpoint,
|
|
{},
|
|
this.createCredentialsObject()
|
|
);
|
|
|
|
// Handle different response structures
|
|
const items = response.items || response.data || response;
|
|
|
|
// Ensure items is an array
|
|
const itemsArray = Array.isArray(items) ? items : [items];
|
|
|
|
// Map response to KDriveFile interface
|
|
return itemsArray.map((item: any) => ({
|
|
...item,
|
|
id: item.id || item.file_id || item.fileId,
|
|
name: item.name || item.filename || item.file_name,
|
|
type: item.type === 'dir' ? 'directory' : (item.type || item.file_type || 'file'),
|
|
path: path,
|
|
size: item.size || item.file_size,
|
|
created_at: item.created_at || item.createdAt || item.date_created,
|
|
updated_at: item.updated_at || item.updatedAt || item.date_modified,
|
|
}));
|
|
}
|
|
|
|
public async createFolder(folderName: string, parentPath: string = '/'): Promise<KDriveFile> {
|
|
const parentId = await resolvePathToId.call(
|
|
this.executeFunctions,
|
|
normalizePath(parentPath),
|
|
this.credentials.driveId,
|
|
this.createCredentialsObject()
|
|
);
|
|
|
|
const endpoint = parentId === 'root'
|
|
? `/3/drive/${this.credentials.driveId}/files/root/directory`
|
|
: `/3/drive/${this.credentials.driveId}/files/${parentId}/directory`;
|
|
|
|
const response = await kdriveApiRequest.call(
|
|
this.executeFunctions,
|
|
'POST',
|
|
endpoint,
|
|
{
|
|
name: folderName,
|
|
parent_id: parentId
|
|
},
|
|
this.createCredentialsObject()
|
|
);
|
|
|
|
return {
|
|
id: response.id,
|
|
name: response.name,
|
|
type: response.type === 'dir' ? 'folder' : response.type,
|
|
path: parentPath === '/' ? `/${folderName}` : `${parentPath}/${folderName}`
|
|
};
|
|
}
|
|
|
|
public async uploadFile(file: Blob, fileName: string, parentPath: string = '/'): Promise<KDriveFile> {
|
|
const parentId = await resolvePathToId.call(
|
|
this.executeFunctions,
|
|
normalizePath(parentPath),
|
|
this.credentials.driveId,
|
|
this.createCredentialsObject()
|
|
);
|
|
|
|
// Use the upload endpoint for all uploads
|
|
const endpoint = `/3/drive/${this.credentials.driveId}/upload`;
|
|
|
|
// Convert Blob to Buffer for upload
|
|
const buffer = await file.arrayBuffer();
|
|
const fileBuffer = Buffer.from(buffer);
|
|
|
|
// Use formData for file uploads with correct field names for kDrive API
|
|
const formData = {
|
|
file: fileBuffer,
|
|
file_name: fileName,
|
|
directory_id: parentId === 'root' ? 'root' : parentId,
|
|
total_size: fileBuffer.length
|
|
};
|
|
|
|
const response = await kdriveApiRequest.call(
|
|
this.executeFunctions,
|
|
'POST',
|
|
endpoint,
|
|
formData,
|
|
this.createCredentialsObject()
|
|
);
|
|
|
|
return {
|
|
id: response.id,
|
|
name: response.name,
|
|
type: response.type,
|
|
path: parentPath === '/' ? `/${fileName}` : `${parentPath}/${fileName}`,
|
|
size: response.size
|
|
};
|
|
}
|
|
|
|
public async downloadFile(fileId: string): Promise<Blob> {
|
|
const endpoint = `/3/drive/${this.credentials.driveId}/files/${fileId}/download`;
|
|
|
|
const response = await kdriveApiRequest.call(
|
|
this.executeFunctions,
|
|
'GET',
|
|
endpoint,
|
|
{},
|
|
this.createCredentialsObject(),
|
|
true // returnFullResponse
|
|
);
|
|
|
|
// Convert response to Blob (Node.js compatible)
|
|
const buffer = Buffer.isBuffer(response.body) ? response.body : Buffer.from(response.body);
|
|
return {
|
|
arrayBuffer: async () => buffer.buffer,
|
|
text: async () => buffer.toString('utf-8'),
|
|
size: buffer.length,
|
|
type: response.headers['content-type'] || 'application/octet-stream'
|
|
} as any;
|
|
}
|
|
|
|
public async deleteFile(fileId: string): Promise<void> {
|
|
const endpoint = `/3/drive/${this.credentials.driveId}/files/${fileId}`;
|
|
|
|
await kdriveApiRequest.call(
|
|
this.executeFunctions,
|
|
'DELETE',
|
|
endpoint,
|
|
{},
|
|
this.createCredentialsObject()
|
|
);
|
|
}
|
|
|
|
private createCredentialsObject(): IDataObject {
|
|
return {
|
|
authentication: 'apiKey',
|
|
apiKey: this.credentials.apiKey
|
|
};
|
|
}
|
|
} |