import { EntityFile } from "../model/EntityFile"
import { FileVersions } from "./FileVersions"
import '../globalTypedef'
import { fromBuffer } from 'file-type'
import FormData from "form-data"
/**
* Class corresponding to Aworks EntityFiles Endpoints
* @category Endpoints
* @see [EntityFiles in Awork API Docs](https://openapi.awork.com/#/EntityFiles)
*/
export class EntityFiles {
/**
* Endpoint constructor
* @param {import('../client/index').Client} client
* @param {('projects'|'companies'|'tasks'|'comments')} entityName The name of the entity.
* @param {String} entityId The id of the entity.
*/
constructor(client, entityName, entityId) {
/**
* @private
*/
this._client = client
/**
* @private
*/
this._entityName = entityName
/**
* @private
*/
this._entityId = entityId
}
/**
* Returns the file with the specified id of the entity with the specified Id
* @param {String} fileId The id of the file.
* @returns {Promise<EntityFile>}
*/
async get(fileId) {
const response = await this._client.get(`/${this._entityName}/${this._entityId}/files/${fileId}`)
const data = response.data()
return new EntityFile(data)
}
/**
* Returns all files of the entity with the specified id.
* @param {import('../global').ListOptions} [options] Pagination and filtering options
* @returns {Promise<Array<EntityFile>>}
*/
async list(options) {
const response = await this._client.get(`/${this._entityName}/${this._entityId}/files`, options)
const data = response.data()
return data.map(d => new EntityFile(d))
}
/**
* @typedef {Object} FileMetaData
* @property {String} [name] The user-specified name of the file.
* @property {String} [filename] The name of the file.
*/
/**
* Uploads a File or Buffer Object
* @param {File|Buffer} file The file content eather as ES6 File object or Buffer.
* @param {FileMetaData} metadata The file metadata.
* @returns {Promise<EntityFile>}
*/
async create(file, metadata) {
let filename = metadata.filename || file.name
if (file instanceof Buffer) {
const { ext } = await fromBuffer(file)
filename = filename || `upload.${ext}`
}
let formData = new FormData()
formData.append('file', file, filename || 'upload')
formData.append('name', metadata.name || filename || 'upload')
formData.append('filename', filename || 'upload')
const response = await this._client.post(`/${this._entityName}/${this._entityId}/files`, formData.getBuffer(), {}, { 'Content-Length': formData.getLengthSync(), ...formData.getHeaders() })
const data = response.data()
return new EntityFile(data)
}
/**
* @typedef {Object} EntityFileUpdateModel
* @property {String} [name] The user-specified name of the file.
* @property {String} [description] The description of the file.
*
*/
/**
* Updates the file with the specified id of the entity with the specified Id.
* @param {String} fileId The id of the file.
* @param {EntityFileUpdateModel} entityFile The model to update the file with the specified id.
* @returns {Promise<EntityFile>}
*/
async update(fileId, entityFile) {
const response = await this._client.put(`/${this._entityName}/${this._entityId}/files/${fileId}`, entityFile)
const data = response.data()
return new EntityFile(data)
}
/**
* Deletes the file with the specified id of the entity with the specified Id.
* @param {String} fileId The id of the file.
* @returns {Promise<void>}
*/
async delete(fileId) {
await this._client.delete(`/${this._entityName}/${this._entityId}/files/${fileId}`)
}
/**
* Deletes all the files of the specified entity.
* @returns {Promise<void>}
*/
async deleteAll() {
await this._client.delete(`/${this._entityName}/${this._entityId}/files`)
}
/**
* @typedef {Object} ExternalFileForm
* @property {String} name The name of the file.
* @property {String} [description] The description of the file.
* @property {String} externalProvider The external provider for the file. Like 'google' or 'onedrive'.
* @property {String} externalFileUrl The url of the external provider.
* @property {String} [mimeType] The mime type of the external file.
*
*/
/**
* Endpoint to create file infos with batch operation. Created file infos don't have a version.
* @param {Array<ExternalFileForm>} externalFileForm List of file forms.
* @returns {Promise<EntityFile>}
*/
async externalFiles(externalFileForm) {
const response = await this._client.post(`/${this._entityName}/${this._entityId}/externalfiles/`, externalFileForm)
const data = response.data()
return new EntityFile(data)
}
/**
* @typedef {Object} FileByUrlModel
* @property {String} url The public URL to the file.
* @property {String} name The name of the file.
* @property {String} [description] The description of the file.
*/
/**
* Uploads a new file by providing an url. The file needs to be a public available url. The file size must not exceed 100MB.
* @param {FileByUrlModel} fileByUrlModel The url, name and description of the file.
* @returns {Promise<EntityFile>}
*/
async byUrl(fileByUrlModel) {
const response = await this._client.post(`/${this._entityName}/${this._entityId}/files/byurl`, fileByUrlModel)
const data = response.data()
return new EntityFile(data)
}
/**
* @typedef {Object} DownloadOptions
* @property {Number} [width] Set width to resize.
* @property {Number} [height] Set height to resize.
* @property {Boolean} [crop] Whether to crop the image when resizing it.
*/
/**
* @param {String} fileId The id of the file.
* @param {DownloadOptions} [options] The download options.
* @returns {String} binary
*/
async download (fileId, options = {}) {
const response = await this._client.getBinary(`/${this._entityName}/${this._entityId}/files/${fileId}/download`, options)
return response.data()
}
/**
* Returns the content of the entity file with the specified id as pdf if possible and returns bad request, if not valid type or conversion not possible.
* @param {String} fileId The id of the file.
* @param {Boolean} [inline] Default: false. If inline is false, content-disposition header is attachment.
* @returns {String} binary
*/
async pdf(fileId, inline = false) {
const response = await this._client.get(`/${this._entityName}/${this._entityId}/files/${fileId}/pdf`, { inline: inline })
return response.data()
}
/**
* @typedef {Object} LinkedEntity The model to change the entity information of the file.
* @property {String} entityId The id of the entity the file should be linked to.
* @property {String} entityType The type of the linked entity.
*/
/**
* Copys the file to a new entity (meta and content).
* @param {String} fileId The id of the file.
* @param {LinkedEntity} entity The entity to copy the file to.
* @returns {Promise<void>}
*/
async copy(fileId, entity) {
const response = await this._client.post(`/${this._entityName}/${this._entityId}/files/${fileId}/copy`, entity)
return response.data()
}
/**
* Currently only allowed in the projects entity. Returns all files of the entity with the specified id.
* @returns {Promise<Array<EntityFile>>}
*/
async allFiles() {
const response = await this._client.get(`/${this._entityName}/${this._entityId}/allfiles`)
const data = response.data()
return data.map(d => new EntityFile(d))
}
/**
* Returns a url to share the file.
* @param {String} fileId The id of the file.
* @returns {Promise<String>}
*/
async shareUrl(fileId) {
const response = await this._client.get(`/${this._entityName}/${this._entityId}/files/${fileId}/shareurl`)
return response.data()
}
/**
* Changes the entity this file belongs to. Switch to the specified entity or to a global file if the 'EntityId' of the model is set to null.
* @param {String} fileId The id of the file.
* @param {LinkedEntity} entity The entity to move the file to.
* @returns {Promise<void>}
*/
async changeEntity(fileId, entity) {
const response = await this._client.post(`/${this._entityName}/${this._entityId}/files/${fileId}/changeentity`, entity)
return response.data()
}
/**
* Returns the {@link FileVersions} Endpoint with the specified entity name, entity id and file Id.
* @param {String} fileId The id of the file.
* @returns {FileVersions}
*/
versions(fileId) {
return new FileVersions(this._client, this._entityName, this._entityId, fileId)
}
}
Source