files.com
Version:
Files.com SDK for JavaScript
990 lines (753 loc) • 34.6 kB
JavaScript
import Readable from 'readable-stream'
import { Buffer } from 'safe-buffer'
/* eslint-disable no-unused-vars */
import Api from '../Api'
import * as errors from '../Errors'
import {
isBrowser, getType, isArray, isInt, isObject, isString,
} from '../utils'
/* eslint-enable no-unused-vars */
/**
* Class File
*/
class File {
attributes = {}
options = {}
constructor(attributes = {}, options = {}) {
Object.entries(attributes).forEach(([key, value]) => {
const normalizedKey = key.replace('?', '')
this.attributes[normalizedKey] = value
Object.defineProperty(this, normalizedKey, { value, writable: false })
})
this.options = { ...options }
}
isLoaded = () => !!this.attributes.path
static _openUpload = async (path, paramsRaw, options) => {
const params = { ...paramsRaw, action: 'put' }
const response = await Api.sendRequest(`/files/${encodeURIComponent(path)}`, 'POST', params, options)
if (!response) {
return null
}
const partData = {
...response.data,
headers: response.headers,
parameters: params,
}
const FileUploadPart = require('./FileUploadPart.js').default
return new FileUploadPart(partData)
}
static _continueUpload = async (path, partNumber, firstFileUploadPart, options) => {
const params = {
action: 'put',
part: partNumber,
ref: firstFileUploadPart.ref,
}
const response = await Api.sendRequest(`/files/${encodeURIComponent(path)}`, 'POST', params, options)
if (!response) {
return null
}
const partData = {
...response.data,
headers: response.headers,
parameters: params,
}
const FileUploadPart = require('./FileUploadPart.js').default
return new FileUploadPart(partData)
}
static _completeUpload = async (firstFileUploadPart, options) => {
const params = {
action: 'end',
ref: firstFileUploadPart.ref,
}
return Api.sendRequest(`/files/${encodeURIComponent(firstFileUploadPart.path)}`, 'POST', params, options)
}
/**
* @note see File.copy() for list of supported params
*/
static uploadStream = async (destinationPath, readableStream, params, optionsRaw) => {
const { determinePartUploadUri: determinePartUploadUriRaw, ...options } = optionsRaw || {}
const firstFileUploadPart = await File._openUpload(destinationPath, params, options)
if (!firstFileUploadPart) {
return null
}
const determinePartUploadUri = determinePartUploadUriRaw || (fileUploadPart => fileUploadPart.upload_uri)
try {
const file = await new Promise((resolve, reject) => {
let part = 0
let chunks = []
let length = 0
const concurrentUploads = []
let chunkBuffer = null
let streamEnded = false
const handleStreamEnd = async () => {
if (chunkBuffer !== null || !streamEnded) {
return
}
try {
if (chunks.length > 0) {
const buffer = Buffer.concat(chunks)
const nextFileUploadPart = await File._continueUpload(destinationPath, ++part, firstFileUploadPart, options)
const uploadUri = determinePartUploadUri(nextFileUploadPart)
// instantiate an httpsAgent dynamically if needed
const agent = options.getAgentForUrl?.(uploadUri) || options?.agent
concurrentUploads.push(Api.sendFilePart(uploadUri, 'PUT', buffer, { agent }))
}
await Promise.all(concurrentUploads)
const response = await File._completeUpload(firstFileUploadPart, options)
const createdFile = new File(response.data, options)
resolve(createdFile)
} catch (error) {
reject(error)
}
}
readableStream.on('error', error => { reject(error) })
// note that for a network stream, each chunk is typically less than partsize * 2, but
// if a stream has been created based on very large data, it's possible for a chunk to
// contain the entire file and we could get a single chunk with length >= partsize * 3
readableStream.on('data', async chunk => {
try {
let excessLength = (length + chunk.length) - firstFileUploadPart.partsize
chunkBuffer = Buffer.from(chunk)
if (excessLength > 0) {
readableStream.pause()
while (chunkBuffer) {
// the amount to append this last part with to make it exactly the full partsize
const lengthForEndOfCurrentPart = chunkBuffer.length - excessLength
const lastChunkForCurrentPart = chunkBuffer.subarray(0, lengthForEndOfCurrentPart)
const chunkBufferAfterCurrentPart = chunkBuffer.subarray(lengthForEndOfCurrentPart)
chunks.push(lastChunkForCurrentPart)
const buffer = Buffer.concat(chunks)
/* eslint-disable-next-line no-await-in-loop */
const nextFileUploadPart = await File._continueUpload(destinationPath, ++part, firstFileUploadPart, options)
const uploadUri = determinePartUploadUri(nextFileUploadPart)
// instantiate an httpsAgent dynamically if needed
const agent = options.getAgentForUrl?.(uploadUri) || options?.agent
const uploadPromise = Api.sendFilePart(uploadUri, 'PUT', buffer, { agent })
if (firstFileUploadPart.parallel_parts) {
concurrentUploads.push(uploadPromise)
} else {
/* eslint-disable-next-line no-await-in-loop */
await uploadPromise
}
// determine if the remainder of the excess chunk data is too large to be a single part
const isNextChunkAtLeastOnePart = chunkBufferAfterCurrentPart.length >= firstFileUploadPart.partsize
// the excess data contains >= 1 full part, so we'll loop again to enqueue
// the next part for upload and continue processing any excess beyond that
if (isNextChunkAtLeastOnePart) {
chunks = []
length = 0
chunkBuffer = chunkBufferAfterCurrentPart
excessLength = chunkBuffer.length - firstFileUploadPart.partsize
// the excess data is less than a full part, so we'll enqueue it
} else if (chunkBufferAfterCurrentPart.length > 0) {
chunks = [chunkBufferAfterCurrentPart]
length = chunkBufferAfterCurrentPart.length
chunkBuffer = null
} else {
chunkBuffer = null
}
}
readableStream.resume()
} else {
chunks.push(chunkBuffer)
length += chunk.length
chunkBuffer = null
}
if (streamEnded) {
handleStreamEnd()
}
} catch (error) {
reject(error)
}
})
// note that this event may occur while there is still data being processed above
readableStream.on('end', () => {
streamEnded = true
handleStreamEnd()
})
})
return file
} catch (error) {
errors.handleErrorResponse(error)
return null
}
}
/**
* data - string, Buffer, Stream, any object implementing Symbol.iterator or Symbol.asyncIterator
* @note see File.copy() for list of supported params
*/
static uploadData = async (destinationPath, data, params, options) => {
if (!data) {
throw new errors.MissingParameterError('Upload data was not provided')
}
return File.uploadStream(destinationPath, Readable.from(data), params, options)
}
/**
* @note see File.copy() for list of supported params
*/
static uploadFile = async (destinationPath, sourceFilePath, params, options) => {
if (isBrowser()) {
throw new errors.NotImplementedError('Disk file uploads are only available in a NodeJS environment')
}
const { openDiskFileReadStream } = require('../isomorphic/File.node.js')
const stream = openDiskFileReadStream(sourceFilePath)
return File.uploadStream(destinationPath, stream, params, options)
}
downloadToStream = async writableStream => {
if (isBrowser()) {
throw new errors.NotImplementedError('Stream downloads are only available in a NodeJS environment')
}
const downloadUri = this.getDownloadUri()
if (!downloadUri) {
throw new errors.EmptyPropertyError('Current object has no download URI')
}
const { saveUrlToStream } = require('../isomorphic/File.node.js')
return saveUrlToStream(downloadUri, writableStream)
}
downloadToString = async () => {
if (isBrowser()) {
throw new errors.NotImplementedError('String downloads are only available in a NodeJS environment')
}
const downloadUri = this.getDownloadUri()
if (!downloadUri) {
throw new errors.EmptyPropertyError('Current object has no download URI')
}
const { saveUrlToString } = require('../isomorphic/File.node.js')
return saveUrlToString(downloadUri)
}
downloadToFile = async destinationPath => {
if (isBrowser()) {
throw new errors.NotImplementedError('Disk file downloads are only available in a NodeJS environment')
}
const downloadUri = this.getDownloadUri()
if (!downloadUri) {
throw new errors.EmptyPropertyError('Current object has no download URI')
}
const { saveUrlToFile } = require('../isomorphic/File.node.js')
return saveUrlToFile(downloadUri, destinationPath)
}
copyTo = async (destinationFilePath, options) => {
const params = { destination: destinationFilePath }
return Api.sendRequest(`/file_actions/copy/${encodeURIComponent(this.path)}`, 'POST', params, options)
}
moveTo = async (destinationFilePath, options) => {
const params = { destination: destinationFilePath }
return Api.sendRequest(`/file_actions/move/${encodeURIComponent(this.path)}`, 'POST', params, options)
}
// string # File/Folder path. This must be slash-delimited, but it must neither start nor end with a slash. Maximum of 5000 characters.
getPath = () => this.attributes.path
setPath = value => {
this.attributes.path = value
}
// int64 # User ID of the User who created the file/folder
getCreatedById = () => this.attributes.created_by_id
setCreatedById = value => {
this.attributes.created_by_id = value
}
// int64 # ID of the API key that created the file/folder
getCreatedByApiKeyId = () => this.attributes.created_by_api_key_id
setCreatedByApiKeyId = value => {
this.attributes.created_by_api_key_id = value
}
// int64 # ID of the AS2 Incoming Message that created the file/folder
getCreatedByAs2IncomingMessageId = () => this.attributes.created_by_as2_incoming_message_id
setCreatedByAs2IncomingMessageId = value => {
this.attributes.created_by_as2_incoming_message_id = value
}
// int64 # ID of the Automation that created the file/folder
getCreatedByAutomationId = () => this.attributes.created_by_automation_id
setCreatedByAutomationId = value => {
this.attributes.created_by_automation_id = value
}
// int64 # ID of the Bundle Registration that created the file/folder
getCreatedByBundleRegistrationId = () => this.attributes.created_by_bundle_registration_id
setCreatedByBundleRegistrationId = value => {
this.attributes.created_by_bundle_registration_id = value
}
// int64 # ID of the Inbox that created the file/folder
getCreatedByInboxId = () => this.attributes.created_by_inbox_id
setCreatedByInboxId = value => {
this.attributes.created_by_inbox_id = value
}
// int64 # ID of the Remote Server that created the file/folder
getCreatedByRemoteServerId = () => this.attributes.created_by_remote_server_id
setCreatedByRemoteServerId = value => {
this.attributes.created_by_remote_server_id = value
}
// int64 # ID of the Remote Server Sync that created the file/folder
getCreatedByRemoteServerSyncId = () => this.attributes.created_by_remote_server_sync_id
setCreatedByRemoteServerSyncId = value => {
this.attributes.created_by_remote_server_sync_id = value
}
// object # Custom metadata map of keys and values. Limited to 32 keys, 256 characters per key and 1024 characters per value.
getCustomMetadata = () => this.attributes.custom_metadata
setCustomMetadata = value => {
this.attributes.custom_metadata = value
}
// string # File/Folder display name
getDisplayName = () => this.attributes.display_name
setDisplayName = value => {
this.attributes.display_name = value
}
// string # Type: `directory` or `file`.
getType = () => this.attributes.type
setType = value => {
this.attributes.type = value
}
// int64 # File/Folder size
getSize = () => this.attributes.size
setSize = value => {
this.attributes.size = value
}
// date-time # File created date/time
getCreatedAt = () => this.attributes.created_at
// int64 # User ID of the User who last modified the file/folder
getLastModifiedById = () => this.attributes.last_modified_by_id
setLastModifiedById = value => {
this.attributes.last_modified_by_id = value
}
// int64 # ID of the API key that last modified the file/folder
getLastModifiedByApiKeyId = () => this.attributes.last_modified_by_api_key_id
setLastModifiedByApiKeyId = value => {
this.attributes.last_modified_by_api_key_id = value
}
// int64 # ID of the Automation that last modified the file/folder
getLastModifiedByAutomationId = () => this.attributes.last_modified_by_automation_id
setLastModifiedByAutomationId = value => {
this.attributes.last_modified_by_automation_id = value
}
// int64 # ID of the Bundle Registration that last modified the file/folder
getLastModifiedByBundleRegistrationId = () => this.attributes.last_modified_by_bundle_registration_id
setLastModifiedByBundleRegistrationId = value => {
this.attributes.last_modified_by_bundle_registration_id = value
}
// int64 # ID of the Remote Server that last modified the file/folder
getLastModifiedByRemoteServerId = () => this.attributes.last_modified_by_remote_server_id
setLastModifiedByRemoteServerId = value => {
this.attributes.last_modified_by_remote_server_id = value
}
// int64 # ID of the Remote Server Sync that last modified the file/folder
getLastModifiedByRemoteServerSyncId = () => this.attributes.last_modified_by_remote_server_sync_id
setLastModifiedByRemoteServerSyncId = value => {
this.attributes.last_modified_by_remote_server_sync_id = value
}
// date-time # File last modified date/time, according to the server. This is the timestamp of the last Files.com operation of the file, regardless of what modified timestamp was sent.
getMtime = () => this.attributes.mtime
setMtime = value => {
this.attributes.mtime = value
}
// date-time # File last modified date/time, according to the client who set it. Files.com allows desktop, FTP, SFTP, and WebDAV clients to set modified at times. This allows Desktop<->Cloud syncing to preserve modified at times.
getProvidedMtime = () => this.attributes.provided_mtime
setProvidedMtime = value => {
this.attributes.provided_mtime = value
}
// string # File CRC32 checksum. This is sometimes delayed, so if you get a blank response, wait and try again.
getCrc32 = () => this.attributes.crc32
setCrc32 = value => {
this.attributes.crc32 = value
}
// string # File MD5 checksum. This is sometimes delayed, so if you get a blank response, wait and try again.
getMd5 = () => this.attributes.md5
setMd5 = value => {
this.attributes.md5 = value
}
// string # File SHA1 checksum. This is sometimes delayed, so if you get a blank response, wait and try again.
getSha1 = () => this.attributes.sha1
setSha1 = value => {
this.attributes.sha1 = value
}
// string # File SHA256 checksum. This is sometimes delayed, so if you get a blank response, wait and try again.
getSha256 = () => this.attributes.sha256
setSha256 = value => {
this.attributes.sha256 = value
}
// string # MIME Type. This is determined by the filename extension and is not stored separately internally.
getMimeType = () => this.attributes.mime_type
setMimeType = value => {
this.attributes.mime_type = value
}
// string # Region location
getRegion = () => this.attributes.region
setRegion = value => {
this.attributes.region = value
}
// string # A short string representing the current user's permissions. Can be `r` (Read),`w` (Write),`d` (Delete), `l` (List) or any combination
getPermissions = () => this.attributes.permissions
setPermissions = value => {
this.attributes.permissions = value
}
// boolean # Are subfolders locked and unable to be modified?
getSubfoldersLocked = () => this.attributes.subfolders_locked
setSubfoldersLocked = value => {
this.attributes.subfolders_locked = value
}
// boolean # Is this folder locked and unable to be modified?
getIsLocked = () => this.attributes.is_locked
setIsLocked = value => {
this.attributes.is_locked = value
}
// string # Link to download file. Provided only in response to a download request.
getDownloadUri = () => this.attributes.download_uri
setDownloadUri = value => {
this.attributes.download_uri = value
}
// string # Bookmark/priority color of file/folder
getPriorityColor = () => this.attributes.priority_color
setPriorityColor = value => {
this.attributes.priority_color = value
}
// int64 # File preview ID
getPreviewId = () => this.attributes.preview_id
setPreviewId = value => {
this.attributes.preview_id = value
}
// Preview # File preview
getPreview = () => this.attributes.preview
setPreview = value => {
this.attributes.preview = value
}
// string # The action to perform. Can be `append`, `attachment`, `end`, `upload`, `put`, or may not exist
getAction = () => this.attributes.action
setAction = value => {
this.attributes.action = value
}
// int64 # Length of file.
getLength = () => this.attributes.length
setLength = value => {
this.attributes.length = value
}
// boolean # Create parent directories if they do not exist?
getMkdirParents = () => this.attributes.mkdir_parents
setMkdirParents = value => {
this.attributes.mkdir_parents = value
}
// int64 # Part if uploading a part.
getPart = () => this.attributes.part
setPart = value => {
this.attributes.part = value
}
// int64 # How many parts to fetch?
getParts = () => this.attributes.parts
setParts = value => {
this.attributes.parts = value
}
// string #
getRef = () => this.attributes.ref
setRef = value => {
this.attributes.ref = value
}
// int64 # File byte offset to restart from.
getRestart = () => this.attributes.restart
setRestart = value => {
this.attributes.restart = value
}
// string # If copying folder, copy just the structure?
getStructure = () => this.attributes.structure
setStructure = value => {
this.attributes.structure = value
}
// boolean # Allow file rename instead of overwrite?
getWithRename = () => this.attributes.with_rename
setWithRename = value => {
this.attributes.with_rename = value
}
// Download File
//
// Parameters:
// action - string - Can be blank, `redirect` or `stat`. If set to `stat`, we will return file information but without a download URL, and without logging a download. If set to `redirect` we will serve a 302 redirect directly to the file. This is used for integrations with Zapier, and is not recommended for most integrations.
// preview_size - string - Request a preview size. Can be `small` (default), `large`, `xlarge`, or `pdf`.
// with_previews - boolean - Include file preview information?
// with_priority_color - boolean - Include file priority color information?
download = async (params = {}) => {
if (!this.attributes.path) {
throw new errors.EmptyPropertyError('Current object has no path')
}
if (!isObject(params)) {
throw new errors.InvalidParameterError(`Bad parameter: params must be of type object, received ${getType(params)}`)
}
params.path = this.attributes.path
if (params.path && !isString(params.path)) {
throw new errors.InvalidParameterError(`Bad parameter: path must be of type String, received ${getType(params.path)}`)
}
if (params.action && !isString(params.action)) {
throw new errors.InvalidParameterError(`Bad parameter: action must be of type String, received ${getType(params.action)}`)
}
if (params.preview_size && !isString(params.preview_size)) {
throw new errors.InvalidParameterError(`Bad parameter: preview_size must be of type String, received ${getType(params.preview_size)}`)
}
if (!params.path) {
if (this.attributes.path) {
params.path = this.path
} else {
throw new errors.MissingParameterError('Parameter missing: path')
}
}
const response = await Api.sendRequest(`/files/${encodeURIComponent(params.path)}`, 'GET', params, this.options)
return new File(response?.data, this.options)
}
// Parameters:
// custom_metadata - object - Custom metadata map of keys and values. Limited to 32 keys, 256 characters per key and 1024 characters per value.
// provided_mtime - string - Modified time of file.
// priority_color - string - Priority/Bookmark color of file.
update = async (params = {}) => {
if (!this.attributes.path) {
throw new errors.EmptyPropertyError('Current object has no path')
}
if (!isObject(params)) {
throw new errors.InvalidParameterError(`Bad parameter: params must be of type object, received ${getType(params)}`)
}
params.path = this.attributes.path
if (params.path && !isString(params.path)) {
throw new errors.InvalidParameterError(`Bad parameter: path must be of type String, received ${getType(params.path)}`)
}
if (params.provided_mtime && !isString(params.provided_mtime)) {
throw new errors.InvalidParameterError(`Bad parameter: provided_mtime must be of type String, received ${getType(params.provided_mtime)}`)
}
if (params.priority_color && !isString(params.priority_color)) {
throw new errors.InvalidParameterError(`Bad parameter: priority_color must be of type String, received ${getType(params.priority_color)}`)
}
if (!params.path) {
if (this.attributes.path) {
params.path = this.path
} else {
throw new errors.MissingParameterError('Parameter missing: path')
}
}
const response = await Api.sendRequest(`/files/${encodeURIComponent(params.path)}`, 'PATCH', params, this.options)
return new File(response?.data, this.options)
}
// Parameters:
// recursive - boolean - If true, will recursively delete folders. Otherwise, will error on non-empty folders.
delete = async (params = {}) => {
if (!this.attributes.path) {
throw new errors.EmptyPropertyError('Current object has no path')
}
if (!isObject(params)) {
throw new errors.InvalidParameterError(`Bad parameter: params must be of type object, received ${getType(params)}`)
}
params.path = this.attributes.path
if (params.path && !isString(params.path)) {
throw new errors.InvalidParameterError(`Bad parameter: path must be of type String, received ${getType(params.path)}`)
}
if (!params.path) {
if (this.attributes.path) {
params.path = this.path
} else {
throw new errors.MissingParameterError('Parameter missing: path')
}
}
await Api.sendRequest(`/files/${encodeURIComponent(params.path)}`, 'DELETE', params, this.options)
}
destroy = (params = {}) =>
this.delete(params)
// Copy File/Folder
//
// Parameters:
// destination (required) - string - Copy destination path.
// structure - boolean - Copy structure only?
// overwrite - boolean - Overwrite existing file(s) in the destination?
copy = async (params = {}) => {
if (!this.attributes.path) {
throw new errors.EmptyPropertyError('Current object has no path')
}
if (!isObject(params)) {
throw new errors.InvalidParameterError(`Bad parameter: params must be of type object, received ${getType(params)}`)
}
params.path = this.attributes.path
if (params.path && !isString(params.path)) {
throw new errors.InvalidParameterError(`Bad parameter: path must be of type String, received ${getType(params.path)}`)
}
if (params.destination && !isString(params.destination)) {
throw new errors.InvalidParameterError(`Bad parameter: destination must be of type String, received ${getType(params.destination)}`)
}
if (!params.path) {
if (this.attributes.path) {
params.path = this.path
} else {
throw new errors.MissingParameterError('Parameter missing: path')
}
}
if (!params.destination) {
if (this.attributes.destination) {
params.destination = this.destination
} else {
throw new errors.MissingParameterError('Parameter missing: destination')
}
}
const response = await Api.sendRequest(`/file_actions/copy/${encodeURIComponent(params.path)}`, 'POST', params, this.options)
const FileAction = require('./FileAction.js').default
return new FileAction(response?.data, this.options)
}
// Move File/Folder
//
// Parameters:
// destination (required) - string - Move destination path.
// overwrite - boolean - Overwrite existing file(s) in the destination?
move = async (params = {}) => {
if (!this.attributes.path) {
throw new errors.EmptyPropertyError('Current object has no path')
}
if (!isObject(params)) {
throw new errors.InvalidParameterError(`Bad parameter: params must be of type object, received ${getType(params)}`)
}
params.path = this.attributes.path
if (params.path && !isString(params.path)) {
throw new errors.InvalidParameterError(`Bad parameter: path must be of type String, received ${getType(params.path)}`)
}
if (params.destination && !isString(params.destination)) {
throw new errors.InvalidParameterError(`Bad parameter: destination must be of type String, received ${getType(params.destination)}`)
}
if (!params.path) {
if (this.attributes.path) {
params.path = this.path
} else {
throw new errors.MissingParameterError('Parameter missing: path')
}
}
if (!params.destination) {
if (this.attributes.destination) {
params.destination = this.destination
} else {
throw new errors.MissingParameterError('Parameter missing: destination')
}
}
const response = await Api.sendRequest(`/file_actions/move/${encodeURIComponent(params.path)}`, 'POST', params, this.options)
const FileAction = require('./FileAction.js').default
return new FileAction(response?.data, this.options)
}
// Begin File Upload
//
// Parameters:
// mkdir_parents - boolean - Create parent directories if they do not exist?
// part - int64 - Part if uploading a part.
// parts - int64 - How many parts to fetch?
// ref - string -
// restart - int64 - File byte offset to restart from.
// size - int64 - Total bytes of file being uploaded (include bytes being retained if appending/restarting).
// with_rename - boolean - Allow file rename instead of overwrite?
beginUpload = async (params = {}) => {
if (!this.attributes.path) {
throw new errors.EmptyPropertyError('Current object has no path')
}
if (!isObject(params)) {
throw new errors.InvalidParameterError(`Bad parameter: params must be of type object, received ${getType(params)}`)
}
params.path = this.attributes.path
if (params.path && !isString(params.path)) {
throw new errors.InvalidParameterError(`Bad parameter: path must be of type String, received ${getType(params.path)}`)
}
if (params.part && !isInt(params.part)) {
throw new errors.InvalidParameterError(`Bad parameter: part must be of type Int, received ${getType(params.part)}`)
}
if (params.parts && !isInt(params.parts)) {
throw new errors.InvalidParameterError(`Bad parameter: parts must be of type Int, received ${getType(params.parts)}`)
}
if (params.ref && !isString(params.ref)) {
throw new errors.InvalidParameterError(`Bad parameter: ref must be of type String, received ${getType(params.ref)}`)
}
if (params.restart && !isInt(params.restart)) {
throw new errors.InvalidParameterError(`Bad parameter: restart must be of type Int, received ${getType(params.restart)}`)
}
if (params.size && !isInt(params.size)) {
throw new errors.InvalidParameterError(`Bad parameter: size must be of type Int, received ${getType(params.size)}`)
}
if (!params.path) {
if (this.attributes.path) {
params.path = this.path
} else {
throw new errors.MissingParameterError('Parameter missing: path')
}
}
const response = await Api.sendRequest(`/file_actions/begin_upload/${encodeURIComponent(params.path)}`, 'POST', params, this.options)
const FileUploadPart = require('./FileUploadPart.js').default
return response?.data?.map(obj => new FileUploadPart(obj, this.options)) || []
}
save = async () => {
const newObject = await File.create(this.attributes.path, this.attributes, this.options)
this.attributes = { ...newObject.attributes }
return true
}
// Parameters:
// path (required) - string - Path to operate on.
// action - string - The action to perform. Can be `append`, `attachment`, `end`, `upload`, `put`, or may not exist
// etags[etag] (required) - array(string) - etag identifier.
// etags[part] (required) - array(int64) - Part number.
// length - int64 - Length of file.
// mkdir_parents - boolean - Create parent directories if they do not exist?
// part - int64 - Part if uploading a part.
// parts - int64 - How many parts to fetch?
// provided_mtime - string - User provided modification time.
// ref - string -
// restart - int64 - File byte offset to restart from.
// size - int64 - Size of file.
// structure - string - If copying folder, copy just the structure?
// with_rename - boolean - Allow file rename instead of overwrite?
static create = async (path, params = {}, options = {}) => {
if (!isObject(params)) {
throw new errors.InvalidParameterError(`Bad parameter: params must be of type object, received ${getType(params)}`)
}
params.path = path
if (!params.path) {
throw new errors.MissingParameterError('Parameter missing: path')
}
if (params.path && !isString(params.path)) {
throw new errors.InvalidParameterError(`Bad parameter: path must be of type String, received ${getType(params.path)}`)
}
if (params.action && !isString(params.action)) {
throw new errors.InvalidParameterError(`Bad parameter: action must be of type String, received ${getType(params.action)}`)
}
if (params.length && !isInt(params.length)) {
throw new errors.InvalidParameterError(`Bad parameter: length must be of type Int, received ${getType(params.length)}`)
}
if (params.part && !isInt(params.part)) {
throw new errors.InvalidParameterError(`Bad parameter: part must be of type Int, received ${getType(params.part)}`)
}
if (params.parts && !isInt(params.parts)) {
throw new errors.InvalidParameterError(`Bad parameter: parts must be of type Int, received ${getType(params.parts)}`)
}
if (params.provided_mtime && !isString(params.provided_mtime)) {
throw new errors.InvalidParameterError(`Bad parameter: provided_mtime must be of type String, received ${getType(params.provided_mtime)}`)
}
if (params.ref && !isString(params.ref)) {
throw new errors.InvalidParameterError(`Bad parameter: ref must be of type String, received ${getType(params.ref)}`)
}
if (params.restart && !isInt(params.restart)) {
throw new errors.InvalidParameterError(`Bad parameter: restart must be of type Int, received ${getType(params.restart)}`)
}
if (params.size && !isInt(params.size)) {
throw new errors.InvalidParameterError(`Bad parameter: size must be of type Int, received ${getType(params.size)}`)
}
if (params.structure && !isString(params.structure)) {
throw new errors.InvalidParameterError(`Bad parameter: structure must be of type String, received ${getType(params.structure)}`)
}
const response = await Api.sendRequest(`/files/${encodeURIComponent(params.path)}`, 'POST', params, options)
return new File(response?.data, options)
}
// Parameters:
// path (required) - string - Path to operate on.
// preview_size - string - Request a preview size. Can be `small` (default), `large`, `xlarge`, or `pdf`.
// with_previews - boolean - Include file preview information?
// with_priority_color - boolean - Include file priority color information?
static find = async (path, params = {}, options = {}) => {
if (!isObject(params)) {
throw new errors.InvalidParameterError(`Bad parameter: params must be of type object, received ${getType(params)}`)
}
params.path = path
if (!params.path) {
throw new errors.MissingParameterError('Parameter missing: path')
}
if (params.path && !isString(params.path)) {
throw new errors.InvalidParameterError(`Bad parameter: path must be of type String, received ${getType(params.path)}`)
}
if (params.preview_size && !isString(params.preview_size)) {
throw new errors.InvalidParameterError(`Bad parameter: preview_size must be of type String, received ${getType(params.preview_size)}`)
}
const response = await Api.sendRequest(`/file_actions/metadata/${encodeURIComponent(params.path)}`, 'GET', params, options)
return new File(response?.data, options)
}
static get = (path, params = {}, options = {}) =>
File.find(path, params, options)
}
export default File
module.exports = File
module.exports.default = File