type DeviceDescription = 'browser-chrome' | 'desktop-macos' | 'desktop-windows' | 'mobile-android' | 'mobile-ios' | 'remarkable';

/**
 * Represents a reMarkable Cloud API session.
 *
 * The reMarkable Cloud API uses JWT token based authentication. All requests
 * performed to the API (expect the authentication ones) must contain a valid
 * JWT token which identifies the (@link Device) performing the request.
 *
 * The `Session` class provides an interface to access the authentication
 * token information and verify its validity.
 */
declare class Session {
    readonly deviceId: string;
    readonly expiresAt: Date;
    readonly token: string;
    constructor(sessionToken: string);
    get expired(): boolean;
}

/**
 * Represents a reMarkable device. Provides an interface to
 * authenticate with the reMarkable Cloud API.
 *
 * The reMarkable Cloud API uses `devices` to authenticate users. A
 * `device` is any software paired to a reMarkable Cloud user account.
 * `devices` are represented by a `device token`. A `device token` is
 * a JWT token without expiration date. It is used to fetch `session tokens`
 * from the reMarkable Cloud API, which can be used to perform authenticated
 * request to the different API services.
 *
 * The `Device` class encapsulates the logic to pair new applications to
 * reMarkable Cloud user accounts and create user sessions for interacting
 * with the reMarkable Cloud API.
 *
 * Paired `Devices` are listed in: [https://my.remarkable.com/device/remarkable](https://my.remarkable.com/device/remarkable)
 */
declare class Device {
    /**
     * Creates a new device and pairs it to a reMarkable Cloud user account.
     *
     * @param id - Unique `device` ID (uuid v4)
     * @param description - Label which indicates the `device` running environment (web browser, mobile app, ...)
     * @param oneTimeCode - One-time password to authenticate reMarkable Cloud user account when pairing `device`
     * @param HttpClientConstructor - HttpClient used for generating pair token
     */
    static pair(id: string, description: DeviceDescription, oneTimeCode: string, HttpClientConstructor?: unknown): Promise<Device>;
    /**
     * `device` unique identifier (uuid v4)
     */
    readonly id: string;
    /**
     * `device` running environment (web browser, mobile app, ...)
     */
    readonly description: DeviceDescription;
    /**
     * reMarkable Cloud API token associated to `device`
     */
    readonly token: string;
    private readonly httpClient;
    constructor(deviceToken: string, HttpClientConstructor?: unknown);
    /**
     * Creates a new `device` `session`.
     *
     * Fetches a new session token from the reMarkable Cloud API. This token
     * can be used to perform authenticated requests to the reMarkable Cloud API
     * in behalf of the user account associated to the `device`.
     */
    connect(): Promise<Session>;
}

/**
 * Represents a reMarkable Cloud folder
 */
declare class Folder {
    id: string;
    hash: string;
    name: string;
    folders?: Folder[];
    documents?: Document[];
    parentFolder?: Folder;
    lastModified?: Date;
    constructor(id: string, hash: string, name: string, lastModified: Date, parentFolder?: Folder, folders?: Folder[], documents?: Document[]);
    get root(): boolean;
}

/**
 * Represents a reMarkable Cloud document
 */
declare class Document {
    id: string;
    hash: string;
    name: string;
    fileType: 'pdf' | 'epub' | 'notebook';
    folder?: Folder;
    lastModified: Date;
    lastOpened: Date;
    constructor(id: string, hash: string, name: string, fileType: 'pdf' | 'epub' | 'notebook', lastModified?: Date, lastOpened?: Date, folder?: Folder);
}

/**
 * The reMarkable API only works with `.pdf` and `.epub` files. This error is
 * raised when an `Buffer` with an unsupported file extension is passed to
 * the `FileBufferType` class.
 */
declare class UnsupportedFileExtensionError extends Error {
}
/**
 * Represents the type of the file associated to its buffer.
 *
 * It is possible to identify the type of a file by examining its buffer.
 * This class encapsulates the logic to infer a files type from its
 * respective buffer.
 *
 * Since the reMarkable Cloud API only allows uploading `.pdf` and `.epub`
 * files, the class only handles buffers with that extension, raising an
 * { @link UnsupportedFileExtensionError } when a buffer from an unsupported
 * file extension is passed.
 */
declare class FileBufferType {
    static extension(buffer: Buffer): 'pdf' | 'epub';
    static mimeType(buffer: Buffer): string;
    /**
     * Buffer file extension
     */
    readonly extension: string;
    /**
     * MIME type of the buffer file
     */
    readonly mimeType: string;
    constructor(buffer: Buffer);
}

type HeadersPayload = Record<string, string>;
/**
 * { @link HttpClient } { @link Request } headers
 *
 * Encapsulates a collection of `http` `header` key - value pairs
 * and provides logic to export them in different formats
 * compatible with `http` libraries.
 */
declare class Headers {
    #private;
    constructor(headers: HeadersPayload);
    get entries(): Record<string, string>;
}

/**
 * { @link HttpClient } { @link Request } context
 *
 * `HttpClient` instance configuration. Given an `HttpClient` with a
 * `Context`, the `Context` represents the base URL and headers set
 * used in all http requests performed with the client.
 */
declare class Context {
    readonly host: string;
    readonly headers: Headers;
    constructor(host: string, headers?: HeadersPayload);
}

/**
 * HTTP request `body` types supported by { @link HttpClient } { @link Body }.
 *
 * These types can be converted into a `serialized` format, compatible with `http` libraries,
 * by the { @link HttpClient } { @link Body } to be dispatched as `body` in an
 * HTTP POST / PATCH / PUT request.
 */
type BodyPayload = Record<string, string | boolean | number> | ArrayBuffer | Buffer | string;

/**
 * Interface for library HTTP client.
 *
 * Provides a RESTful interface for performing HTTP requests. All http
 * requests performed by the library should be done through this interface.
 *
 * `HttpClients` interface consists on a set of static methods for performing
 * HTTP requests. To perform multiple requests with a base `host` and set of
 * `headers` use the instance methods by instantiating the client with the
 * base `host` and `headers` as context.
 */
declare abstract class HttpClient {
    static get(host: string, path: string, headers?: HeadersPayload): Promise<Response>;
    static post(host: string, path: string, headers?: HeadersPayload, body?: BodyPayload): Promise<Response>;
    static patch(host: string, path: string, headers?: HeadersPayload, body?: BodyPayload): Promise<Response>;
    static put(host: string, path: string, headers?: HeadersPayload, body?: BodyPayload): Promise<Response>;
    static delete(host: string, path: string, headers?: HeadersPayload): Promise<Response>;
    readonly context: Context;
    constructor(host: string, headers?: HeadersPayload);
    /**
     * Perform a GET request.
     *
     * @param path - Request path destination (https://{@link host}/{@link path})
     * @param headers - Request headers. Merged with client { @link context.headers } when performing request
     */
    get(path: string, headers?: HeadersPayload): Promise<Response>;
    /**
     * Perform a POST request.
     *
     * @param path - Request path destination (https://{@link host}/{@link path})
     * @param body - Request body payload
     * @param headers - Request headers. Merged with client { @link context.headers } when performing request
     */
    post(path: string, body?: BodyPayload, headers?: HeadersPayload): Promise<Response>;
    /**
     * Perform a PATCH request.
     *
     * @param path - Request path destination (https://{@link host}/{@link path})
     * @param body - Request body payload
     * @param headers - Request headers. Merged with client { @link context.headers } when performing request
     */
    patch(path: string, body?: BodyPayload, headers?: HeadersPayload): Promise<Response>;
    /**
     * Perform a PUT request.
     *
     * @param path - Request path destination (https://{@link host}/{@link path})
     * @param body - Request body payload
     * @param headers - Request headers. Merged with client { @link context.headers } when performing request
     */
    put(path: string, body?: BodyPayload, headers?: HeadersPayload): Promise<Response>;
    /**
     * Perform a DELETE request.
     *
     * @param path - Request path destination (https://{@link host}/{@link path})
     * @param headers - Request headers. Merged with client { @link context.headers } when performing request
     */
    delete(path: string, headers?: HeadersPayload): Promise<Response>;
    /**
     * Get the underlying `HttpClient` instance class reference.
     *
     * Used to perform HTTP requests through the client specific http static methods.
     *
     * @private
     */
    private classReference;
    /**
     * Request specific configuration. Merges client { @link context.headers }
     * with request specific headers.
     *
     * @param headers - Request specific headers
     *
     * @private
     */
    private requestContext;
}

/**
 * Generates `HttpClient` instances preconfigured for performing
 * requests to the different services available in the reMarkable
 * Cloud API.
 *
 * Each service in the reMarkable Cloud API (such as authentication,
 * document storage, ...) has a specific host. The `/service` API
 * endpoint allows developers to fetch the these hosts. This class
 * provides a public interface of methods representing all the
 * services available in the API.
 *
 * Use these methods to get instances of the `HttpClient` configured
 * with the corresponding host and authentication headers for the
 * service you want to make use of.
 */
declare class ServiceManager {
    /**
     * Returns `HttpClient` configured with host and header options to
     * perform requests to the reMarkable production API.
     *
     * This API endpoint is not a service per-se, but provides some similar
     * utilities other services provide (such as device pairing or session
     * creation). To keep the logic to fetch endpoints consistent, this
     * method encapsulates the endpoint logic as if it was another service.
     *
     * Some of the utilities the endpoint provide does not require from
     * any headers. By defining this method as static, we can make use
     * of this endpoint without requiring a `Device` instance (as it
     * is required for other endpoints).
     */
    static productionHttpClient(headers?: HeadersPayload, HttpClientConstructor?: unknown): HttpClient;
    readonly session: Session;
    readonly httpClient: HttpClient;
    constructor(session: Session, HttpClientConstructor?: unknown);
    /**
     * Returns `HttpClient` configured with host and header options to
     * perform requests to the reMarkable Document Storage API service.
     */
    documentStorageHttpClient(): Promise<HttpClient>;
    /**
     * Returns `HttpClient` configured with host and header options to
     * perform requests to the reMarkable internal API.
     *
     * This API endpoint is not a service per-se, but provides some similar
     * utilities other services provide (such as file upload). To keep the
     * logic to fetch endpoints consistent, this method encapsulates the
     * endpoint logic as if it was another service.
     */
    internalCloudHttpClient(): Promise<HttpClient>;
    private serviceHttpClient;
}

declare class FileNotUploadedError extends Error {
}
/**
 * Represents a reference to an uploaded { @link Document }
 *
 * In the reMarkable Cloud API, documents are identified by a unique
 * ID and Hash. While the ID is always the same, the hash changes
 * conforming changes are pushed to the user account file system.
 *
 * The { @link DocumentReference } class parses the reMarkable Cloud
 * API success upload response and returns a reference to the uploaded
 * document.
 */
declare class DocumentReference {
    readonly id: string;
    readonly hash: string;
    constructor(id: string, hash: string);
}
/**
 * Represents a file content, encoded as a buffer, ready to be uploaded
 * to reMarkable Cloud.
 *
 * Encapsulates the logic to handle file upload. Given the Buffer
 * content of a file, it verifies the type compatibility with the
 * reMarkable Cloud API and provides an interface to upload the file
 * and get a reference to its cloud equivalent when successfully
 * pushed.
 */
declare class FileBuffer {
    /**
     * Creates a FileBuffer from a local file
     *
     * Used to easily upload local files to reMarkable cloud
     *
     * @param {string} path
     * @param {ServiceManager} serviceManager
     */
    static fromLocalFile(path: string, serviceManager: ServiceManager): Promise<FileBuffer>;
    /**
     * Creates FileBuffer from file Buffer and uploads it
     *
     * @param name - File name
     * @param buffer - File content
     * @param serviceManager
     */
    static upload(name: string, buffer: Buffer, serviceManager: ServiceManager): Promise<FileBuffer>;
    readonly name: string;
    readonly buffer: Buffer;
    readonly type: FileBufferType;
    documentReference?: DocumentReference;
    private httpClient?;
    private readonly serviceManager;
    constructor(name: string, buffer: Buffer, serviceManager: ServiceManager);
    get uploaded(): boolean;
    upload(): Promise<DocumentReference>;
    private internalCloudHttpClient;
    private get encodedName();
}

/**
 * Represents a snapshot of the reMarkable Cloud API file system.
 *
 * Provides a list of all { @link Document }s and { @link Folder }s in
 * the user's reMarkable Cloud account in a specific point in time.
 *
 * A snapshot is valid as long as the user does not perform any write
 * operations on the reMarkable Cloud file system. As soon a file in
 * the system is uploaded or modified, all the files hashes are modify,
 * causing the snapshot to be de-synchornized with the actual reMarkable
 * Cloud file system.
 *
 * You can see the snapshot as a cache of the reMarkable Cloud file system.
 */
declare class FileSystemSnapshot {
    #private;
    constructor(documents: Document[], folders: Folder[]);
    get documents(): Document[];
    get folders(): Folder[];
    get rootFolder(): Folder;
    document(id: string): Document | undefined;
    folder(id: string): Folder | undefined;
}

/**
 * Represents the reMarkable Cloud API file system. Provides an
 * interface to retrieve the list of {@link Document}s and {@link Folder}s
 * in a user reMarkable Cloud account and navigate through them.
 *
 * The reMarkable API `/doc/v2/files` endpoint returns a list of all files
 * in a user reMarkable Cloud account with their respective metadata.
 *
 * The `FileSystem` class parses the API response and maps the file system
 * hierarchy to a set of {@link Document} and {@link Folder} instances,
 * providing a virtual recreation of the actual file system tree, which
 * can be then used to navigate through it in the similar way as in any
 * other file system.
 */
declare class FileSystem {
    #private;
    constructor(serviceManager: ServiceManager);
    get lastFetchSnapshot(): FileSystemSnapshot | undefined;
    /**
     * Requests new reMarkable Cloud snapshot of all documents and folders in user account.
     */
    snapshot(): Promise<FileSystemSnapshot>;
    /**
     * Requests new reMarkable Cloud list of all documents in user account.
     *
     * Consider using {@link snapshot} method to get a snapshot of the entire file system
     * and fetch the documents from there instead of calling this method. Each document
     * request triggers a fetch call of the whole file system and the post-processing
     * of the response to build the file system tree. This is an expensive operation
     * that should be only invoked when changes have been made to the file system
     * (files uploaded, updated, deleted, etc).
     *
     * If no changes were uploaded to the reMarkable Cloud you should use the {@link snapshot}
     * method to get the list of documents and folders in the user account. The snapshot works
     * as a cache, and contains the file system information of the last request made to the
     * reMarkable Cloud API.
     */
    document(id: string): Promise<Document | undefined>;
    /**
     * Requests new reMarkable Cloud list of all folder in user account.
     *
     * Consider using {@link snapshot} method to get a snapshot of the entire file system
     * and fetch the folder from there instead of calling this method. Each folder
     * request triggers a fetch call of the whole file system and the post-processing
     * of the response to build the file system tree. This is an expensive operation
     * that should be only invoked when changes have been made to the file system
     * (files uploaded, updated, deleted, etc).
     *
     * If no changes were uploaded to the reMarkable Cloud you should use the {@link snapshot}
     * method to get the list of documents and folders in the user account. The snapshot works
     * as a cache, and contains the file system information of the last request made to the
     * reMarkable Cloud API.
     */
    folder(id: string): Promise<Folder | undefined>;
    private fetchSnapshot;
}

/**
 * reMarkable API `/downloads` endpoint response payload
 *
 * Represents the URL to access the content of a `hash`.
 *
 * Download URLs are signed. The `hash` content is accessible
 * through an HTTP request to its `url` with the `method` specified
 * (no authentication required).
 *
 * Once the `expires` date is reached, the URL is no longer valid.
 */
interface HashPathPayload {
    expires: string;
    method: 'GET' | 'PUT' | 'PATCH';
    relative_path: string;
    url: string;
}
/**
 * Represents the URL to access the content of a `hash`.
 *
 * A `hash` is a string which uniquely identifies a piece of information in the
 * reMarkable cloud. A piece of information can be a `Document`, a `Folder`,
 * metadata associated to a `Document` or a `Folder`, etc.
 *
 * To access the content of a `hash`, the reMarkable API provides a `/downloads`
 * endpoint. This endpoint returns the download URL for a given `hash`. Download
 * URLs are signed URLs with an expiration date. When performing an HTTP request
 * to the download URL, the content of the `hash` is returned. Once the expiration
 * date is reached, the URL is no longer valid, requiring a new request to the
 * `/downloads` endpoint to get a new download URL.
 *
 * The `HashUrl` class provides an interface to download the content of a `hash`.
 */
declare class HashUrl {
    /**
     * Returns `HashUrl` for a given `hash`.
     *
     * @param {string} hash
     * @param {ServiceManager} serviceManager
     */
    static fromHash(hash: string, serviceManager: ServiceManager): Promise<HashUrl>;
    /**
     * Returns `HashUrl` for the `hash` associated to the root folder.
     *
     * The root folder represents the root path of the reMarkable cloud storage.
     *
     * @param {ServiceManager} serviceManager
     */
    static fromRootHash(serviceManager: ServiceManager): Promise<HashUrl>;
    expires: Date;
    method: 'GET' | 'PUT' | 'PATCH';
    relativePath: string;
    url: URL;
    constructor(hashPathPayload: HashPathPayload);
    get expired(): boolean;
    fetch(): Promise<Response>;
}

/**
 * { @link HttpClient } which uses web browser `fetch` method to perform HTTP requests.
 */
declare class FetchClient extends HttpClient {
    static get(host: string, path: string, headers?: HeadersPayload): Promise<Response>;
    static post(host: string, path: string, headers?: HeadersPayload, body?: BodyPayload | null): Promise<Response>;
    static patch(host: string, path: string, headers?: HeadersPayload, body?: BodyPayload | null): Promise<Response>;
    static put(host: string, path: string, headers?: HeadersPayload, body?: BodyPayload | null): Promise<Response>;
    static delete(host: string, path: string, headers?: HeadersPayload): Promise<Response>;
    private static makeRequest;
    private static request;
}

/**
 * { @link HttpClient } which uses Node.js `https` module to perform HTTP requests.
 */
declare class NodeClient extends HttpClient {
    static get(host: string, path: string, headers?: HeadersPayload): Promise<Response>;
    static post(host: string, path: string, headers?: HeadersPayload, body?: BodyPayload | null): Promise<Response>;
    static patch(host: string, path: string, headers?: HeadersPayload, body?: BodyPayload | null): Promise<Response>;
    static put(host: string, path: string, headers?: HeadersPayload, body?: BodyPayload | null): Promise<Response>;
    static delete(host: string, path: string, headers?: HeadersPayload): Promise<Response>;
    private static makeRequest;
    private static request;
}

/**
 * reMarkable Cloud API client.
 *
 * Provides an interface to interact with the reMarkable Cloud API:
 * - Navigate through the file system
 * - Upload documents
 */
declare class RemarkableClient {
    #private;
    static withFetchHttpClient(deviceToken?: string, sessionToken?: string): RemarkableClient;
    static withNodeHttpClient(deviceToken?: string, sessionToken?: string): RemarkableClient;
    constructor(deviceToken?: string, sessionToken?: string, httpClientConstructor?: unknown);
    get device(): Device;
    get session(): Session;
    pair(id: string, description: DeviceDescription, oneTimeCode: string): Promise<boolean>;
    connect(): Promise<void>;
    document(id: string): Promise<Document | undefined>;
    folder(id: string): Promise<Folder | undefined>;
    upload(name: string, buffer: Buffer): Promise<DocumentReference>;
    get sessionExpired(): boolean;
    get paired(): boolean;
}

export { Device, type DeviceDescription, Document, DocumentReference, FetchClient, FileBuffer, FileBufferType, FileNotUploadedError, FileSystem, Folder, HashUrl, HttpClient, NodeClient, RemarkableClient, ServiceManager, Session, UnsupportedFileExtensionError };
