@adobe/aio-lib-files
Version:
An abstraction on top of blob cloud storage exposing a file like API
406 lines (394 loc) • 17.3 kB
TypeScript
/**
* Read, Write, Delete permission enum
*/
export type FilePermissions = any;
/**
* external, internal URL type enum
*/
export type UrlType = any;
/**
* Cloud Files Abstraction
*/
export class Files {
/**
* @param filePath - {@link RemotePathString}
* @returns normalized path
*/
protected static _normalizeRemotePath(filePath: RemotePathString): string;
/**
* @param filePath - {@link RemotePathString}
* @returns true if it's the root
*/
protected static _isRemoteRoot(filePath: RemotePathString): boolean;
/**
* @param filePath - {@link RemotePathString}
* @returns true if the file is public
*/
protected static _isRemotePublic(filePath: RemotePathString): boolean;
/**
* @param filePath - {@link RemotePathString}
* @returns true if path is a directory
*/
protected static _isRemoteDirectory(filePath: RemotePathString): boolean;
/**
* @param filePath - {@link RemotePathString}
* @param details - pass details to error for debugging purpose (e.g. calling function params)
*/
protected static _throwIfRemoteDirectory(filePath: RemotePathString, details: any): void;
/**
* Reads a stream into a buffer
* @param stream - readableStream
* @returns buffer
*/
protected static _readStream(stream: NodeJS.ReadableStream): Promise<Buffer>;
/**
* Wraps errors for request to the cloud provider
* @param requestPromise - the promise resolving to the response or error
* @param details - pass details to error for debugging purpose (e.g. pass function params)
* @param filePathToThrowOn404 - path to the file on which the request was made, if specified will throw on 404
* @returns promise resolving to same value as requestPromise
*/
protected _wrapProviderRequest(requestPromise: Promise, details: any, filePathToThrowOn404: string): Promise;
/**
* @param filePath - {@link RemotePathString}
* @returns resolves to array of {@link RemoteFileProperties}
*/
protected _listFolder(filePath: RemotePathString): Promise<RemoteFileProperties[]>;
/**
* @param filePath - {@link RemotePathString}
* @returns resolves to boolean
*/
protected _fileExists(filePath: RemotePathString): Promise<boolean>;
/**
* @param filePath - {@link RemotePathString}
* @returns resolves to boolean
*/
protected _deleteFile(filePath: RemotePathString): Promise<boolean>;
/**
* @param filePath - {@link RemotePathString}
* @returns resolve to {@link RemoteFileProperties}
*/
protected getFileInfo(filePath: RemotePathString): Promise<RemoteFileProperties>;
/**
* **NODEJS ONLY**
* @param filePath - {@link RemotePathString}
* @param [options = {}] - createReadStreamOptions
* @param [options.position] - read start position of the file. By default is set to 0. If set to bigger than
* size, throws an ERROR_OUT_OF_RANGE error
* @param [options.length] - number of bytes to read. By default reads everything since starting position. If
* set to bigger than file size, reads until end.
* @returns a readable stream
*/
protected _createReadStream(filePath: RemotePathString, options?: {
position?: number;
length?: number;
}): Promise<NodeJS.ReadableStream>;
/**
* **NODEJS ONLY**
* @param filePath - {@link RemotePathString}
* @returns a writable stream
*/
protected _createWriteStream(filePath: RemotePathString): Promise<NodeJS.WritableStream>;
/**
* **NODEJS ONLY**
* @param filePath - {@link RemotePathString}
* @param content - to be written
* @returns resolves to number of bytes written
*/
protected _writeStream(filePath: RemotePathString, content: NodeJS.ReadableStream): Promise<number>;
/**
* @param filePath - {@link RemotePathString}
* @param content - to be written
* @returns resolves to number of bytes written
*/
protected _writeBuffer(filePath: RemotePathString, content: Buffer): Promise<number>;
/**
* **Does not work for directories.**
* copies a file from a remote location to another.
* @param srcPath - {@link RemotePathString}
* @param destPath - {@link RemotePathString}
*/
protected _copyRemoteToRemoteFile(srcPath: RemotePathString, destPath: RemotePathString): void;
/**
* @param filePath - {@link RemotePathString}
* @param urlType - type of URL to return public | runtime, defaults to external
* @returns resolves to url
*/
protected _getUrl(filePath: RemotePathString, urlType: string): string;
/**
* [INTERNAL]
* @param e - provider error response
* @returns status code
*/
protected _statusFromProviderError(e: Error): number;
/**
* Lists files. Depending on the input the behavior is different:
* - If a path has a trailing '/' it is considered as a directory and
* list returns files recursively contained below that path. If the
* directory is empty, an empty array is returned.
* - If a path has no trailing '/' it will ALWAYS be considered a file and we
* will return the file (and its properties) in an array. If that file
* doesn't exist we return an empty array EVEN if listing a directory with the
* same name would return some files (directories are subpaths, not entities per se).
* @param [filePath] - {@link RemotePathString} Use a
* trailing '/' otherwise this is considered as a file. If not specified
* list all files.
* @returns resolves to array of
* {@link RemoteFileProperties}
*/
public list(filePath?: RemotePathString): Promise<RemoteFileProperties[]>;
/**
* Deletes a remote file or directory
* @param filePath - {@link RemotePathString}
* @param [options = {}] - remoteDeleteOptions
* @param [options.progressCallback] - cb(RemoteFile) is called after
* the operation completed on each file
* @returns resolves to array of deleted paths
*/
public delete(filePath: RemotePathString, options?: {
progressCallback?: (...params: any[]) => any;
}): Promise<string[]>;
/**
* ***NodeJS only (streams). Does not work on directories.***
*
* Creates a read stream
* @param filePath - {@link RemotePathString}
* @param [options = {}] - createReadStreamOptions
* @param [options.position] - read start position of the file. By default is set to 0. If set to bigger than
* size, throws an ERROR_OUT_OF_RANGE error
* @param [options.length] - number of bytes to read. By default reads everything since starting position. If
* set to bigger than file size, reads until end.
* @returns a readable stream
*/
public createReadStream(filePath: RemotePathString, options?: {
position?: number;
length?: number;
}): Promise<NodeJS.ReadableStream>;
/**
* **[UNSTABLE] please prefer using `write(<NodeJS.ReadableStream>)`**
*
* ***NodeJS only (streams). Does not work on directories.***
*
* Returns a write stream.
* Use `stream.on('finish', (bytesWritten) => {})` to listen on completion event
* @param filePath - {@link RemotePathString}
* @returns a writable stream
*/
public createWriteStream(filePath: RemotePathString): Promise<NodeJS.WritableStream>;
/**
* ***Does not work on directories.***
*
* Reads a remote file content
* @param filePath - {@link RemotePathString}
* @param [options = {}] - remoteReadOptions
* @param [options.position] - read start position of the file. By default is set to 0. If set to bigger than
* size, throws an ERROR_OUT_OF_RANGE error
* @param [options.length] - number of bytes to read. By default reads everything since starting position. If
* set to bigger than file size, reads until end.
* @returns buffer holding content
*/
public read(filePath: RemotePathString, options?: {
position?: number;
length?: number;
}): Promise<Buffer>;
/**
* ***Does not work on directories.***
*
* Writes content to a file
* @param filePath - {@link RemotePathString}
* @param content - to be written,
* `ReadableStream` input works for **NodeJS only**
* @returns resolves to number of bytes written
*/
public write(filePath: RemotePathString, content: string | Buffer | NodeJS.ReadableStream): Promise<number>;
/**
* Reads properties of a file or directory
* @param filePath - {@link RemotePathString}
* @returns resolves {@link RemoteFileProperties}
*/
getProperties(filePath: RemotePathString): Promise<RemoteFileProperties>;
/**
* ***NodeJS only (streams + fs).***
*
* A utility function to copy files and directories across remote and local Files. This
* is comparable to the `scp` command
*
* Rules for copy files are:
* 1. Remote => Remote
* - a/ (dir) => b/: b/a/
* - a (file) => b/: b/a *does nothing if b/a exists and noOverwrite=true*
* - a (file) => b : b *does nothing if b exists and noOverwrite=true*
* - a/ (dir) => b : b/ *always allowed: in remote Files we can have both b and b/*
* 2. Remote => Local
* - a/ => b/: b/a/
* - a => b/: b/a *does nothing if b/a exists and noOverwrite=true*
* - a => b : b *does nothing if b exists and noOverwrite=true*
* - a/ => b : b/ *throws an error if b exists and is a file: cannot copy a remote
* dir to a local file*
* 3. Local => Remote
* - a/ => b/: b/a/
* - a => b/: b/a *does nothing if b/a exists and noOverwrite=true*
* - a => b : b *does nothing if b exists and noOverwrite=true*
* - a/ => b: b/ *always allowed: in remote Files we can have both b and b/*
* 4. Local => Local
* - not supported
* @param srcPath - copy source path to a file or directory. If srcPath
* points to a local file set `options.localSrc` to true
* @param destPath - copy destination path to a file or directory. If
* destPath points to a local file set `options.localDest` to true
* @param [options = {}] - remoteCopyOptions
* @param [options.localSrc = false] - Set this option to true to copy files
* from the local file system. Cannot be combined with localDest.
* @param [options.localDest = false] - Set this option to true to copy files to
* the local file system. Cannot be combined with localSrc.
* @param [options.noOverwrite = false] - set to true to not overwrite existing
* dest files
* @param [options.progressCallback] - a function that will be called every
* time the operation completes on a single file,the srcPath and destPath to the copied
* file are passed as argument to the callback `progressCallback(srcPath, destPath)`
* @returns returns a promise resolving to an object
* containing all copied files from src to dest `{ srcFilePath: destFilePath }`
*/
copy(srcPath: RemotePathString, destPath: RemotePathString, options?: {
localSrc?: boolean;
localDest?: boolean;
noOverwrite?: boolean;
progressCallback?: (...params: any[]) => any;
}): Promise<{ key: string; }>;
/**
* Generate pre-sign URLs for a private file
* @param filePath - {@link RemotePathString}
* @param options - Options to generate presign URL
* @param options.expiryInSeconds - presign URL expiry duration
* @param options.permissions - permissions for presigned URL (any combination of rwd)
* @param options.urlType - default 'external', type of URL to return 'internal' or 'external'
* @returns Presign URL for the given file
*/
generatePresignURL(filePath: RemotePathString, options: {
expiryInSeconds: number;
permissions: string;
urlType: string;
}): Promise<string>;
/**
* Revoke all generated pre-sign URLs
*/
revokeAllPresignURLs(): void;
}
/**
* Initializes and returns the cloud files SDK.
*
* To use the SDK you must either provide provide your
* [OpenWhisk credentials]{@link OpenWhiskCredentials} in
* `credentials.ow` or your own
* [Azure blob storage credentials]{@link AzureCredentialsAccount} in `credentials.azure`.
*
* OpenWhisk credentials can also be read from environment variables (`__OW_NAMESPACE` and `__OW_API_KEY`).
* @param [config = {}] - configuration used to init the sdk
* @param [config.ow] - {@link OpenWhiskCredentials}. Set those if you want
* to use ootb credentials to access the state management service. OpenWhisk
* namespace and auth can also be passed through environment variables:
* `__OW_NAMESPACE` and `__OW_API_KEY`
* @param [config.azure] - bring your own [Azure SAS credentials]{@link AzureCredentialsSAS} or
* [Azure storage account credentials]{@link AzureCredentialsAccount}
* @param [config.tvm] - tvm configuration, applies only when passing OpenWhisk credentials
* @param [config.tvm.apiUrl] - alternative tvm api url.
* @param [config.tvm.cacheFile] - alternative tvm cache file, set to `false` to disable caching of temporary credentials.
* @returns A Files instance
*/
export function init(config?: {
ow?: OpenWhiskCredentials;
azure?: AzureCredentialsAccount | AzureCredentialsSAS;
tvm?: {
apiUrl?: string;
cacheFile?: string;
};
}): Promise<Files>;
/**
* An object holding the OpenWhisk credentials
* @property namespace - user namespace
* @property auth - auth key
*/
export type OpenWhiskCredentials = {
namespace: string;
auth: string;
};
/**
* SAS Azure credentials. The sdk needs two SAS credentials to allow access to
* two already existing containers, a private and a public one (with access=`blob`).
* @property sasURLPrivate - sas url to existing private azure blob
* container
* @property sasURLPublic - sas url to existing public (with
* access=`blob`) azure blob container
*/
export type AzureCredentialsSAS = {
sasURLPrivate: string;
sasURLPublic: string;
};
/**
* Azure account credentials. Must have the permission to create containers.
* @property storageAccount - name of azure storage account
* @property storageAccessKey - access key for azure storage account
* @property containerName - name of container to store files.
* Another `${containerName}-public` will also be used for public files.
* @property [hostName] - custom domain for returned URLs
*/
export type AzureCredentialsAccount = {
storageAccount: string;
storageAccessKey: string;
containerName: string;
hostName?: string;
};
/**
* a string to the remote path. If the path ends with a `/` it will
* be treated as a directory, if not it will be treated as a file.
*/
export type RemotePathString = string;
/**
* File properties
* @property name - unique name of this file, it is the full path
* @property creationTime - utc datetime string when file was created
* @property lastModified - utc datetime string when file last modified
* @property etag - unique ( per modification ) etag for the asset
* @property contentLength - size, in bytes
* @property contentType - mime/type
* @property isDirectory - true if file is a directory
* @property isPublic - true if file is public
* @property url - remote file URL with URI encoded path, use decodeURIComponent to decode the URL.
* @property internalUrl - remote file URL which allows file access only from Adobe I/O Runtime actions.
*/
export type RemoteFileProperties = {
name: string;
creationTime: string;
lastModified: string;
etag: string;
contentLength: number;
contentType: string;
isDirectory: boolean;
isPublic: boolean;
url: string;
internalUrl: string;
};
export type FilesLibError = Error;
/**
* Files lib custom errors.
*
* `e.sdkDetails` provides additional context for each error (e.g. function parameter)
* @property ERROR_BAD_ARGUMENT - this error is thrown when an argument is missing or has invalid type
* @property ERROR_NOT_IMPLEMENTED - this error is thrown when a method is not implemented or when calling
* methods directly on the abstract class (Files).
* @property ERROR_BAD_CREDENTIALS - this error is thrown when the supplied init credentials are invalid.
* @property ERROR_INTERNAL - this error is thrown when an unknown error is thrown by the underlying
* provider or TVM server for credential exchange. More details can be found in `e.sdkDetails._internal`.
* @property ERROR_FILE_NOT_EXISTS - this error is thrown when the filePath does not exists for operations
* that need the file to exists (e.g. read)
* @property ERROR_BAD_FILE_TYPE - this error is thrown when the filePath is not the expected type for
* operations that need the file to be of a specific type, e.g. write on a dir would fail
*/
export type FilesLibErrors = {
ERROR_BAD_ARGUMENT: FilesLibError;
ERROR_NOT_IMPLEMENTED: FilesLibError;
ERROR_BAD_CREDENTIALS: FilesLibError;
ERROR_INTERNAL: FilesLibError;
ERROR_FILE_NOT_EXISTS: FilesLibError;
ERROR_BAD_FILE_TYPE: FilesLibError;
};