import IPostMessage from '../IPostMessage';
import { IStorageUnit, IFilePath, IFile, IHeaders, ICopyFileOptions, IMoveFileOptions, ExtractMethodType } from './types';
import StorageUnitsChangedMessage from './StorageUnitsChangedMessage';
import IFileSystem from './IFileSystem';
import { HashAlgorithm } from './HashAlgorithm';
/**
* The `sos.fileSystem` API groups together methods for low-level access to the file system. The File System API supports both internal and
* external storage.
*
* :::warning Differences between File System API and Offline Cache API
* File System directory structure is **PERSISTENT** and is **NOT** automatically deleted through `Applet Reload` power action!
* Applet Reload only deletes `/data` directory which is reserved for simplified [Offline Cache API](./offline). Use
* `deleteFile()` to clear the device storage file system.
* :::
*
* :::info GitHub Example
* - [Example usage of File System API in Applet](https://github.com/signageos/applet-examples/tree/master/examples/content-js-api/file-system)
* :::
*
*
* Device File System Capabilities
* | Capability | Description |
* |:------------|:-------------|
* | `FILE_SYSTEM_INTERNAL_STORAGE` | If device supports internal storage units |
* | `FILE_SYSTEM_EXTERNAL_STORAGE` | If device supports connecting external storage units |
* | `FILE_SYSTEM_FILE_CHECKSUM` | If device supports checksum for MD5 or CRC32 hash algorithms |
* | `FILE_SYSTEM_LINK` | If device supports creating hard links to files |
* | `FILE_SYSTEM_CREATE_ARCHIVE` | If device supports creating archives - zip |
* | `FILE_SYSTEM_ARCHIVE_EXTRACT_INFO` | If device supports extracting information about archive files |
*
* If you want to check if the device supports this capability, use [`sos.display.supports()`](https://developers.signageos.io/sdk/sos/display#supports).
*
*
*
* ## Storing files permanently
* To allow more low-level file operations, the applet SDK exposes the File System API. Files created using this API are permanent and are only removed on a factory reset or file system wipeout.
* The file system is also shared between all applets, which means you cannot rely on any file system structure on startup because a different applet on the device could have saved files you didn't expect.
* To mitigate this issue, create a directory for your applet and save all files inside it.
*
* @example
* import sos from '@signageos/front-applet';
*
* sos.onReady(async () => {
* const storageUnits = await sos.fileSystem.listStorageUnits();
* const rootPath = {
* filePath: '', // Empty string is used as an absolute path instead of "/"
* storageUnit: storageUnits.find((s) => !s.removable), // Find internal storage
* };
*
* // This will return files previous applets saved to the device
* const files = await sos.fileSystem.listFiles(rootPath);
* });
*/
export default class FileSystem implements IFileSystem {
private messagePrefix;
private postMessage;
static MESSAGE_PREFIX: string;
private eventEmitter;
/** @internal */
constructor(messagePrefix: string, postMessage: IPostMessage);
/**
* The `listStorageUnits()` method lists all available storage units. All devices always have one internal storage device (with
* `removable: false`) and zero or more external devices. The capacity values are in bytes.
*
* :::note
* This is a mandatory method that is required for all the other File System APIs. The other APIs require a storageUnit object that is retrieved from this method to manipulate with files on a correct storage location (internal/external).
* :::
*
* :::warning
* `storageUnit` is a dynamic object! It has to be always generated and retrieved by this JS API, as the values in type differ platform by platform. Never generate the object manually. `{"type":"internal"}` is for demonstration only.
* :::
*
* @returns {Promise} An array of storage units available on the device.
* @throws InternalFileSystemError Unexpected error occurred when listing storage units.
* @since 2.1.0
*
* @example
* // Storage units are equivalent to disk volumes (C:, D: etc on Windows; /mnt/disc1, /mnt/disc2 on Unix)
* const storageUnits = await sos.fileSystem.listStorageUnits();
* const externalStorageUnits = storageUnits.filter((storageUnit) => storageUnit.removable);
* externalStorageUnits.forEach((storageUnit) => {
* console.log(`Storage Unit Type: ${storageUnit.type}`);
* console.log(`Capacity: ${storageUnit.capacity} bytes`);
* });
*/
listStorageUnits(): Promise;
/**
* A shorthand method for listing only the internal storage units (i.e., those with the `removable: false`). The capacity values are in bytes.
*
* @returns {Promise} An array of internal storage units available on the device.
* @since 7.0.0
*
* @example
* // List internal storage units
* const internalStorageUnits = await sos.fileSystem.listInternalStorageUnits();
* internalStorageUnits.forEach((storageUnit) => {
* console.log(`Storage Unit Type: ${storageUnit.type}`);
* console.log(`Capacity: ${storageUnit.capacity} bytes`);
* console.log(`Free Space: ${storageUnit.freeSpace} bytes`);
* console.log(`Usable Space: ${storageUnit.usableSpace} bytes`);
* });
*/
listInternalStorageUnits(): Promise;
/**
* The `onStorageUnitsChanged()` method sets up a listener, which is called whenever the list of storage units changes.
*
* @param listener The listener function to be called when the storage units change.
* @throws Error If `listener` is not a valid function.
* @since 2.1.0
*/
onStorageUnitsChanged(listener: () => void): void;
/**
* The `removeStorageUnitsChangedListener()` method removes a listener, previously added by `onStorageUnitsChanged()`
*/
removeStorageUnitsChangedListener(listener: () => void): void;
/**
* The `removeAllListeners()` method removes all listeners, previously added by `onStorageUnitsChanged()`
*/
removeAllListeners(): void;
/**
* The `listFiles()` method lists all files and directories in the specified path (nested files are not included).
*
* @param directoryPath The path to the directory where files will be listed.
* @returns {Promise} A promise that resolves to an array of file paths in the specified directory.
* @throws Error If `directoryPath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If the path does not exist, or it is a file.
* @since 2.1.0
*
* @example
* // List files in the root directory of the internal storage unit
* const internalStorageUnit = (await sos.fileSystem.listInternalStorageUnits())[0];
* const directoryPath = {
* storageUnit: internalStorageUnit,
* filePath: '', // Empty string is used as an absolute path instead of "/"
* };
*
* const files = await sos.fileSystem.listFiles(directoryPath);
* console.log('Files in the root directory:', files.length);
* files.forEach((file) => {
* console.log(`File: ${file.filePath}`);
* });
*/
listFiles(directoryPath: IFilePath): Promise;
/**
* The `exists()` method checks whether a file or directory exists.
*
* @param filePath The path to the file or directory to check.
* @returns {Promise} A promise that resolves to `true` if the file or directory exists, `false` otherwise.
* @throws Error If the `filePath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If any error occurs during the existence check operation on the device.
* @since 2.1.0
*
* @example
* const filePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/file.txt',
* };
*
* const fileExists = await sos.fileSystem.exists(filePath);
* console.log(`File exists: ${fileExists}`); // Prints true if the file exists, false otherwise
*/
exists(filePath: IFilePath): Promise;
/**
* The `getFile()` method returns runtime information about a file path, such as local url, last modified date or size.
*
* :::warning
* Return statement is a dynamic object! It has to be always generated and retrieved by this JS API, as the values in localUri differ platform by platform. Never generate the object manually. `{"localUri":"file://internal/path/to/file.txt"}` is for demonstration only.
* :::
*
* @param filePath The path to the file to be retrieved.
* @returns {Promise} A promise that resolves to the file information or `null` if the file does not exist.
* @throws Error If the `filePath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If the file is a directory.
* @throws Error If any error occurs during the retrieval operation on the device.
* @since 2.1.0
*
* @example
* // Get file information
* const filePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/file.txt',
* };
*
* const fileInfo = await sos.fileSystem.getFile(filePath);
* console.log(JSON.stringify(fileInfo)); // Prints the file information
* console.log(fileInfo.localUri); // Prints the local URI of the file
*/
getFile(filePath: IFilePath): Promise;
/**
* The `writeFile()` method writes string content to the file specified by `filePath`. If the file does exist, it is created.
*
* @param filePath The path to the file to be written.
* @param contents The content to be written to the file.
* @returns {Promise} A promise that resolves when the content is written successfully.
* @throws Error If the parent directory does not exist or the `filePath` is a directory.
* @throws Error If the `filePath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If any error occurs during the write operation on the device.
* @since 3.2.0
*
* @example
* const filePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/file.txt',
* };
*
* const contents = 'This is the content to write to the file.';
* await sos.fileSystem.writeFile(filePath, contents);
*/
writeFile(filePath: IFilePath, contents: string): Promise;
/**
* The `appendFile()` method appends string content to the file specified by `filePath`.
* If the file does exist, it is created.
*
* :::note
* Only string can be appended to the file. If you want to append binary data, you have to convert it to a string first.
* :::
*
* @param filePath The path to the file to be appended.
* @param contents The content to be appended to the file.
* @returns {Promise} A promise that resolves when the content is appended successfully.
* @throws Error If the parent directory does not exist.
* @throws Error If the `filePath` is a directory.
* @throws Error If the `filePath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If any error occurs during the append operation on the device.
* @since
*
* @example
* const filePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/file.txt',
* };
*
* const contents = 'This is the content to append to the file.';
* await sos.fileSystem.appendFile(filePath, contents);
*/
appendFile(filePath: IFilePath, contents: string): Promise;
/**
* The `readFile()` method returns content of the file specified by `filePath`.
* The file has to be a text file, otherwise the content will be mangled.
*
* @param filePath The path to the file to be read.
* @returns {Promise} A promise that resolves to the content of the file.
* @throws Error If the file does not exist.
* @throws Error If the `filePath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If the file is a directory.
* @throws Error If any error occurs during the read operation on the device.
* @since 3.3.0
*
* @example
* const filePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/file.txt',
* };
*
* const fileContent = await sos.fileSystem.readFile(filePath);
* console.log(`Content of the file: ${fileContent}`);
*/
readFile(filePath: IFilePath): Promise;
/**
* The `copyFile()` method creates a copy of file from `sourceFilePath` to `destinationFilePath`.
*
* @param sourceFilePath The path to the file to be copied.
* @param destinationFilePath The path where the file will be copied to.
* @param options Options for copying the file.
* @param options.overwrite If set to `true`, the method will overwrite the destination file if it already exists.
* @returns {Promise} A promise that resolves when the file is copied successfully.
* @throws Error If the source file does not exist.
* @throws Error If parent of the destination file path does not exist.
* @throws Error If `options` object is not valid.
* @throws Error If any error occurs during the copy operation on the device.
* @since 2.1.0
*
* @example
* // Copy file from one directory to another and overwrite it if it already exists
* const sourceFilePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/source/file.txt',
* };
*
* const destinationFilePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/destination/file.txt',
* };
*
* await sos.fileSystem.copyFile(sourceFilePath, destinationFilePath, { overwrite: true });
*/
copyFile(sourceFilePath: IFilePath, destinationFilePath: IFilePath, options?: ICopyFileOptions): Promise;
/**
* The `moveFile()` method moves a file from `sourceFilePath` to `destinationFilePath`.
*
* @param sourceFilePath The path to the file to be moved.
* @param destinationFilePath The path where the file will be moved to.
* @param options Options for moving the file.
* @param options.overwrite If set to `true`, the method will overwrite the destination file if it already exists.
* @returns {Promise} A promise that resolves when the file is moved successfully.
* @throws Error If the source file does not exist or parent of the destination file path does not exist.
* @throws Error If the `options.overwrite` is not set and the destination file path already exists.
* @throws Error If deleting path does not exist.
* @throws Error If any error occurs during the move operation on the device.
* @since 2.1.0
*
* @example
* // Move file from one directory to another and overwrite it if it already exists
* const sourceFilePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/source/file.txt',
* };
*
* const destinationFilePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/destination/file.txt',
* };
*
* await sos.fileSystem.moveFile(sourceFilePath, destinationFilePath, { overwrite: true });
*/
moveFile(sourceFilePath: IFilePath, destinationFilePath: IFilePath, options?: IMoveFileOptions): Promise;
/**
* The `deleteFile()` method deletes the file specified by `filePath`.
*
* @param filePath The path to the file or directory to be deleted.
* @param recursive If set to `true`, the method will delete the directory and all its contents recursively.
* @returns {Promise} A promise that resolves when the file is deleted successfully.
* @throws Error If `filePath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If the file does not exist or if `recursive` is set to false and the file path is a directory.
* @throws Error If deleting path does not exist.
* @throws Error When is deleting directory and is not empty (not recursive).
* @since 2.1.0
*
* @example
* // Delete directory and all files inside
* //// First check, if there is such a directory
* if (await sos.fileSystem.exists({ storageUnit: internalStorageUnit, filePath: 'test-dir' })) {
* // Delete the directory and all it's content recursively
* await sos.fileSystem.deleteFile({ storageUnit: internalStorageUnit, filePath: 'test-dir' }, true);
* }
*
* // Delete file
* //// First check, if there is such a file
* if (await sos.fileSystem.exists({ storageUnit: internalStorageUnit, filePath: 'test-dir/downloaded-file.png' })) {
* // Delete the file
* await sos.fileSystem.deleteFile({ storageUnit: internalStorageUnit, filePath: 'test-dir/downloaded-file.png' }, false);
* }
*/
deleteFile(filePath: IFilePath, recursive: boolean): Promise;
/**
* The `downloadFile()` method download a file from `sourceUri` and saves it to the specified path. If the file already exists, the file will be
* overwritten. Optionally, headers for the download request may be specified.
*
* :::danger
* For every download request, our Core Apps makes HEAD request for `content-length` header on that downloaded file. It's due to determining if device has enough space to download the file.
* :::
*
* #### Encoding
* All downloads respect a standard of `Encoding` with optional compression of files. See [Mozilla standard Accept Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding) and [Content Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding).
*
* Download file method is always sending optional following headers:
* ```
* Accept-Encoding: gzip
* Accept-Encoding: compress
* Accept-Encoding: deflate
* Accept-Encoding: br
* Accept-Encoding: identity
* Accept-Encoding: *
* ```
*
* If the server understands the `Encoding` standard, it compresses files using `gzip` algorithm before the files are sent to the client. If so, the response will contain the following headers:
* ```
* Content-Encoding: gzip
* Content-Encoding: compress
* Content-Encoding: deflate
* Content-Encoding: br
* ```
* So the data communication is compressed under the hood. The client will automatically decompress data before it's saved to a specified location path. So from JS API point of view, there is no requirement to decompress data by itself.
*
* The standard is supported on all following platforms:
*
* - WebOS 3+
* - Tizen 2.4+
* - Brightsign
* - Raspberry Pi
* - Windows
*
* @param filePath The path where the downloaded file will be saved.
* @param sourceUri The URI of the file to be downloaded.
* @param headers Key, value pairs of HTTP headers to send along with the request. Used when the target file is protected by a password or if any
* @returns {Promise} A promise that resolves when the file is downloaded successfully.
* @throws Error If `filePath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If `sourceUri` is not a valid URI.
* @throws Error If `headers` is not a valid object.
* @throws Error If the parent directory of `filePath` does not exist.
* @throws Error If the network request fails.
* @since 2.1.0
*
* @example
* const filePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/downloaded/file.zip',
* };
* const sourceUri = 'https://example.com/path/to/file.zip';
* const headers = {
* 'Authorization': 'Bearer your_token_here',
* };
* await sos.fileSystem.downloadFile(filePath, sourceUri, headers);
*/
downloadFile(filePath: IFilePath, sourceUri: string, headers?: IHeaders): Promise;
/**
* The `extractFile()` method extract (recursively) the archive file at `archiveFilePath` into a new file specified by `destinationDirectoryPath`.
*
* :::note
* - The directory/folder you are extracting your ZIP file into has to be created BEFORE you start extracting the ZIP.
* - Only supported extract method is `zip`.
* :::
*
* @param archiveFilePath The path to the archive file to be decompressed.
* @param destinationDirectoryPath The path to the directory where the decompressed files will be saved.
* @param method Extract method to use for extracting, e.g. 'zip'.
* @throws Error If the archive file path does not exist.
* @throws Error If it is not a valid archive file.
* @throws Error If destination directory does not exist.
* @since 2.1.0
*
* @example
* const archiveFilePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/archive.zip',
* };
*
* const destinationDirectoryPath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/destination/directory',
* };
*
* await sos.fileSystem.extractFile(archiveFilePath, destinationDirectoryPath, 'zip');
*/
extractFile(archiveFilePath: IFilePath, destinationDirectoryPath: IFilePath, method: ExtractMethodType): Promise;
/**
* The `createArchive()` method creates an archive file from selected files and directories.
*
* :::warning
* - Never start OR end the `filePath` with a slash - `/`.
* - It is a good practice to check if file exists - `exists()` prior creating it
* :::
*
* :::info
* - This function is available only on Tizen devices.
* - All files are added to the archive based on absolute path from root directory.
* :::
*
* @param archiveFilePath The path where the archive file will be created.
* @param archiveEntries An array of file paths to be included in the archive.
* @returns {Promise} A promise that resolves when the archive file is created successfully.
* @throws Error If `archiveFilePath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If `archiveEntries` is not a valid array of objects.
* @throws Error If the parent directory of `archiveFilePath` does not exist.
* @throws Error If any of the `archiveEntries` do not exist or are directories.
* @throws Error If creating the archive file fails.
* @throws Error If the platform does not support creating archive files.
* @since 5.12.0
*
* @example
* const archiveFilePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/archive.zip',
* };
*
* const archiveEntries = [
* {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/file1.txt',
* },
* {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/file2.txt',
* },
* {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/directory1',
* },
* ];
*
* await sos.fileSystem.createArchive(archiveFilePath, archiveEntries);
*/
createArchive(archiveFilePath: IFilePath, archiveEntries: IFilePath[]): Promise;
/**
* The `getChecksumFile()` method computes a checksum of the file specified by `filePath`.
*
* :::warning Tizen limitation
* If you are about to use the MD5 file validation it will automatically return on any Samsung Tizen - 2.4, 3.0 and 4.0.
* Reason: MD5 file checksum is not available on any Tizen displays due to the Samsung restriction.
* :::
*
* @param filePath The path to the file for which the checksum will be computed.
* @param hashType The type of hash algorithm to use for computing the checksum.
* @returns {Promise} A promise that resolves to the computed checksum of the file.
* @throws Error If `filePath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If `hashType` is not a valid type or string.
* @throws Error If the file does not exist.
* @throws Error If `filepath` it is a directory
*
* @example
* const filePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/file.txt',
* };
*
* const checksum = await sos.fileSystem.getFileChecksum(filePath, 'md5');
* console.log(`Checksum of the file: ${checksum}`);
*/
getFileChecksum(filePath: IFilePath, hashType: HashAlgorithm): Promise;
/**
* The `createDirectory()` method create a new directory at specified path.
*
* :::warning
* - Never start OR end the filePath with a slash - `/`.
* - It is a good practice to check if directory exists - `isDirectory()` prior creating it.
* :::
*
* @param directoryPath The path where the new directory will be created.
* @returns {Promise} A promise that resolves when the directory is created successfully.
* @throws Error If `directoryPath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If the directory already exists.
* @throws Error If parent directory does not exist.
* @since 2.1.0
*
* @example
* const internalStorageUnit = (await sos.fileSystem.listInternalStorageUnits())[0];
* const directoryPath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/new/directory',
* };
*
* await sos.fileSystem.createDirectory(directoryPath);
*/
createDirectory(directoryPath: IFilePath): Promise;
/**
* The `isDirectory()` method checks whether the file path points to a directory.
*
* @param filePath The file path to check.
* @returns {Promise} A promise that resolves to `true` if the file path is a directory, `false` otherwise.
* @throws Error If `filePath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If the file path does not exist.
* @since 2.1.0
*
* @example
* const filePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/directory',
* };
* const isDir = await sos.fileSystem.isDirectory(filePath);
* if (isDir) {
* console.log('The file path is a directory.');
* } else {
* console.log('The file path is not a directory.');
* }
*/
isDirectory(filePath: IFilePath): Promise;
/**
* The `link()` method creates a symbolic link from `sourceFilePath` (existing path) to `destinationFilePath` (new path).
*
* :::note
* This method is only available on Linux devices.
* :::
*
* @param sourceFilePath The path to the existing file or directory that you want to link to.
* @param destinationFilePath The path where the symbolic link will be created.
* @throws Error If `sourceFilePath` or `destinationPath` is not a valid object or does not contain `storageUnit` and `filePath`.
* @throws Error If the `sourceFilePath` does not exist or if the `destinationFilePath` already exists.
* @throws Error The platform does not support linking directories.
* @returns {Promise} A promise that resolves when the symbolic link is created successfully.
* @since 4.0.0
*
* @example
* const internalStorageUnit = (await sos.fileSystem.listInternalStorageUnits())[0];
* const sourceFilePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/existing/file.txt',
* };
*
* const destinationFilePath = {
* storageUnit: internalStorageUnit,
* filePath: 'path/to/symlink/file_link.txt',
* };
*
* await sos.fileSystem.link(sourceFilePath, destinationFilePath);
*/
link(sourceFilePath: IFilePath, destinationFilePath: IFilePath): Promise;
/**
* The `wipeout()` method is used to wipe out all data from the file system.
*
* :::danger
* - Ensure that function is called only once, otherwise it will wipe out the file system again on applet or device start!
* - This function is clearing internal file system storage, cache storage and cookies. Local storage will not be cleared.
* :::
*
* @returns {Promise} A promise that resolves when the wipeout is complete.
*
* @example
* await sos.fileSystem.wipeout().then(() => {
* console.log('File system wiped out successfully.');
* await sos.management.power.systemReboot(); // Reboot the device after wipeout
* }).catch((error) => {
* console.error('Error wiping out file system:', error);
* });
*/
wipeout(): Promise;
/** @internal */
handleMessageData(data: StorageUnitsChangedMessage): void;
private getMessage;
}