npm package: @repalash/rclone.js
Description: JavaScript API for rclone
Author: Sơn Trần-Nguyễn
Latest version: 0.6.6

# Rclone.js

The JavaScript API to the "Swiss army knife of cloud storage"
[rclone](https://rclone.org/).

Besides providing a way to install rclone on different platforms, a CLI and
a JavaScript API are included.

## Installation

```sh
npm install rclone.js
```

After installation, the latest binary of `rclone` is also fetched based on
your system environment.

If a custom version of `rclone` binary is needed, use `RCLONE_EXECUTABLE`
environment variable to set the path to that custom binary.

## Usage

### Node.js

Except `selfupdate`, which is used to update `rclone` binary, all API functions
return a child process whose events we can listen to. Optional flags can be
passed as an object to the last argument of the function call. Except removing
the `--` prefix, there is no other conversion to the flag name. JSON values are
stringified before passed to `rclone`.

Each API functions can also take options for the spawned child process. See
https://nodejs.org/api/child_process.html#child_processspawncommand-args-options
for their documentation.

```js
const rclone = require("rclone.js");

const ls = rclone.ls("source:", {
  "max-depth": 1,
  // Spawn options:
  "env": {
    RCLONE_CONFIG: "~/.config/rclone/rclone.conf",
  },
  "shell": "/bin/sh",
});

ls.stdout.on("data", (data) => {
  console.log(data.toString());
});

ls.stderr.on("data", (data) => {
  console.error(data.toString());
});
```

There is also a Promise-based API:

```js
const rclone = require("rclone.js").promises;

(async function() {
  const results = await rclone.ls("source:", {
    "max-depth": 1,
    // Spawn options:
    "env": {
      RCLONE_CONFIG: "~/.config/rclone/rclone.conf",
    },
    "shell": "/bin/sh",
  });

  console.log(results);
})();
```

When the official `rclone` adds new command that has not been provided here,
we can still use the command through the default exported functions, passing
the command name as first argument:

```js
const rclone = require("rclone.js");

rclone("newcommand", "source:", "target:", {
  "flag": true,
});

(async function() {
  const results = await rclone.promises("newcommand", "source:", "target:", {
    "flag": true,
  });

  console.log(results);
})();
```

### CLI

This simple CLI calls the JS API above and outputs `stdout` and `stderr`.

```sh
$ npx rclone --version
rclone v1.54.0
- os/arch: darwin/amd64
- go version: go1.15.7
```

```sh
$ npx rclone ls source: --max-depth 1
          -1 2020-12-12 10:01:44        -1 Documents
          -1 2020-12-11 16:24:20        -1 Pictures
```

### Custom command

The CLI also supports executing a custom JS-based command to further extend
usage outside of what the official `rclone` offers:

```sh
$ npx rclone echo.js arg1 --string value arg2 --boolean
```

The custom JS file just needs to export a function that takes the arguments and
flags parsed from the CLI. It can either return a child process, or a `Promise`.
For a child process, its `stdout` and `stderr` are piped to the caller process.

Inside the function, `this` is set to `rclone.js` module.

```js
const { spawn } = require("child_process");

module.exports = function echo(arg1, arg2, flags = {}) {
  return spawn("echo", [arg1, arg2, JSON.stringify(flags)]);
}
```

The custom module is loaded through `require`, so it has some nice advantages
when [locating module](https://nodejs.org/api/modules.html#all-together):

- Does not need to specify `.js` extension, `custom` is same as `custom.js`.
- Considers both `foobar.js` and `foobar/index.js`.
- Can be extended through `NODE_PATH` environment variable.
- Can also use module from `node_modules` by its name.

With that, there are a few things custom commands can be used:

- Wraps existing API to add new functionality, such as `archive`.
- Defines a module with the same name as existing API to extend it with new
  flags and/or backends.

For a "real-life" example, check out [selfupdate](rclone/selfupdate.js), which
overrides the built-in `selfupdate` command to download rclone executable if it
has not been downloaded yet. Consecutive runs just call `selfupdate` API.

For publishing a custom `rclone` command as NPM package, consider prefixing the
package name with `rclone-` so it's clearer and not conflicting.

### Example Custom Commands

- [rclone-archive](https://www.npmjs.com/package/rclone-archive):
  Tracking https://github.com/rclone/rclone/issues/2815.