Skip to content

Developing and Installing Script Drives ​

JavaScript Drives add storage backends without recompiling go-drive. Extensions for Dropbox, Qiniu, and other services use this mechanism.

They are intended for storage services with HTTP/HTTPS APIs that can map files and directories to paths. They are not a general protocol runtime: SMB/Samba, SFTP, FTP, local filesystems, and services that require raw sockets, native libraries, Node.js packages, or operating-system commands need a built-in Go Drive instead.

Installation ​

Open Admin → Other Drives, refresh the repository, and select an extension to install. An extension usually contains:

  • <name>.js: the server-side Drive implementation.
  • an optional browser upload adapter, declared with @uploader and copied to drive-uploaders/<name>.js on install.

Default repository:

text
https://api.github.com/repos/devld/go-drive/contents/script-drives

It can be changed in the configuration:

yaml
drives-dir: script-drives
drive-uploaders-dir: drive-uploaders
drive-repository-url: https://example.com/my-drives.json

A custom repository returns an array in the style of the GitHub Contents API, with name and download_url. Only .js entries are downloaded:

json
[
  { "name": "example.js", "download_url": "https://example.com/example.js" },
  { "name": "example-uploader.js", "download_url": "https://example.com/example-uploader.js" }
]

The server script declares metadata in its leading comments:

js
// @name Example Cloud
// @version 1.0.0
// @uploader example-uploader.js
// @description Example Cloud REST API adapter.

Refreshing the repository runs as a background task. go-drive downloads every .js listing entry, then keeps scripts that declare both @name and @version. Uploaders are kept only when a drive script references them with @uploader. Files are stored under script-drives/.repo/ until install/update copies them into script-drives/ and drive-uploaders/. The management page uses the version to offer an update without uninstalling the script Drive. If the uploader changes, also bump the server script version. Installed scripts without @name or @version are not listed.

After installation, create the corresponding type on the Drive management page and reload the Drives.

Development entry points ​

Start with the current templates and definitions:

The template uses TypeScript references for editor completion, but the runtime is still server-side JavaScript. It runs on Goja with ES6+ syntax (let/const, arrow functions, classes, rest/spread, and modern array methods). Host APIs are fully synchronous and never return Promises; there is no event loop, asynchronous HTTP, timers, or top-level await. The old PascalCase Go wrapper API is incompatible; use the lowerCamel names exposed by the current mapper, after converting URL to Url, JSON to Json, and OAuth to Oauth before lowercasing the first letter. An implementation should:

  • Define a unique type name, display name, description, and configuration form.
  • Keep configForm static. Dynamic multi-step configuration belongs in explicit initConfig(config, env) and init(data, config, env) callbacks, following the native Drive lifecycle. Form fields beginning with _ are reserved.
  • Handle OAuth explicitly with env.oauthInitConfig, env.oauthInit, and env.oauthLoad; there is no automatic OAuth hook.
  • Implement createInstance(config, env), loading only the dynamic initialization fields needed by the Drive with env.data.load("key", ...).
  • Implement defineDrive with get and list, plus getURL or getReader, then the write, upload, download, and thumbnail methods supported by the service.
  • Return Unsupported from unavailable native copy operations so the dispatcher can stream-copy; note that move does not have a copy-and-delete fallback.
  • Host operations inherit the current execution context and its cancellation. Use http(url, { timeout }) to set a request-specific timeout.
  • Promptly close response bodies, readers, and remote connections.
  • Never write tokens, passwords, or signed URLs to logs.

Browser uploader ​

An uploader runs in the user's browser and can provide direct transfers to S3-like services. It must handle CORS, progress, cancellation, errors, and server-returned results. The server script and uploader are separate trust surfaces; review both when auditing an extension.

Debugging ​

  1. Install or edit the script in a test instance.
  2. Use a dedicated test account and directory.
  3. Set GO_DRIVE_LOGGING_LEVEL=debug for temporary diagnostic logs.
  4. Test empty files, large files, overwrite, directories, cancellation, network errors, and credential expiration separately.
  5. Remove the environment variable and reload the Drive when testing is complete.

Calls use a pool of concurrent script VMs. Ordinary mutable globals are not reliable shared state; only JSON-serializable $ instance properties are synchronized between VMs. Scripts can access the network and Drive data, so do not treat the runtime as a sandbox for untrusted code.

Released under the MIT License.