You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2026/06/11 08:46:33 UTC
(opendal) branch main updated: feat(website): Add per-service configuration reference pages (#7730)
This is an automated email from the ASF dual-hosted git repository.
Xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git
The following commit(s) were added to refs/heads/main by this push:
new 7c419a98b feat(website): Add per-service configuration reference pages (#7730)
7c419a98b is described below
commit 7c419a98b57dcb2dba9c6d84b381525c470982bc
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Thu Jun 11 16:46:27 2026 +0800
feat(website): Add per-service configuration reference pages (#7730)
* feat(dev): generate per-service configuration docs data
Add a `docs` target to the dev generator that emits
`website/data/services.json` from every service's `config.rs`: the
universal config fields (key, type, required, group, default/example)
plus ready-to-copy setup snippets for the Rust, Python, Node.js and Java
bindings, all derived from the same single source of truth.
Config fields may carry `@group`, `@default` and `@example` doc markers
to organize and document options; markers use an HTML-comment form so
they stay machine-readable while rendering invisibly in rustdoc. S3 and
GCS are annotated as the first examples; other services fall back to a
single default group. The odev CI job regenerates the data and fails on
drift.
* feat(website): add per-service configuration reference pages
Render a `/services` section from `services.json`: an index of every
service and, for each, a page with language tabs (a minimal quick start
and a full copy-and-trim reference), plus a configuration table grouped
by topic with collapsible advanced groups and default/example hints.
Routes are registered by a plugin, so every supported (service, binding)
pair also gets a deep-linkable page (e.g. `/services/s3/python`) without
cluttering the docs sidebar.
---
.github/workflows/ci_odev.yml | 3 +
core/services/gcs/src/config.rs | 31 +
core/services/s3/src/config.rs | 70 +
dev/src/generate/docs.rs | 458 ++
dev/src/generate/mod.rs | 2 +
dev/src/generate/parser.rs | 137 +-
website/data/services.json | 4807 +++++++++++++++++++++
website/docusaurus.config.js | 9 +-
website/plugins/services-docs-plugin.js | 103 +
website/src/components/services/ServicePage.jsx | 215 +
website/src/components/services/ServicesIndex.jsx | 79 +
website/src/components/services/styles.module.css | 251 ++
12 files changed, 6154 insertions(+), 11 deletions(-)
diff --git a/.github/workflows/ci_odev.yml b/.github/workflows/ci_odev.yml
index aa73684ff..eeb2063d0 100644
--- a/.github/workflows/ci_odev.yml
+++ b/.github/workflows/ci_odev.yml
@@ -76,6 +76,9 @@ jobs:
- name: Generate Java bindings code
run: cargo run --manifest-path=dev/Cargo.toml -- generate -l java
+
+ - name: Generate services documentation data
+ run: cargo run --manifest-path=dev/Cargo.toml -- generate -l docs
- run: cargo fmt --manifest-path bindings/python/Cargo.toml --all
- name: Check diff
diff --git a/core/services/gcs/src/config.rs b/core/services/gcs/src/config.rs
index 1ef2a925d..c4a8f7b01 100644
--- a/core/services/gcs/src/config.rs
+++ b/core/services/gcs/src/config.rs
@@ -28,8 +28,14 @@ use super::backend::GcsBuilder;
#[non_exhaustive]
pub struct GcsConfig {
/// root URI, all operations happens under `root`
+ ///
+ /// <!-- @group General -->
+ /// <!-- @default / -->
pub root: Option<String>,
/// bucket name
+ ///
+ /// <!-- @group General -->
+ /// <!-- @example my-bucket -->
#[serde(
alias = "google_bucket",
alias = "google_bucket_name",
@@ -38,10 +44,17 @@ pub struct GcsConfig {
pub bucket: String,
/// endpoint URI of GCS service,
/// default is `https://storage.googleapis.com`
+ ///
+ /// <!-- @group General -->
+ /// <!-- @default https://storage.googleapis.com -->
pub endpoint: Option<String>,
/// Scope for gcs.
+ ///
+ /// <!-- @group General -->
pub scope: Option<String>,
/// Service Account for gcs.
+ ///
+ /// <!-- @group Credentials -->
#[serde(
alias = "google_service_account",
alias = "google_service_account_path",
@@ -49,20 +62,32 @@ pub struct GcsConfig {
)]
pub service_account: Option<String>,
/// Credentials string for GCS service OAuth2 authentication.
+ ///
+ /// <!-- @group Credentials -->
#[serde(alias = "google_service_account_key", alias = "service_account_key")]
pub credential: Option<String>,
/// Local path to credentials file for GCS service OAuth2 authentication.
+ ///
+ /// <!-- @group Credentials -->
#[serde(alias = "google_application_credentials")]
pub credential_path: Option<String>,
/// The predefined acl for GCS.
+ ///
+ /// <!-- @group Behavior -->
pub predefined_acl: Option<String>,
/// The default storage class used by gcs.
+ ///
+ /// <!-- @group Behavior -->
pub default_storage_class: Option<String>,
/// Skip signature will skip loading credentials and signing requests.
+ ///
+ /// <!-- @group Credentials -->
#[serde(alias = "google_skip_signature")]
pub skip_signature: bool,
/// Allow opendal to send requests without signing when credentials are not
/// loaded.
+ ///
+ /// <!-- @group Deprecated -->
#[deprecated(
since = "0.57.0",
note = "Please use `skip_signature` instead of `allow_anonymous`"
@@ -70,12 +95,18 @@ pub struct GcsConfig {
pub allow_anonymous: bool,
/// Disable attempting to load credentials from the GCE metadata server when
/// running within Google Cloud.
+ ///
+ /// <!-- @group Credentials -->
pub disable_vm_metadata: bool,
/// Disable loading configuration from the environment.
+ ///
+ /// <!-- @group Credentials -->
pub disable_config_load: bool,
/// A Google Cloud OAuth2 token.
///
/// Takes precedence over `credential` and `credential_path`.
+ ///
+ /// <!-- @group Credentials -->
pub token: Option<String>,
}
diff --git a/core/services/s3/src/config.rs b/core/services/s3/src/config.rs
index 912a6eefc..0b3a7cafe 100644
--- a/core/services/s3/src/config.rs
+++ b/core/services/s3/src/config.rs
@@ -37,13 +37,21 @@ pub struct S3Config {
/// All operations will happen under this root.
///
/// default to `/` if not set.
+ ///
+ /// <!-- @group General -->
+ /// <!-- @default / -->
pub root: Option<String>,
/// bucket name of this backend.
///
/// required.
+ ///
+ /// <!-- @group General -->
+ /// <!-- @example my-bucket -->
#[serde(alias = "aws_bucket", alias = "aws_bucket_name", alias = "bucket_name")]
pub bucket: String,
/// Deprecated: S3 versioning capability is enabled by default.
+ ///
+ /// <!-- @group Deprecated -->
#[deprecated(
since = "0.57.0",
note = "S3 versioning capability is enabled by default and this option is no longer needed."
@@ -65,6 +73,9 @@ pub struct S3Config {
/// - If endpoint is set, we will take user's input first.
/// - If not, we will try to load it from environment.
/// - If still not set, default to `https://s3.amazonaws.com`.
+ ///
+ /// <!-- @group General -->
+ /// <!-- @default https://s3.amazonaws.com -->
#[serde(
alias = "aws_endpoint",
alias = "aws_endpoint_url",
@@ -77,6 +88,9 @@ pub struct S3Config {
/// If using a custom endpoint,
/// - If region is set, we will take user's input first.
/// - If not, we will try to load it from environment.
+ ///
+ /// <!-- @group General -->
+ /// <!-- @example us-east-1 -->
#[serde(alias = "aws_region")]
pub region: Option<String>,
@@ -84,32 +98,48 @@ pub struct S3Config {
///
/// - If access_key_id is set, we will take user's input first.
/// - If not, we will try to load it from environment.
+ ///
+ /// <!-- @group Credentials -->
#[serde(alias = "aws_access_key_id")]
pub access_key_id: Option<String>,
/// secret_access_key of this backend.
///
/// - If secret_access_key is set, we will take user's input first.
/// - If not, we will try to load it from environment.
+ ///
+ /// <!-- @group Credentials -->
#[serde(alias = "aws_secret_access_key")]
pub secret_access_key: Option<String>,
/// session_token (aka, security token) of this backend.
///
/// This token will expire after sometime, it's recommended to set session_token
/// by hand.
+ ///
+ /// <!-- @group Credentials -->
#[serde(alias = "aws_session_token", alias = "aws_token", alias = "token")]
pub session_token: Option<String>,
/// role_arn for this backend.
///
/// If `role_arn` is set, we will use already known config as source
/// credential to assume role with `role_arn`.
+ ///
+ /// <!-- @group Assume role -->
pub role_arn: Option<String>,
/// external_id for this backend.
+ ///
+ /// <!-- @group Assume role -->
pub external_id: Option<String>,
/// role_session_name for this backend.
+ ///
+ /// <!-- @group Assume role -->
pub role_session_name: Option<String>,
/// assume_role_duration_seconds for this backend.
+ ///
+ /// <!-- @group Assume role -->
pub assume_role_duration_seconds: Option<u32>,
/// assume_role_session_tags for this backend.
+ ///
+ /// <!-- @group Assume role -->
pub assume_role_session_tags: Option<HashMap<String, String>>,
/// Disable config load so that opendal will not load config from
/// environment.
@@ -118,16 +148,24 @@ pub struct S3Config {
///
/// - envs like `AWS_ACCESS_KEY_ID`
/// - files like `~/.aws/config`
+ ///
+ /// <!-- @group Credentials -->
pub disable_config_load: bool,
/// Disable load credential from ec2 metadata.
///
/// This option is used to disable the default behavior of opendal
/// to load credential from ec2 metadata, a.k.a., IMDSv2
+ ///
+ /// <!-- @group Credentials -->
pub disable_ec2_metadata: bool,
/// Skip signature will skip loading credentials and signing requests.
+ ///
+ /// <!-- @group Credentials -->
pub skip_signature: bool,
/// Allow anonymous will allow opendal to send request without signing
/// when credential is not loaded.
+ ///
+ /// <!-- @group Deprecated -->
#[deprecated(
since = "0.57.0",
note = "Please use `skip_signature` instead of `allow_anonymous`"
@@ -136,6 +174,8 @@ pub struct S3Config {
/// server_side_encryption for this backend.
///
/// Available values: `AES256`, `aws:kms`.
+ ///
+ /// <!-- @group Encryption -->
#[serde(alias = "aws_server_side_encryption")]
pub server_side_encryption: Option<String>,
/// server_side_encryption_aws_kms_key_id for this backend
@@ -148,21 +188,29 @@ pub struct S3Config {
/// returned.
/// - If `server_side_encryption` is not `aws:kms`, setting `server_side_encryption_aws_kms_key_id`
/// is a noop.
+ ///
+ /// <!-- @group Encryption -->
#[serde(alias = "aws_sse_kms_key_id")]
pub server_side_encryption_aws_kms_key_id: Option<String>,
/// server_side_encryption_customer_algorithm for this backend.
///
/// Available values: `AES256`.
+ ///
+ /// <!-- @group Encryption -->
pub server_side_encryption_customer_algorithm: Option<String>,
/// server_side_encryption_customer_key for this backend.
///
/// Value: BASE64-encoded key that matches algorithm specified in
/// `server_side_encryption_customer_algorithm`.
+ ///
+ /// <!-- @group Encryption -->
#[serde(alias = "aws_sse_customer_key_base64")]
pub server_side_encryption_customer_key: Option<String>,
/// Set server_side_encryption_customer_key_md5 for this backend.
///
/// Value: MD5 digest of key specified in `server_side_encryption_customer_key`.
+ ///
+ /// <!-- @group Encryption -->
pub server_side_encryption_customer_key_md5: Option<String>,
/// default storage_class for this backend.
///
@@ -179,30 +227,40 @@ pub struct S3Config {
/// - `STANDARD_IA`
///
/// S3 compatible services don't support all of them
+ ///
+ /// <!-- @group Behavior -->
pub default_storage_class: Option<String>,
/// Enable virtual host style so that opendal will send API requests
/// in virtual host style instead of path style.
///
/// - By default, opendal will send API to `https://s3.us-east-1.amazonaws.com/bucket_name`
/// - Enabled, opendal will send API to `https://bucket_name.s3.us-east-1.amazonaws.com`
+ ///
+ /// <!-- @group Behavior -->
#[serde(
alias = "aws_virtual_hosted_style_request",
alias = "virtual_hosted_style_request"
)]
pub enable_virtual_host_style: bool,
/// Deprecated: S3 delete batch capability is enabled by default.
+ ///
+ /// <!-- @group Deprecated -->
#[deprecated(
since = "0.57.0",
note = "S3 delete batch capability is enabled by default. Use CapabilityOverrideLayer to override delete_max_size for specific endpoints."
)]
pub batch_max_operations: Option<usize>,
/// Deprecated: S3 delete batch capability is enabled by default.
+ ///
+ /// <!-- @group Deprecated -->
#[deprecated(
since = "0.57.0",
note = "S3 delete batch capability is enabled by default. Use CapabilityOverrideLayer to override delete_max_size for specific endpoints."
)]
pub delete_max_size: Option<usize>,
/// Deprecated: S3 stat override capabilities are enabled by default.
+ ///
+ /// <!-- @group Deprecated -->
#[deprecated(
since = "0.57.0",
note = "S3 stat override capabilities are enabled by default. Use CapabilityOverrideLayer to override them for specific endpoints."
@@ -214,9 +272,13 @@ pub struct S3Config {
/// Available options:
/// - "crc32c"
/// - "md5"
+ ///
+ /// <!-- @group Behavior -->
#[serde(alias = "aws_checksum_algorithm")]
pub checksum_algorithm: Option<String>,
/// Deprecated: S3 write with If-Match capability is enabled by default.
+ ///
+ /// <!-- @group Deprecated -->
#[deprecated(
since = "0.57.0",
note = "S3 write with If-Match capability is enabled by default and this option is no longer needed."
@@ -224,6 +286,8 @@ pub struct S3Config {
pub disable_write_with_if_match: bool,
/// Deprecated: S3 append capability is enabled by default.
+ ///
+ /// <!-- @group Deprecated -->
#[deprecated(
since = "0.57.0",
note = "S3 append capability is enabled by default and this option is no longer needed."
@@ -233,14 +297,20 @@ pub struct S3Config {
/// OpenDAL uses List Objects V2 by default to list objects.
/// However, some legacy services do not yet support V2.
/// This option allows users to switch back to the older List Objects V1.
+ ///
+ /// <!-- @group Behavior -->
pub disable_list_objects_v2: bool,
/// Indicates whether the client agrees to pay for the requests made to the S3 bucket.
+ ///
+ /// <!-- @group Behavior -->
#[serde(alias = "aws_request_payer", alias = "request_payer")]
pub enable_request_payer: bool,
/// Default ACL for new objects.
/// Note that some s3 services like minio do not support this option.
+ ///
+ /// <!-- @group Behavior -->
pub default_acl: Option<String>,
}
diff --git a/dev/src/generate/docs.rs b/dev/src/generate/docs.rs
new file mode 100644
index 000000000..2e36b185b
--- /dev/null
+++ b/dev/src/generate/docs.rs
@@ -0,0 +1,458 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//! Generate a single `services.json` that drives the website's per-service
+//! configuration documentation.
+//!
+//! The config fields (keys, types, required, comments) are the universal
+//! source of truth shared by every binding, so the data is emitted once per
+//! service. On top of that we render ready-to-copy snippets for the bindings
+//! whose config-passing API is a plain `String -> String` map, which is the
+//! exact shape `via_iter` / `Operator.of(map)` / kwargs / `new Operator(obj)`
+//! all expect. Adding a new binding is a matter of adding an entry to
+//! [`BINDINGS`] plus a snippet renderer in [`render_examples`].
+
+use crate::generate::parser::{AttrDeprecated, Config, ConfigType, Services};
+use anyhow::{Context, Result};
+use regex::Regex;
+use serde::Serialize;
+use std::collections::HashSet;
+use std::fs;
+use std::path::{Path, PathBuf};
+
+/// A binding we can render copy-paste snippets for.
+struct Binding {
+ /// Stable id, also used in the page URL: `/services/<scheme>/<id>`.
+ id: &'static str,
+ /// Human readable label shown on the language tab.
+ label: &'static str,
+ /// Prism language id used for syntax highlighting in the code block.
+ language: &'static str,
+ /// Path (relative to the workspace root) of the binding crate's
+ /// `Cargo.toml`, used to learn which services it enables. `None` means the
+ /// binding exposes every service (this is the case for the Rust crate
+ /// itself, which is the source of all services).
+ cargo: Option<&'static str>,
+}
+
+const BINDINGS: &[Binding] = &[
+ Binding {
+ id: "rust",
+ label: "Rust",
+ language: "rust",
+ cargo: None,
+ },
+ Binding {
+ id: "python",
+ label: "Python",
+ language: "python",
+ cargo: Some("bindings/python/Cargo.toml"),
+ },
+ Binding {
+ id: "nodejs",
+ label: "Node.js",
+ language: "javascript",
+ cargo: Some("bindings/nodejs/Cargo.toml"),
+ },
+ Binding {
+ id: "java",
+ label: "Java",
+ language: "java",
+ cargo: Some("bindings/java/Cargo.toml"),
+ },
+];
+
+#[derive(Serialize)]
+struct DocsOutput {
+ bindings: Vec<BindingMeta>,
+ services: Vec<ServiceDoc>,
+}
+
+#[derive(Serialize)]
+struct BindingMeta {
+ id: String,
+ label: String,
+ language: String,
+}
+
+#[derive(Serialize)]
+struct ServiceDoc {
+ /// Directory name, e.g. `mini_moka`.
+ name: String,
+ /// The scheme users pass to a binding, e.g. `mini-moka`.
+ scheme: String,
+ /// Group names in display order (first appearance in the config struct).
+ groups: Vec<String>,
+ configs: Vec<ConfigDoc>,
+ examples: Vec<ServiceExample>,
+}
+
+#[derive(Serialize)]
+struct ConfigDoc {
+ name: String,
+ /// Friendly type name: `string`, `bool`, `integer`, `duration`, `list`, `map`.
+ #[serde(rename = "type")]
+ type_name: String,
+ required: bool,
+ /// Resolved group; defaults to [`DEFAULT_GROUP`] when the field is unmarked.
+ group: String,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ default: Option<String>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ example: Option<String>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ deprecated: Option<AttrDeprecated>,
+ comments: String,
+}
+
+/// Group assigned to fields without an explicit `@group` marker.
+const DEFAULT_GROUP: &str = "General";
+
+/// Conventional group name for deprecated options; always sorted last.
+const DEPRECATED_GROUP: &str = "Deprecated";
+
+#[derive(Serialize)]
+struct ServiceExample {
+ binding: String,
+ language: String,
+ minimal: String,
+ full: String,
+}
+
+pub fn generate(workspace_dir: PathBuf, services: Services) -> Result<()> {
+ // Resolve, per binding, the set of schemes it enables.
+ let support: Vec<Option<HashSet<String>>> = BINDINGS
+ .iter()
+ .map(|b| match b.cargo {
+ None => Ok(None),
+ Some(rel) => supported_schemes(&workspace_dir, rel).map(Some),
+ })
+ .collect::<Result<_>>()?;
+
+ let mut service_docs = Vec::with_capacity(services.len());
+ for (name, service) in services {
+ let scheme = name.replace('_', "-");
+
+ // Preserve source order: the order fields appear in the config struct is
+ // the author's logical order (root, bucket, endpoint, credentials, ...),
+ // which reads far better than an alphabetical dump.
+ let configs = &service.config;
+
+ // Group names in first-appearance order, across all fields (the table
+ // shows deprecated fields too, so they participate in group ordering).
+ let mut groups: Vec<String> = Vec::new();
+ for c in configs {
+ let g = c.group.clone().unwrap_or_else(|| DEFAULT_GROUP.to_string());
+ if !groups.contains(&g) {
+ groups.push(g);
+ }
+ }
+ // Deprecated options are noise for newcomers; always show them last.
+ if let Some(pos) = groups.iter().position(|g| g == DEPRECATED_GROUP) {
+ let g = groups.remove(pos);
+ groups.push(g);
+ }
+
+ // Fields usable in a snippet: not deprecated.
+ let fields: Vec<Field> = configs
+ .iter()
+ .filter(|c| c.deprecated.is_none())
+ .map(Field::from)
+ .collect();
+ let grouped = group_fields(&fields, &groups);
+ let required: Vec<&Field> = fields.iter().filter(|f| f.required).collect();
+
+ let mut examples = Vec::new();
+ for (binding, support) in BINDINGS.iter().zip(support.iter()) {
+ let enabled = match support {
+ None => true,
+ Some(set) => set.contains(&scheme),
+ };
+ if !enabled {
+ continue;
+ }
+ let (minimal, full) = render_examples(binding.id, &scheme, &required, &grouped);
+ examples.push(ServiceExample {
+ binding: binding.id.to_string(),
+ language: binding.language.to_string(),
+ minimal,
+ full,
+ });
+ }
+
+ service_docs.push(ServiceDoc {
+ name,
+ scheme,
+ groups,
+ configs: configs.iter().map(ConfigDoc::from).collect(),
+ examples,
+ });
+ }
+
+ service_docs.sort_by(|a, b| a.scheme.cmp(&b.scheme));
+
+ let output = DocsOutput {
+ bindings: BINDINGS
+ .iter()
+ .map(|b| BindingMeta {
+ id: b.id.to_string(),
+ label: b.label.to_string(),
+ language: b.language.to_string(),
+ })
+ .collect(),
+ services: service_docs,
+ };
+
+ let path = workspace_dir.join("website/data/services.json");
+ if let Some(parent) = path.parent() {
+ fs::create_dir_all(parent)?;
+ }
+ let json = serde_json::to_string_pretty(&output)?;
+ fs::write(&path, format!("{json}\n"))
+ .with_context(|| format!("failed to write {}", path.display()))?;
+ log::info!(
+ "generated {} with {} services",
+ path.display(),
+ output.services.len()
+ );
+ Ok(())
+}
+
+/// Collect the schemes a binding crate enables by scanning every `services-*`
+/// token in its `Cargo.toml`. Bindings declare services in two places: their
+/// own `[features]` table (Python, Node.js) or the `opendal` dependency's
+/// `features` list (Java), so a textual scan over non-comment text covers both
+/// layouts and naturally skips `# "services-foo"` lines that are turned off.
+/// Feature names are kebab-case and map directly to a scheme once the
+/// `services-` prefix is stripped.
+fn supported_schemes(workspace: &Path, cargo_rel: &str) -> Result<HashSet<String>> {
+ let path = workspace.join(cargo_rel);
+ let content =
+ fs::read_to_string(&path).with_context(|| format!("failed to read {}", path.display()))?;
+
+ let re = Regex::new(r"services-([a-z0-9-]+)").expect("valid regex");
+ let mut set = HashSet::new();
+ for line in content.lines() {
+ // Cargo.toml comments run from `#` to end of line; service names never
+ // contain `#`, so cutting there is enough to ignore disabled services.
+ let code = line.split('#').next().unwrap_or(line);
+ for cap in re.captures_iter(code) {
+ set.insert(cap[1].to_string());
+ }
+ }
+ Ok(set)
+}
+
+/// A single config field reduced to what the renderers need.
+struct Field<'a> {
+ name: &'a str,
+ value: ConfigType,
+ required: bool,
+ comments: &'a str,
+ group: &'a str,
+ default: Option<&'a str>,
+ example: Option<&'a str>,
+}
+
+impl<'a> From<&'a Config> for Field<'a> {
+ fn from(c: &'a Config) -> Self {
+ Field {
+ name: &c.name,
+ value: c.value,
+ required: !c.optional,
+ comments: &c.comments,
+ group: c.group.as_deref().unwrap_or(DEFAULT_GROUP),
+ default: c.default_value.as_deref(),
+ example: c.example.as_deref(),
+ }
+ }
+}
+
+impl From<&Config> for ConfigDoc {
+ fn from(c: &Config) -> Self {
+ ConfigDoc {
+ name: c.name.clone(),
+ type_name: friendly_type(c.value).to_string(),
+ required: !c.optional,
+ group: c.group.clone().unwrap_or_else(|| DEFAULT_GROUP.to_string()),
+ default: c.default_value.clone(),
+ example: c.example.clone(),
+ deprecated: c.deprecated.clone(),
+ comments: c.comments.clone(),
+ }
+ }
+}
+
+/// Cluster fields by group, in the given group order, dropping empty groups.
+fn group_fields<'a>(
+ fields: &'a [Field<'a>],
+ groups: &'a [String],
+) -> Vec<(&'a str, Vec<&'a Field<'a>>)> {
+ groups
+ .iter()
+ .map(|g| {
+ let items: Vec<&Field> = fields.iter().filter(|f| f.group == g).collect();
+ (g.as_str(), items)
+ })
+ .filter(|(_, items)| !items.is_empty())
+ .collect()
+}
+
+fn friendly_type(ty: ConfigType) -> &'static str {
+ match ty {
+ ConfigType::Bool => "bool",
+ ConfigType::String => "string",
+ ConfigType::Duration => "duration",
+ ConfigType::Usize
+ | ConfigType::U64
+ | ConfigType::I64
+ | ConfigType::U32
+ | ConfigType::U16 => "integer",
+ ConfigType::Vec => "list",
+ ConfigType::HashMap => "map",
+ }
+}
+
+/// Example string value for a field. Prefers an explicit `@default`; otherwise
+/// falls back to a per-type placeholder. Every binding here passes config as a
+/// `String -> String` map, so even non-string types are quoted strings that
+/// OpenDAL's `ConfigDeserializer` parses (e.g. `"true"`, `"10s"`, `"a,b"`).
+fn value_of<'a>(f: &Field<'a>) -> &'a str {
+ let placeholder = match f.value {
+ ConfigType::Bool => "true",
+ ConfigType::String | ConfigType::HashMap => "...",
+ ConfigType::Duration => "10s",
+ ConfigType::Usize
+ | ConfigType::U64
+ | ConfigType::I64
+ | ConfigType::U32
+ | ConfigType::U16 => "1000",
+ ConfigType::Vec => "value1,value2",
+ };
+ f.default.or(f.example).unwrap_or(placeholder)
+}
+
+/// Per-binding syntax used by the generic snippet builder.
+struct Syntax {
+ /// Import lines plus the opening of the call, ready for fields to follow.
+ open: String,
+ /// Text closing the call.
+ close: String,
+ /// Indentation for field lines.
+ indent: &'static str,
+ /// Line-comment marker, e.g. `# ` or `// `.
+ comment: &'static str,
+ /// Render a single `key = value` assignment (no indent, no comment marker).
+ assign: fn(&Field) -> String,
+}
+
+/// Build the `(minimal, full)` snippet pair for one binding.
+///
+/// `minimal` lists only the required fields. `full` walks every group in order,
+/// emitting a group header (when there is more than one group), each field's
+/// doc comment, and the assignment — uncommented when required, commented out
+/// otherwise so the block is a copy-and-trim reference.
+fn build(required: &[&Field], grouped: &[(&str, Vec<&Field>)], s: &Syntax) -> (String, String) {
+ let doc_prefix = format!("{}{}", s.indent, s.comment);
+
+ let comment_block = |comments: &str, out: &mut String| {
+ for line in comments.lines() {
+ if line.trim().is_empty() {
+ out.push_str(doc_prefix.trim_end());
+ } else {
+ out.push_str(&doc_prefix);
+ out.push_str(line);
+ }
+ out.push('\n');
+ }
+ };
+
+ let mut minimal = s.open.clone();
+ for f in required {
+ minimal.push_str(&format!("{}{}\n", s.indent, (s.assign)(f)));
+ }
+ minimal.push_str(&s.close);
+
+ let multi = grouped.len() > 1;
+ let mut full = s.open.clone();
+ for (group, fields) in grouped {
+ if multi {
+ full.push_str(&format!("{}{}--- {group} ---\n", s.indent, s.comment));
+ }
+ for f in fields {
+ comment_block(f.comments, &mut full);
+ let assign = (s.assign)(f);
+ if f.required {
+ full.push_str(&format!("{}{assign}\n\n", s.indent));
+ } else {
+ full.push_str(&format!("{}{}{assign}\n\n", s.indent, s.comment));
+ }
+ }
+ }
+ full.push_str(&s.close);
+
+ (minimal, full)
+}
+
+fn render_examples(
+ binding: &str,
+ scheme: &str,
+ required: &[&Field],
+ grouped: &[(&str, Vec<&Field>)],
+) -> (String, String) {
+ let syntax = match binding {
+ "rust" => Syntax {
+ open: format!("use opendal::Operator;\n\nlet op = Operator::via_iter(\"{scheme}\", [\n"),
+ close: "])?;".to_string(),
+ indent: " ",
+ comment: "// ",
+ assign: |f| {
+ format!(
+ "(\"{}\".to_string(), \"{}\".to_string()),",
+ f.name,
+ value_of(f)
+ )
+ },
+ },
+ "python" => Syntax {
+ open: format!("import opendal\n\nop = opendal.Operator(\n \"{scheme}\",\n"),
+ close: ")".to_string(),
+ indent: " ",
+ comment: "# ",
+ assign: |f| format!("{}=\"{}\",", f.name, value_of(f)),
+ },
+ "nodejs" => Syntax {
+ open: format!(
+ "import {{ Operator }} from \"opendal\";\n\nconst op = new Operator(\"{scheme}\", {{\n"
+ ),
+ close: "});".to_string(),
+ indent: " ",
+ comment: "// ",
+ assign: |f| format!("{}: \"{}\",", f.name, value_of(f)),
+ },
+ "java" => Syntax {
+ open: "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n".to_string(),
+ close: format!("Operator op = Operator.of(\"{scheme}\", conf);"),
+ indent: "",
+ comment: "// ",
+ assign: |f| format!("conf.put(\"{}\", \"{}\");", f.name, value_of(f)),
+ },
+ other => unreachable!("no renderer for binding {other}"),
+ };
+
+ build(required, grouped, &syntax)
+}
diff --git a/dev/src/generate/mod.rs b/dev/src/generate/mod.rs
index b3d52cb8f..75e70e393 100644
--- a/dev/src/generate/mod.rs
+++ b/dev/src/generate/mod.rs
@@ -15,6 +15,7 @@
// specific language governing permissions and limitations
// under the License.
+mod docs;
mod java;
mod parser;
mod python;
@@ -41,6 +42,7 @@ pub fn run(language: &str) -> Result<()> {
match language {
"java" => java::generate(workspace_dir, services),
"python" | "py" => python::generate(workspace_dir, services),
+ "docs" => docs::generate(workspace_dir, services),
_ => anyhow::bail!("unsupported language: {}", language),
}
}
diff --git a/dev/src/generate/parser.rs b/dev/src/generate/parser.rs
index 8d6fb8897..2cf13d28b 100644
--- a/dev/src/generate/parser.rs
+++ b/dev/src/generate/parser.rs
@@ -67,6 +67,14 @@ pub struct Config {
///
/// All white spaces and extra new lines will be trimmed.
pub comments: String,
+ /// The group this config belongs to, parsed from a `@group <name>` doc
+ /// marker. Used to organize the configuration reference by topic instead of
+ /// a flat list. `None` means the field is ungrouped.
+ pub group: Option<String>,
+ /// The default value, parsed from a `@default <value>` doc marker.
+ pub default_value: Option<String>,
+ /// An example value, parsed from a `@example <value>` doc marker.
+ pub example: Option<String>,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
@@ -151,6 +159,15 @@ pub struct AttrDeprecated {
pub note: String,
}
+/// Structured markers extracted from a field's doc comment, e.g. `@group`,
+/// `@default` and `@example`.
+#[derive(Debug, Default, Clone, Eq, PartialEq)]
+struct DocMarkers {
+ group: Option<String>,
+ default_value: Option<String>,
+ example: Option<String>,
+}
+
/// List and parse given path to a `Services` struct.
fn collect_custom_type_names(items: &[Item]) -> HashSet<String> {
fn extract_name(tree: &UseTree) -> Option<String> {
@@ -275,6 +292,7 @@ impl ServiceParser {
let deprecated = Self::parse_attr_deprecated(&field)?;
let comments = Self::parse_attr_comments(&field)?;
+ let markers = Self::parse_attr_markers(&field);
let (cfg_type, optional) = match &field.ty {
Type::Path(TypePath { path, .. }) => {
@@ -323,14 +341,15 @@ impl ServiceParser {
optional,
deprecated,
comments,
+ group: markers.group,
+ default_value: markers.default_value,
+ example: markers.example,
})
}
- /// Parse the comments attr from the field.
- ///
- /// This comment may have multiple lines.
- fn parse_attr_comments(field: &Field) -> Result<String> {
- Ok(field
+ /// Collect the doc comment of a field as a list of trimmed lines.
+ fn doc_lines(field: &Field) -> Vec<String> {
+ field
.attrs
.iter()
.filter(|attr| attr.path().is_ident("doc"))
@@ -346,8 +365,66 @@ impl ServiceParser {
None
})
- .collect::<Vec<_>>()
- .join("\n"))
+ .collect()
+ }
+
+ /// Recognize a structured doc marker line such as `@group Credentials` or
+ /// `@default /`. Returns `(key, value)` only for keys we understand, so any
+ /// other `@`-prefixed line stays part of the human-facing comment.
+ ///
+ /// Markers may be wrapped in an HTML comment — `<!-- @group Credentials -->`
+ /// — so they stay machine-readable here while rendering invisibly in
+ /// rustdoc (CommonMark passes HTML comments through undisplayed).
+ fn parse_marker(line: &str) -> Option<(&'static str, String)> {
+ let line = line.trim();
+ let inner = line
+ .strip_prefix("<!--")
+ .and_then(|l| l.strip_suffix("-->"))
+ .map(str::trim)
+ .unwrap_or(line);
+ let rest = inner.strip_prefix('@')?;
+ let (key, value) = rest.split_once(char::is_whitespace)?;
+ let value = value.trim().to_string();
+ match key {
+ "group" => Some(("group", value)),
+ "default" => Some(("default", value)),
+ "example" => Some(("example", value)),
+ _ => None,
+ }
+ }
+
+ /// Parse the comments attr from the field, with structured `@`-markers
+ /// stripped out so they don't leak into the human-facing description.
+ ///
+ /// This comment may have multiple lines.
+ fn parse_attr_comments(field: &Field) -> Result<String> {
+ let mut lines: Vec<String> = Self::doc_lines(field)
+ .into_iter()
+ .filter(|line| Self::parse_marker(line).is_none())
+ .collect();
+
+ // Drop blank lines left dangling at the end once markers are removed.
+ while lines.last().is_some_and(|l| l.is_empty()) {
+ lines.pop();
+ }
+
+ Ok(lines.join("\n").trim().to_string())
+ }
+
+ /// Parse the structured `@`-markers from a field's doc comment.
+ fn parse_attr_markers(field: &Field) -> DocMarkers {
+ let mut markers = DocMarkers::default();
+ for line in Self::doc_lines(field) {
+ if let Some((key, value)) = Self::parse_marker(&line) {
+ match key {
+ "group" => markers.group = Some(value),
+ "default" => markers.default_value = Some(value),
+ "example" => markers.example = Some(value),
+ _ => {}
+ }
+ }
+ }
+ markers
}
/// Parse the deprecated attr from the field.
@@ -420,6 +497,9 @@ mod tests {
optional: true,
deprecated: None,
comments: "".to_string(),
+ group: None,
+ default_value: None,
+ example: None,
},
),
(
@@ -430,6 +510,9 @@ mod tests {
optional: false,
deprecated: None,
comments: "".to_string(),
+ group: None,
+ default_value: None,
+ example: None,
},
),
];
@@ -437,9 +520,11 @@ mod tests {
for (input, expected) in cases {
let input = format!("struct Test {{ {input} }}");
let x: ItemStruct = syn::parse_str(&input).unwrap();
- let actual =
- ServiceParser::parse_field(x.fields.iter().next().unwrap().clone(), &HashSet::new())
- .unwrap();
+ let actual = ServiceParser::parse_field(
+ x.fields.iter().next().unwrap().clone(),
+ &HashSet::new(),
+ )
+ .unwrap();
assert_eq!(actual, expected);
}
}
@@ -706,6 +791,9 @@ For example, R2 could return `Internal Error` while batch delete 1000 files.
Please tune this value based on services' document."
.to_string(),
+ group: None,
+ default_value: None,
+ example: None,
},
);
assert_eq!(
@@ -718,10 +806,39 @@ Please tune this value based on services' document."
comments: r"Disable write with if match so that opendal will not send write request with if match headers.
For example, Ceph RADOS S3 doesn't support write with if match.".to_string(),
+ group: None,
+ default_value: None,
+ example: None,
},
);
}
+ #[test]
+ fn test_parse_field_markers() {
+ let input = r#"
+ struct Test {
+ /// bucket name of this backend.
+ ///
+ /// required.
+ ///
+ /// <!-- @group General -->
+ /// <!-- @default my-bucket -->
+ /// @example example-bucket
+ pub bucket: String
+ }
+ "#;
+ let x: ItemStruct = syn::parse_str(input).unwrap();
+ let actual =
+ ServiceParser::parse_field(x.fields.iter().next().unwrap().clone(), &HashSet::new())
+ .unwrap();
+
+ // Markers are extracted as structured fields and stripped from comments.
+ assert_eq!(actual.group.as_deref(), Some("General"));
+ assert_eq!(actual.default_value.as_deref(), Some("my-bucket"));
+ assert_eq!(actual.example.as_deref(), Some("example-bucket"));
+ assert_eq!(actual.comments, "bucket name of this backend.\n\nrequired.");
+ }
+
#[test]
fn test_parse() {
let path = workspace_dir()
diff --git a/website/data/services.json b/website/data/services.json
new file mode 100644
index 000000000..80c78f6e2
--- /dev/null
+++ b/website/data/services.json
@@ -0,0 +1,4807 @@
+{
+ "bindings": [
+ {
+ "id": "rust",
+ "label": "Rust",
+ "language": "rust"
+ },
+ {
+ "id": "python",
+ "label": "Python",
+ "language": "python"
+ },
+ {
+ "id": "nodejs",
+ "label": "Node.js",
+ "language": "javascript"
+ },
+ {
+ "id": "java",
+ "label": "Java",
+ "language": "java"
+ }
+ ],
+ "services": [
+ {
+ "name": "aliyun-drive",
+ "scheme": "aliyun-drive",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The Root of this backend.\n\nAll operations will happen under this root.\n\nDefault to `/` if not set."
+ },
+ {
+ "name": "access_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The access_token of this backend.\n\nSolution for client-only purpose. #4733\n\nRequired if no client_id, client_secret and refresh_token are provided."
+ },
+ {
+ "name": "client_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The client_id of this backend.\n\nRequired if no access_token is provided."
+ },
+ {
+ "name": "client_secret",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The client_secret of this backend.\n\nRequired if no access_token is provided."
+ },
+ {
+ "name": "refresh_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The refresh_token of this backend.\n\nRequired if no access_token is provided."
+ },
+ {
+ "name": "drive_type",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "The drive_type of this backend.\n\nAll operations will happen under this type of drive.\n\nAvailable values are `default`, `backup` and `resource`.\n\nFallback to default if not set or no other drives can be found."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"aliyun-drive\", [\n (\"drive_type\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"aliyun-drive\", [\n // The Root of this backend.\n //\n // All operations will happen under this root.\n //\n // Default to `/` if not set.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // The access_token of this backend.\n //\n // Solution for client-only purpose. #4733\n //\n // Required if no client_id, client_secret and refresh_token are provided.\n // (\"access_tok [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"aliyun-drive\",\n drive_type=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"aliyun-drive\",\n # The Root of this backend.\n #\n # All operations will happen under this root.\n #\n # Default to `/` if not set.\n # root=\"...\",\n\n # The access_token of this backend.\n #\n # Solution for client-only purpose. #4733\n #\n # Required if no client_id, client_secret and refresh_token are provided.\n # access_token=\"...\",\n\n # The client_id of this backend.\n [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"aliyun-drive\", {\n drive_type: \"...\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"aliyun-drive\", {\n // The Root of this backend.\n //\n // All operations will happen under this root.\n //\n // Default to `/` if not set.\n // root: \"...\",\n\n // The access_token of this backend.\n //\n // Solution for client-only purpose. #4733\n //\n // Required if no client_id, client_secret and refresh_token are provided.\n // access_token: \"...\",\n\n // The client_id of this bac [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"drive_type\", \"...\");\nOperator op = Operator.of(\"aliyun-drive\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// The Root of this backend.\n//\n// All operations will happen under this root.\n//\n// Default to `/` if not set.\n// conf.put(\"root\", \"...\");\n\n// The access_token of this backend.\n//\n// Solution for client-only purpose. #4733\n//\n// Required if no client_id, client_secret and refresh_token are provided.\n// conf.put(\"access_ [...]
+ }
+ ]
+ },
+ {
+ "name": "alluxio",
+ "scheme": "alluxio",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend.\n\nAll operations will happen under this root.\n\ndefault to `/` if not set."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "endpoint of this backend.\n\nEndpoint must be full uri, mostly like `http://127.0.0.1:39999`."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"alluxio\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"alluxio\", [\n // root of this backend.\n //\n // All operations will happen under this root.\n //\n // default to `/` if not set.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // endpoint of this backend.\n //\n // Endpoint must be full uri, mostly like `http://127.0.0.1:39999`.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"alluxio\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"alluxio\",\n # root of this backend.\n #\n # All operations will happen under this root.\n #\n # default to `/` if not set.\n # root=\"...\",\n\n # endpoint of this backend.\n #\n # Endpoint must be full uri, mostly like `http://127.0.0.1:39999`.\n # endpoint=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"alluxio\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"alluxio\", {\n // root of this backend.\n //\n // All operations will happen under this root.\n //\n // default to `/` if not set.\n // root: \"...\",\n\n // endpoint of this backend.\n //\n // Endpoint must be full uri, mostly like `http://127.0.0.1:39999`.\n // endpoint: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"alluxio\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// root of this backend.\n//\n// All operations will happen under this root.\n//\n// default to `/` if not set.\n// conf.put(\"root\", \"...\");\n\n// endpoint of this backend.\n//\n// Endpoint must be full uri, mostly like `http://127.0.0.1:39999`.\n// conf.put(\"endpoint\", \"...\");\n\nOperator op = Operator.of(\"alluxio\", conf);"
+ }
+ ]
+ },
+ {
+ "name": "azblob",
+ "scheme": "azblob",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The root of Azblob service backend.\n\nAll operations will happen under this root."
+ },
+ {
+ "name": "container",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "The container name of Azblob service backend."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The endpoint of Azblob service backend.\n\nEndpoint must be full uri, e.g.\n\n- Azblob: `https://accountname.blob.core.windows.net`\n- Azurite: `http://127.0.0.1:10000/devstoreaccount1`"
+ },
+ {
+ "name": "account_name",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The account name of Azblob service backend."
+ },
+ {
+ "name": "account_key",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The account key of Azblob service backend."
+ },
+ {
+ "name": "encryption_key",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The encryption key of Azblob service backend."
+ },
+ {
+ "name": "encryption_key_sha256",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The encryption key sha256 of Azblob service backend."
+ },
+ {
+ "name": "encryption_algorithm",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The encryption algorithm of Azblob service backend."
+ },
+ {
+ "name": "sas_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The sas token of Azblob service backend."
+ },
+ {
+ "name": "batch_max_operations",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "Azblob delete batch capability is enabled by default with Azure Blob's 256-operation batch limit. Use CapabilityOverrideLayer to override delete_max_size for specific endpoints."
+ },
+ "comments": "Deprecated: Azblob delete batch capability is enabled by default with Azure Blob's 256-operation batch limit."
+ },
+ {
+ "name": "skip_signature",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "comments": "Skip signature will skip loading credentials and signing requests."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"azblob\", [\n (\"container\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"azblob\", [\n // The root of Azblob service backend.\n //\n // All operations will happen under this root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // The container name of Azblob service backend.\n (\"container\".to_string(), \"...\".to_string()),\n\n // The endpoint of Azblob service backend.\n //\n // Endpoint must be full uri, e.g.\n //\n // - Azblob: `https://acco [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"azblob\",\n container=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"azblob\",\n # The root of Azblob service backend.\n #\n # All operations will happen under this root.\n # root=\"...\",\n\n # The container name of Azblob service backend.\n container=\"...\",\n\n # The endpoint of Azblob service backend.\n #\n # Endpoint must be full uri, e.g.\n #\n # - Azblob: `https://accountname.blob.core.windows.net`\n # - Azurite: `http://127.0.0.1:10000/devstorea [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"azblob\", {\n container: \"...\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"azblob\", {\n // The root of Azblob service backend.\n //\n // All operations will happen under this root.\n // root: \"...\",\n\n // The container name of Azblob service backend.\n container: \"...\",\n\n // The endpoint of Azblob service backend.\n //\n // Endpoint must be full uri, e.g.\n //\n // - Azblob: `https://accountname.blob.core.windows.net`\n // - Azurite: `http://127.0.0.1:10000 [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"container\", \"...\");\nOperator op = Operator.of(\"azblob\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// The root of Azblob service backend.\n//\n// All operations will happen under this root.\n// conf.put(\"root\", \"...\");\n\n// The container name of Azblob service backend.\nconf.put(\"container\", \"...\");\n\n// The endpoint of Azblob service backend.\n//\n// Endpoint must be full uri, e.g.\n//\n// - Azblob: `https://accountname.blo [...]
+ }
+ ]
+ },
+ {
+ "name": "azdls",
+ "scheme": "azdls",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root of this backend."
+ },
+ {
+ "name": "filesystem",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "Filesystem name of this backend."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Endpoint of this backend."
+ },
+ {
+ "name": "account_name",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Account name of this backend."
+ },
+ {
+ "name": "account_key",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Account key of this backend.\n- required for shared_key authentication"
+ },
+ {
+ "name": "client_secret",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "client_secret\nThe client secret of the service principal.\n- required for client_credentials authentication"
+ },
+ {
+ "name": "tenant_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "tenant_id\nThe tenant id of the service principal.\n- required for client_credentials authentication"
+ },
+ {
+ "name": "client_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "client_id\nThe client id of the service principal.\n- required for client_credentials authentication"
+ },
+ {
+ "name": "sas_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "sas_token\nThe shared access signature token.\n- required for sas authentication"
+ },
+ {
+ "name": "authority_host",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "authority_host\nThe authority host of the service principal.\n- required for client_credentials authentication\n- default value: `https://login.microsoftonline.com`"
+ },
+ {
+ "name": "enable_hns",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "comments": "Whether hierarchical namespace (HNS) is enabled for the storage account.\nWhen enabled, recursive deletion can use pagination to avoid timeouts on large directories.\n- default value: `false`"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"azdls\", [\n (\"filesystem\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"azdls\", [\n // Root of this backend.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // Filesystem name of this backend.\n (\"filesystem\".to_string(), \"...\".to_string()),\n\n // Endpoint of this backend.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // Account name of this backend.\n // (\"account_name\".to_string(), \"...\".to_string()),\n\n // Account key of this [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"azdls\",\n filesystem=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"azdls\",\n # Root of this backend.\n # root=\"...\",\n\n # Filesystem name of this backend.\n filesystem=\"...\",\n\n # Endpoint of this backend.\n # endpoint=\"...\",\n\n # Account name of this backend.\n # account_name=\"...\",\n\n # Account key of this backend.\n # - required for shared_key authentication\n # account_key=\"...\",\n\n # client_secret\n # The client secret of the se [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"azdls\", {\n filesystem: \"...\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"azdls\", {\n // Root of this backend.\n // root: \"...\",\n\n // Filesystem name of this backend.\n filesystem: \"...\",\n\n // Endpoint of this backend.\n // endpoint: \"...\",\n\n // Account name of this backend.\n // account_name: \"...\",\n\n // Account key of this backend.\n // - required for shared_key authentication\n // account_key: \"...\",\n\n // client_secret\n // The client secr [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"filesystem\", \"...\");\nOperator op = Operator.of(\"azdls\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// Root of this backend.\n// conf.put(\"root\", \"...\");\n\n// Filesystem name of this backend.\nconf.put(\"filesystem\", \"...\");\n\n// Endpoint of this backend.\n// conf.put(\"endpoint\", \"...\");\n\n// Account name of this backend.\n// conf.put(\"account_name\", \"...\");\n\n// Account key of this backend.\n// - required for shared [...]
+ }
+ ]
+ },
+ {
+ "name": "azfile",
+ "scheme": "azfile",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The root path for azfile."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The endpoint for azfile."
+ },
+ {
+ "name": "share_name",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "The share name for azfile."
+ },
+ {
+ "name": "account_name",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The account name for azfile."
+ },
+ {
+ "name": "account_key",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The account key for azfile."
+ },
+ {
+ "name": "sas_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The sas token for azfile."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"azfile\", [\n (\"share_name\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"azfile\", [\n // The root path for azfile.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // The endpoint for azfile.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // The share name for azfile.\n (\"share_name\".to_string(), \"...\".to_string()),\n\n // The account name for azfile.\n // (\"account_name\".to_string(), \"...\".to_string()),\n\n // The account key for azf [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"azfile\",\n share_name=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"azfile\",\n # The root path for azfile.\n # root=\"...\",\n\n # The endpoint for azfile.\n # endpoint=\"...\",\n\n # The share name for azfile.\n share_name=\"...\",\n\n # The account name for azfile.\n # account_name=\"...\",\n\n # The account key for azfile.\n # account_key=\"...\",\n\n # The sas token for azfile.\n # sas_token=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"azfile\", {\n share_name: \"...\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"azfile\", {\n // The root path for azfile.\n // root: \"...\",\n\n // The endpoint for azfile.\n // endpoint: \"...\",\n\n // The share name for azfile.\n share_name: \"...\",\n\n // The account name for azfile.\n // account_name: \"...\",\n\n // The account key for azfile.\n // account_key: \"...\",\n\n // The sas token for azfile.\n // sas_token: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"share_name\", \"...\");\nOperator op = Operator.of(\"azfile\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// The root path for azfile.\n// conf.put(\"root\", \"...\");\n\n// The endpoint for azfile.\n// conf.put(\"endpoint\", \"...\");\n\n// The share name for azfile.\nconf.put(\"share_name\", \"...\");\n\n// The account name for azfile.\n// conf.put(\"account_name\", \"...\");\n\n// The account key for azfile.\n// conf.put(\"account_key\", [...]
+ }
+ ]
+ },
+ {
+ "name": "b2",
+ "scheme": "b2",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend.\n\nAll operations will happen under this root."
+ },
+ {
+ "name": "application_key_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "keyID of this backend.\n\n- If application_key_id is set, we will take user's input first.\n- If not, we will try to load it from environment."
+ },
+ {
+ "name": "application_key",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "applicationKey of this backend.\n\n- If application_key is set, we will take user's input first.\n- If not, we will try to load it from environment."
+ },
+ {
+ "name": "bucket",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "bucket of this backend.\n\nrequired."
+ },
+ {
+ "name": "bucket_id",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "bucket id of this backend.\n\nrequired."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"b2\", [\n (\"bucket\".to_string(), \"...\".to_string()),\n (\"bucket_id\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"b2\", [\n // root of this backend.\n //\n // All operations will happen under this root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // keyID of this backend.\n //\n // - If application_key_id is set, we will take user's input first.\n // - If not, we will try to load it from environment.\n // (\"application_key_id\".to_string(), \"...\".to_string()),\n\n // applicationKey o [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"b2\",\n bucket=\"...\",\n bucket_id=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"b2\",\n # root of this backend.\n #\n # All operations will happen under this root.\n # root=\"...\",\n\n # keyID of this backend.\n #\n # - If application_key_id is set, we will take user's input first.\n # - If not, we will try to load it from environment.\n # application_key_id=\"...\",\n\n # applicationKey of this backend.\n #\n # - If application_key is set, we will take user's inp [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"b2\", {\n bucket: \"...\",\n bucket_id: \"...\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"b2\", {\n // root of this backend.\n //\n // All operations will happen under this root.\n // root: \"...\",\n\n // keyID of this backend.\n //\n // - If application_key_id is set, we will take user's input first.\n // - If not, we will try to load it from environment.\n // application_key_id: \"...\",\n\n // applicationKey of this backend.\n //\n // - If application_key is set, we will take [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"bucket\", \"...\");\nconf.put(\"bucket_id\", \"...\");\nOperator op = Operator.of(\"b2\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// root of this backend.\n//\n// All operations will happen under this root.\n// conf.put(\"root\", \"...\");\n\n// keyID of this backend.\n//\n// - If application_key_id is set, we will take user's input first.\n// - If not, we will try to load it from environment.\n// conf.put(\"application_key_id\", \"...\");\n\n// applicationKey of t [...]
+ }
+ ]
+ },
+ {
+ "name": "cacache",
+ "scheme": "cacache",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "datadir",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "That path to the cacache data directory."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"cacache\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"cacache\", [\n // That path to the cacache data directory.\n // (\"datadir\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"cacache\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"cacache\",\n # That path to the cacache data directory.\n # datadir=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"cacache\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"cacache\", {\n // That path to the cacache data directory.\n // datadir: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"cacache\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// That path to the cacache data directory.\n// conf.put(\"datadir\", \"...\");\n\nOperator op = Operator.of(\"cacache\", conf);"
+ }
+ ]
+ },
+ {
+ "name": "cloudflare-kv",
+ "scheme": "cloudflare-kv",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "api_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The token used to authenticate with CloudFlare."
+ },
+ {
+ "name": "account_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The account ID used to authenticate with CloudFlare. Used as URI path parameter."
+ },
+ {
+ "name": "namespace_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The namespace ID. Used as URI path parameter."
+ },
+ {
+ "name": "default_ttl",
+ "type": "duration",
+ "required": false,
+ "group": "General",
+ "comments": "The default ttl for write operations."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root within this backend."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"cloudflare-kv\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"cloudflare-kv\", [\n // The token used to authenticate with CloudFlare.\n // (\"api_token\".to_string(), \"...\".to_string()),\n\n // The account ID used to authenticate with CloudFlare. Used as URI path parameter.\n // (\"account_id\".to_string(), \"...\".to_string()),\n\n // The namespace ID. Used as URI path parameter.\n // (\"namespace_id\".to_string(), \"...\".to_string()),\n\n // The def [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"cloudflare-kv\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"cloudflare-kv\",\n # The token used to authenticate with CloudFlare.\n # api_token=\"...\",\n\n # The account ID used to authenticate with CloudFlare. Used as URI path parameter.\n # account_id=\"...\",\n\n # The namespace ID. Used as URI path parameter.\n # namespace_id=\"...\",\n\n # The default ttl for write operations.\n # default_ttl=\"10s\",\n\n # Root within this backend.\n # root=\".. [...]
+ }
+ ]
+ },
+ {
+ "name": "compfs",
+ "scheme": "compfs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend.\n\nAll operations will happen under this root."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"compfs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"compfs\", [\n // root of this backend.\n //\n // All operations will happen under this root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"compfs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"compfs\",\n # root of this backend.\n #\n # All operations will happen under this root.\n # root=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"compfs\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"compfs\", {\n // root of this backend.\n //\n // All operations will happen under this root.\n // root: \"...\",\n\n});"
+ }
+ ]
+ },
+ {
+ "name": "cos",
+ "scheme": "cos",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root of this backend."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Endpoint of this backend."
+ },
+ {
+ "name": "secret_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Secret ID of this backend."
+ },
+ {
+ "name": "secret_key",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Secret key of this backend."
+ },
+ {
+ "name": "security_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Security token (a.k.a. session token) of this backend.\n\nThis is used for temporary credentials issued by Tencent Cloud STS\n(e.g. `GetFederationToken` / `AssumeRole`). When `security_token` is\nprovided, it will be used together with `secret_id` and `secret_key`\nto sign requests, and the `x-cos-security-token` header will be\nattached automatically by the signer.\n\nIf this field is not set, OpenDAL will also fall back to reading\nthe token from environment vari [...]
+ },
+ {
+ "name": "bucket",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Bucket of this backend."
+ },
+ {
+ "name": "enable_versioning",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "COS versioning capability is enabled by default and this option is no longer needed."
+ },
+ "comments": "Deprecated: COS versioning capability is enabled by default."
+ },
+ {
+ "name": "disable_config_load",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "comments": "Disable config load so that opendal will not load config from"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"cos\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"cos\", [\n // Root of this backend.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // Endpoint of this backend.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // Secret ID of this backend.\n // (\"secret_id\".to_string(), \"...\".to_string()),\n\n // Secret key of this backend.\n // (\"secret_key\".to_string(), \"...\".to_string()),\n\n // Security token (a.k.a. session [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"cos\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"cos\",\n # Root of this backend.\n # root=\"...\",\n\n # Endpoint of this backend.\n # endpoint=\"...\",\n\n # Secret ID of this backend.\n # secret_id=\"...\",\n\n # Secret key of this backend.\n # secret_key=\"...\",\n\n # Security token (a.k.a. session token) of this backend.\n #\n # This is used for temporary credentials issued by Tencent Cloud STS\n # (e.g. `GetFederationToken` / ` [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"cos\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"cos\", {\n // Root of this backend.\n // root: \"...\",\n\n // Endpoint of this backend.\n // endpoint: \"...\",\n\n // Secret ID of this backend.\n // secret_id: \"...\",\n\n // Secret key of this backend.\n // secret_key: \"...\",\n\n // Security token (a.k.a. session token) of this backend.\n //\n // This is used for temporary credentials issued by Tencent Cloud STS\n // (e.g. `GetFederat [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"cos\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// Root of this backend.\n// conf.put(\"root\", \"...\");\n\n// Endpoint of this backend.\n// conf.put(\"endpoint\", \"...\");\n\n// Secret ID of this backend.\n// conf.put(\"secret_id\", \"...\");\n\n// Secret key of this backend.\n// conf.put(\"secret_key\", \"...\");\n\n// Security token (a.k.a. session token) of this backend.\n//\n// [...]
+ }
+ ]
+ },
+ {
+ "name": "d1",
+ "scheme": "d1",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Set the token of cloudflare api."
+ },
+ {
+ "name": "account_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Set the account id of cloudflare api."
+ },
+ {
+ "name": "database_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Set the database id of cloudflare api."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Set the working directory of OpenDAL."
+ },
+ {
+ "name": "table",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Set the table of D1 Database."
+ },
+ {
+ "name": "key_field",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Set the key field of D1 Database."
+ },
+ {
+ "name": "value_field",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Set the value field of D1 Database."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"d1\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"d1\", [\n // Set the token of cloudflare api.\n // (\"token\".to_string(), \"...\".to_string()),\n\n // Set the account id of cloudflare api.\n // (\"account_id\".to_string(), \"...\".to_string()),\n\n // Set the database id of cloudflare api.\n // (\"database_id\".to_string(), \"...\".to_string()),\n\n // Set the working directory of OpenDAL.\n // (\"root\".to_string(), \"...\".to_string() [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"d1\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"d1\",\n # Set the token of cloudflare api.\n # token=\"...\",\n\n # Set the account id of cloudflare api.\n # account_id=\"...\",\n\n # Set the database id of cloudflare api.\n # database_id=\"...\",\n\n # Set the working directory of OpenDAL.\n # root=\"...\",\n\n # Set the table of D1 Database.\n # table=\"...\",\n\n # Set the key field of D1 Database.\n # key_field=\"...\",\n\n # [...]
+ }
+ ]
+ },
+ {
+ "name": "dashmap",
+ "scheme": "dashmap",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root path of this backend"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"dashmap\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"dashmap\", [\n // root path of this backend\n // (\"root\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"dashmap\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"dashmap\",\n # root path of this backend\n # root=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"dashmap\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"dashmap\", {\n // root path of this backend\n // root: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"dashmap\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// root path of this backend\n// conf.put(\"root\", \"...\");\n\nOperator op = Operator.of(\"dashmap\", conf);"
+ }
+ ]
+ },
+ {
+ "name": "dbfs",
+ "scheme": "dbfs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The root for dbfs."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The endpoint for dbfs."
+ },
+ {
+ "name": "token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The token for dbfs."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"dbfs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"dbfs\", [\n // The root for dbfs.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // The endpoint for dbfs.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // The token for dbfs.\n // (\"token\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"dbfs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"dbfs\",\n # The root for dbfs.\n # root=\"...\",\n\n # The endpoint for dbfs.\n # endpoint=\"...\",\n\n # The token for dbfs.\n # token=\"...\",\n\n)"
+ }
+ ]
+ },
+ {
+ "name": "dropbox",
+ "scheme": "dropbox",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root path for dropbox."
+ },
+ {
+ "name": "access_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "access token for dropbox."
+ },
+ {
+ "name": "refresh_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "refresh_token for dropbox."
+ },
+ {
+ "name": "client_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "client_id for dropbox."
+ },
+ {
+ "name": "client_secret",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "client_secret for dropbox."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"dropbox\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"dropbox\", [\n // root path for dropbox.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // access token for dropbox.\n // (\"access_token\".to_string(), \"...\".to_string()),\n\n // refresh_token for dropbox.\n // (\"refresh_token\".to_string(), \"...\".to_string()),\n\n // client_id for dropbox.\n // (\"client_id\".to_string(), \"...\".to_string()),\n\n // client_secret for dropb [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"dropbox\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"dropbox\",\n # root path for dropbox.\n # root=\"...\",\n\n # access token for dropbox.\n # access_token=\"...\",\n\n # refresh_token for dropbox.\n # refresh_token=\"...\",\n\n # client_id for dropbox.\n # client_id=\"...\",\n\n # client_secret for dropbox.\n # client_secret=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"dropbox\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"dropbox\", {\n // root path for dropbox.\n // root: \"...\",\n\n // access token for dropbox.\n // access_token: \"...\",\n\n // refresh_token for dropbox.\n // refresh_token: \"...\",\n\n // client_id for dropbox.\n // client_id: \"...\",\n\n // client_secret for dropbox.\n // client_secret: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"dropbox\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// root path for dropbox.\n// conf.put(\"root\", \"...\");\n\n// access token for dropbox.\n// conf.put(\"access_token\", \"...\");\n\n// refresh_token for dropbox.\n// conf.put(\"refresh_token\", \"...\");\n\n// client_id for dropbox.\n// conf.put(\"client_id\", \"...\");\n\n// client_secret for dropbox.\n// conf.put(\"client_secret\", [...]
+ }
+ ]
+ },
+ {
+ "name": "etcd",
+ "scheme": "etcd",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "endpoints",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "network address of the Etcd services.\nIf use https, must set TLS options: `ca_path`, `cert_path`, `key_path`.\ne.g. \"127.0.0.1:23790,127.0.0.1:23791,127.0.0.1:23792\" or \"http://127.0.0.1:23790,http://127.0.0.1:23791,http://127.0.0.1:23792\" or \"https://127.0.0.1:23790,https://127.0.0.1:23791,https://127.0.0.1:23792\"\n\ndefault is \"http://127.0.0.1:2379\""
+ },
+ {
+ "name": "username",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "the username to connect etcd service.\n\ndefault is None"
+ },
+ {
+ "name": "password",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "the password for authentication\n\ndefault is None"
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "the working directory of the etcd service. Can be \"/path/to/dir\"\n\ndefault is \"/\""
+ },
+ {
+ "name": "ca_path",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "certificate authority file path\n\ndefault is None"
+ },
+ {
+ "name": "cert_path",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "cert path\n\ndefault is None"
+ },
+ {
+ "name": "key_path",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "key path\n\ndefault is None"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"etcd\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"etcd\", [\n // network address of the Etcd services.\n // If use https, must set TLS options: `ca_path`, `cert_path`, `key_path`.\n // e.g. \"127.0.0.1:23790,127.0.0.1:23791,127.0.0.1:23792\" or \"http://127.0.0.1:23790,http://127.0.0.1:23791,http://127.0.0.1:23792\" or \"https://127.0.0.1:23790,https://127.0.0.1:23791,https://127.0.0.1:23792\"\n //\n // default is \"http://127.0.0.1:2379\"\n // [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"etcd\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"etcd\",\n # network address of the Etcd services.\n # If use https, must set TLS options: `ca_path`, `cert_path`, `key_path`.\n # e.g. \"127.0.0.1:23790,127.0.0.1:23791,127.0.0.1:23792\" or \"http://127.0.0.1:23790,http://127.0.0.1:23791,http://127.0.0.1:23792\" or \"https://127.0.0.1:23790,https://127.0.0.1:23791,https://127.0.0.1:23792\"\n #\n # default is \"http://127.0.0.1:2379\"\n # endpoints=\"...\ [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"etcd\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"etcd\", {\n // network address of the Etcd services.\n // If use https, must set TLS options: `ca_path`, `cert_path`, `key_path`.\n // e.g. \"127.0.0.1:23790,127.0.0.1:23791,127.0.0.1:23792\" or \"http://127.0.0.1:23790,http://127.0.0.1:23791,http://127.0.0.1:23792\" or \"https://127.0.0.1:23790,https://127.0.0.1:23791,https://127.0.0.1:23792\"\n //\n // default is \"http://127.0.0.1:2379\"\n // e [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"etcd\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// network address of the Etcd services.\n// If use https, must set TLS options: `ca_path`, `cert_path`, `key_path`.\n// e.g. \"127.0.0.1:23790,127.0.0.1:23791,127.0.0.1:23792\" or \"http://127.0.0.1:23790,http://127.0.0.1:23791,http://127.0.0.1:23792\" or \"https://127.0.0.1:23790,https://127.0.0.1:23791,https://127.0.0.1:23792\"\n//\n/ [...]
+ }
+ ]
+ },
+ {
+ "name": "foundationdb",
+ "scheme": "foundationdb",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of the backend."
+ },
+ {
+ "name": "config_path",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "config_path for the backend."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"foundationdb\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"foundationdb\", [\n // root of the backend.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // config_path for the backend.\n // (\"config_path\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"foundationdb\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"foundationdb\",\n # root of the backend.\n # root=\"...\",\n\n # config_path for the backend.\n # config_path=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"foundationdb\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"foundationdb\", {\n // root of the backend.\n // root: \"...\",\n\n // config_path for the backend.\n // config_path: \"...\",\n\n});"
+ }
+ ]
+ },
+ {
+ "name": "foyer",
+ "scheme": "foyer",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "name",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Name for this cache instance."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root path of this backend."
+ },
+ {
+ "name": "memory",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "comments": "Memory capacity in bytes for the cache."
+ },
+ {
+ "name": "disk_path",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Disk cache directory path.\n\nIf set, enables hybrid cache with disk storage. Data will be persisted to\nthis directory when memory cache is full."
+ },
+ {
+ "name": "disk_capacity",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "comments": "Disk cache total capacity in bytes.\nOnly used when `disk_path` is set."
+ },
+ {
+ "name": "disk_file_size",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "comments": "Individual cache file size in bytes.\n\nDefault is 1 MiB.\nOnly used when `disk_path` is set."
+ },
+ {
+ "name": "recover_mode",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Recovery mode when starting the cache.\n\nValid values: \"none\" (default), \"quiet\", \"strict\".\n- \"none\": Don't recover from disk\n- \"quiet\": Recover and skip errors\n- \"strict\": Recover and panic on errors"
+ },
+ {
+ "name": "shards",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "comments": "Number of shards for concurrent access.\n\nDefault is 1. Higher values improve concurrency but increase overhead."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"foyer\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"foyer\", [\n // Name for this cache instance.\n // (\"name\".to_string(), \"...\".to_string()),\n\n // Root path of this backend.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // Memory capacity in bytes for the cache.\n // (\"memory\".to_string(), \"1000\".to_string()),\n\n // Disk cache directory path.\n //\n // If set, enables hybrid cache with disk storage. Data will be persi [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"foyer\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"foyer\",\n # Name for this cache instance.\n # name=\"...\",\n\n # Root path of this backend.\n # root=\"...\",\n\n # Memory capacity in bytes for the cache.\n # memory=\"1000\",\n\n # Disk cache directory path.\n #\n # If set, enables hybrid cache with disk storage. Data will be persisted to\n # this directory when memory cache is full.\n # disk_path=\"...\",\n\n # Disk cache total cap [...]
+ }
+ ]
+ },
+ {
+ "name": "fs",
+ "scheme": "fs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root dir for backend"
+ },
+ {
+ "name": "atomic_write_dir",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "tmp dir for atomic write"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"fs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"fs\", [\n // root dir for backend\n // (\"root\".to_string(), \"...\".to_string()),\n\n // tmp dir for atomic write\n // (\"atomic_write_dir\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"fs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"fs\",\n # root dir for backend\n # root=\"...\",\n\n # tmp dir for atomic write\n # atomic_write_dir=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"fs\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"fs\", {\n // root dir for backend\n // root: \"...\",\n\n // tmp dir for atomic write\n // atomic_write_dir: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"fs\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// root dir for backend\n// conf.put(\"root\", \"...\");\n\n// tmp dir for atomic write\n// conf.put(\"atomic_write_dir\", \"...\");\n\nOperator op = Operator.of(\"fs\", conf);"
+ }
+ ]
+ },
+ {
+ "name": "ftp",
+ "scheme": "ftp",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "endpoint of this backend"
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend"
+ },
+ {
+ "name": "user",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "user of this backend"
+ },
+ {
+ "name": "password",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "password of this backend"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"ftp\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"ftp\", [\n // endpoint of this backend\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // root of this backend\n // (\"root\".to_string(), \"...\".to_string()),\n\n // user of this backend\n // (\"user\".to_string(), \"...\".to_string()),\n\n // password of this backend\n // (\"password\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"ftp\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"ftp\",\n # endpoint of this backend\n # endpoint=\"...\",\n\n # root of this backend\n # root=\"...\",\n\n # user of this backend\n # user=\"...\",\n\n # password of this backend\n # password=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"ftp\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"ftp\", {\n // endpoint of this backend\n // endpoint: \"...\",\n\n // root of this backend\n // root: \"...\",\n\n // user of this backend\n // user: \"...\",\n\n // password of this backend\n // password: \"...\",\n\n});"
+ }
+ ]
+ },
+ {
+ "name": "gcs",
+ "scheme": "gcs",
+ "groups": [
+ "General",
+ "Credentials",
+ "Behavior",
+ "Deprecated"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "default": "/",
+ "comments": "root URI, all operations happens under `root`"
+ },
+ {
+ "name": "bucket",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "example": "my-bucket",
+ "comments": "bucket name"
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "default": "https://storage.googleapis.com",
+ "comments": "endpoint URI of GCS service,\ndefault is `https://storage.googleapis.com`"
+ },
+ {
+ "name": "scope",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Scope for gcs."
+ },
+ {
+ "name": "service_account",
+ "type": "string",
+ "required": false,
+ "group": "Credentials",
+ "comments": "Service Account for gcs."
+ },
+ {
+ "name": "credential",
+ "type": "string",
+ "required": false,
+ "group": "Credentials",
+ "comments": "Credentials string for GCS service OAuth2 authentication."
+ },
+ {
+ "name": "credential_path",
+ "type": "string",
+ "required": false,
+ "group": "Credentials",
+ "comments": "Local path to credentials file for GCS service OAuth2 authentication."
+ },
+ {
+ "name": "predefined_acl",
+ "type": "string",
+ "required": false,
+ "group": "Behavior",
+ "comments": "The predefined acl for GCS."
+ },
+ {
+ "name": "default_storage_class",
+ "type": "string",
+ "required": false,
+ "group": "Behavior",
+ "comments": "The default storage class used by gcs."
+ },
+ {
+ "name": "skip_signature",
+ "type": "bool",
+ "required": false,
+ "group": "Credentials",
+ "comments": "Skip signature will skip loading credentials and signing requests."
+ },
+ {
+ "name": "allow_anonymous",
+ "type": "bool",
+ "required": false,
+ "group": "Deprecated",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "Please use `skip_signature` instead of `allow_anonymous`"
+ },
+ "comments": "Allow opendal to send requests without signing when credentials are not\nloaded."
+ },
+ {
+ "name": "disable_vm_metadata",
+ "type": "bool",
+ "required": false,
+ "group": "Credentials",
+ "comments": "Disable attempting to load credentials from the GCE metadata server when\nrunning within Google Cloud."
+ },
+ {
+ "name": "disable_config_load",
+ "type": "bool",
+ "required": false,
+ "group": "Credentials",
+ "comments": "Disable loading configuration from the environment."
+ },
+ {
+ "name": "token",
+ "type": "string",
+ "required": false,
+ "group": "Credentials",
+ "comments": "A Google Cloud OAuth2 token.\n\nTakes precedence over `credential` and `credential_path`."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"gcs\", [\n (\"bucket\".to_string(), \"my-bucket\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"gcs\", [\n // --- General ---\n // root URI, all operations happens under `root`\n // (\"root\".to_string(), \"/\".to_string()),\n\n // bucket name\n (\"bucket\".to_string(), \"my-bucket\".to_string()),\n\n // endpoint URI of GCS service,\n // default is `https://storage.googleapis.com`\n // (\"endpoint\".to_string(), \"https://storage.googleapis.com\".to_string()),\n\n // Scope for gcs. [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"gcs\",\n bucket=\"my-bucket\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"gcs\",\n # --- General ---\n # root URI, all operations happens under `root`\n # root=\"/\",\n\n # bucket name\n bucket=\"my-bucket\",\n\n # endpoint URI of GCS service,\n # default is `https://storage.googleapis.com`\n # endpoint=\"https://storage.googleapis.com\",\n\n # Scope for gcs.\n # scope=\"...\",\n\n # --- Credentials ---\n # Service Account for gcs.\n # service_account=\".. [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"gcs\", {\n bucket: \"my-bucket\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"gcs\", {\n // --- General ---\n // root URI, all operations happens under `root`\n // root: \"/\",\n\n // bucket name\n bucket: \"my-bucket\",\n\n // endpoint URI of GCS service,\n // default is `https://storage.googleapis.com`\n // endpoint: \"https://storage.googleapis.com\",\n\n // Scope for gcs.\n // scope: \"...\",\n\n // --- Credentials ---\n // Service Account for gcs.\n // service_a [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"bucket\", \"my-bucket\");\nOperator op = Operator.of(\"gcs\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// --- General ---\n// root URI, all operations happens under `root`\n// conf.put(\"root\", \"/\");\n\n// bucket name\nconf.put(\"bucket\", \"my-bucket\");\n\n// endpoint URI of GCS service,\n// default is `https://storage.googleapis.com`\n// conf.put(\"endpoint\", \"https://storage.googleapis.com\");\n\n// Scope for gcs.\n// conf.put(\" [...]
+ }
+ ]
+ },
+ {
+ "name": "gdrive",
+ "scheme": "gdrive",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The root for gdrive"
+ },
+ {
+ "name": "access_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Access token for gdrive."
+ },
+ {
+ "name": "refresh_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Refresh token for gdrive."
+ },
+ {
+ "name": "client_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Client id for gdrive."
+ },
+ {
+ "name": "client_secret",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Client secret for gdrive."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"gdrive\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"gdrive\", [\n // The root for gdrive\n // (\"root\".to_string(), \"...\".to_string()),\n\n // Access token for gdrive.\n // (\"access_token\".to_string(), \"...\".to_string()),\n\n // Refresh token for gdrive.\n // (\"refresh_token\".to_string(), \"...\".to_string()),\n\n // Client id for gdrive.\n // (\"client_id\".to_string(), \"...\".to_string()),\n\n // Client secret for gdrive.\n [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"gdrive\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"gdrive\",\n # The root for gdrive\n # root=\"...\",\n\n # Access token for gdrive.\n # access_token=\"...\",\n\n # Refresh token for gdrive.\n # refresh_token=\"...\",\n\n # Client id for gdrive.\n # client_id=\"...\",\n\n # Client secret for gdrive.\n # client_secret=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"gdrive\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"gdrive\", {\n // The root for gdrive\n // root: \"...\",\n\n // Access token for gdrive.\n // access_token: \"...\",\n\n // Refresh token for gdrive.\n // refresh_token: \"...\",\n\n // Client id for gdrive.\n // client_id: \"...\",\n\n // Client secret for gdrive.\n // client_secret: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"gdrive\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// The root for gdrive\n// conf.put(\"root\", \"...\");\n\n// Access token for gdrive.\n// conf.put(\"access_token\", \"...\");\n\n// Refresh token for gdrive.\n// conf.put(\"refresh_token\", \"...\");\n\n// Client id for gdrive.\n// conf.put(\"client_id\", \"...\");\n\n// Client secret for gdrive.\n// conf.put(\"client_secret\", \"...\" [...]
+ }
+ ]
+ },
+ {
+ "name": "ghac",
+ "scheme": "ghac",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The root path for ghac."
+ },
+ {
+ "name": "version",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The version that used by cache."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The endpoint for ghac service."
+ },
+ {
+ "name": "runtime_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The runtime token for ghac service."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"ghac\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"ghac\", [\n // The root path for ghac.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // The version that used by cache.\n // (\"version\".to_string(), \"...\".to_string()),\n\n // The endpoint for ghac service.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // The runtime token for ghac service.\n // (\"runtime_token\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"ghac\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"ghac\",\n # The root path for ghac.\n # root=\"...\",\n\n # The version that used by cache.\n # version=\"...\",\n\n # The endpoint for ghac service.\n # endpoint=\"...\",\n\n # The runtime token for ghac service.\n # runtime_token=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"ghac\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"ghac\", {\n // The root path for ghac.\n // root: \"...\",\n\n // The version that used by cache.\n // version: \"...\",\n\n // The endpoint for ghac service.\n // endpoint: \"...\",\n\n // The runtime token for ghac service.\n // runtime_token: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"ghac\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// The root path for ghac.\n// conf.put(\"root\", \"...\");\n\n// The version that used by cache.\n// conf.put(\"version\", \"...\");\n\n// The endpoint for ghac service.\n// conf.put(\"endpoint\", \"...\");\n\n// The runtime token for ghac service.\n// conf.put(\"runtime_token\", \"...\");\n\nOperator op = Operator.of(\"ghac\", conf);"
+ }
+ ]
+ },
+ {
+ "name": "github",
+ "scheme": "github",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend.\n\nAll operations will happen under this root."
+ },
+ {
+ "name": "token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "GitHub access_token.\n\noptional.\nIf not provided, the backend will only support read operations for public repositories.\nAnd rate limit will be limited to 60 requests per hour."
+ },
+ {
+ "name": "owner",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "GitHub repo owner.\n\nrequired."
+ },
+ {
+ "name": "repo",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "GitHub repo name.\n\nrequired."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"github\", [\n (\"owner\".to_string(), \"...\".to_string()),\n (\"repo\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"github\", [\n // root of this backend.\n //\n // All operations will happen under this root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // GitHub access_token.\n //\n // optional.\n // If not provided, the backend will only support read operations for public repositories.\n // And rate limit will be limited to 60 requests per hour.\n // (\"token\".to_string(), \"...\".to_st [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"github\",\n owner=\"...\",\n repo=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"github\",\n # root of this backend.\n #\n # All operations will happen under this root.\n # root=\"...\",\n\n # GitHub access_token.\n #\n # optional.\n # If not provided, the backend will only support read operations for public repositories.\n # And rate limit will be limited to 60 requests per hour.\n # token=\"...\",\n\n # GitHub repo owner.\n #\n # required.\n owner=\"...\",\n [...]
+ }
+ ]
+ },
+ {
+ "name": "goosefs",
+ "scheme": "goosefs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root path of this backend.\n\nAll operations will happen under this root.\nDefault to `/` if not set."
+ },
+ {
+ "name": "master_addr",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Master address(es) in `host:port` format.\n\nFor single master: `\"10.0.0.1:9200\"`\nFor HA (comma-separated): `\"10.0.0.1:9200,10.0.0.2:9200,10.0.0.3:9200\"`\n\nWhen multiple addresses are provided, the client uses\n`PollingMasterInquireClient` to discover the Primary Master automatically.\n\nResolution precedence at `build()` time (highest → lowest), following\n`goosefs-sdk` `docs/CLIENT_CONFIGURATION.md` §1:\n1. This field (when set on the builder / OpenDAL conf [...]
+ },
+ {
+ "name": "block_size",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "comments": "Block size in bytes for new files (default: 64 MiB)."
+ },
+ {
+ "name": "chunk_size",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "comments": "Chunk size in bytes for streaming RPCs (default: 1 MiB)."
+ },
+ {
+ "name": "write_type",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Default write type for new files.\n\nSupported values: `\"must_cache\"`, `\"cache_through\"`, `\"through\"`, `\"async_through\"`.\nDefault: `\"must_cache\"`."
+ },
+ {
+ "name": "auth_type",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Authentication type.\n\nSupported values: `\"nosasl\"`, `\"simple\"`.\nDefault: `\"simple\"` — PLAIN SASL with username.\n`\"nosasl\"` — skip authentication entirely."
+ },
+ {
+ "name": "auth_username",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Authentication username.\n\nUsed in SIMPLE mode as the login identity.\nDefault: current OS user (`$USER` / `$USERNAME`)."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"goosefs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"goosefs\", [\n // Root path of this backend.\n //\n // All operations will happen under this root.\n // Default to `/` if not set.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // Master address(es) in `host:port` format.\n //\n // For single master: `\"10.0.0.1:9200\"`\n // For HA (comma-separated): `\"10.0.0.1:9200,10.0.0.2:9200,10.0.0.3:9200\"`\n //\n // When multiple ad [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"goosefs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"goosefs\",\n # Root path of this backend.\n #\n # All operations will happen under this root.\n # Default to `/` if not set.\n # root=\"...\",\n\n # Master address(es) in `host:port` format.\n #\n # For single master: `\"10.0.0.1:9200\"`\n # For HA (comma-separated): `\"10.0.0.1:9200,10.0.0.2:9200,10.0.0.3:9200\"`\n #\n # When multiple addresses are provided, the client uses\n # `Pollin [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"goosefs\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"goosefs\", {\n // Root path of this backend.\n //\n // All operations will happen under this root.\n // Default to `/` if not set.\n // root: \"...\",\n\n // Master address(es) in `host:port` format.\n //\n // For single master: `\"10.0.0.1:9200\"`\n // For HA (comma-separated): `\"10.0.0.1:9200,10.0.0.2:9200,10.0.0.3:9200\"`\n //\n // When multiple addresses are provided, the client uses\n [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"goosefs\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// Root path of this backend.\n//\n// All operations will happen under this root.\n// Default to `/` if not set.\n// conf.put(\"root\", \"...\");\n\n// Master address(es) in `host:port` format.\n//\n// For single master: `\"10.0.0.1:9200\"`\n// For HA (comma-separated): `\"10.0.0.1:9200,10.0.0.2:9200,10.0.0.3:9200\"`\n//\n// When multipl [...]
+ }
+ ]
+ },
+ {
+ "name": "gridfs",
+ "scheme": "gridfs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "connection_string",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The connection string of the MongoDB service."
+ },
+ {
+ "name": "database",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The database name of the MongoDB GridFs service to read/write."
+ },
+ {
+ "name": "bucket",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The bucket name of the MongoDB GridFs service to read/write."
+ },
+ {
+ "name": "chunk_size",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "comments": "The chunk size of the MongoDB GridFs service used to break the user file into chunks."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The working directory, all operations will be performed under it."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"gridfs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"gridfs\", [\n // The connection string of the MongoDB service.\n // (\"connection_string\".to_string(), \"...\".to_string()),\n\n // The database name of the MongoDB GridFs service to read/write.\n // (\"database\".to_string(), \"...\".to_string()),\n\n // The bucket name of the MongoDB GridFs service to read/write.\n // (\"bucket\".to_string(), \"...\".to_string()),\n\n // The chunk size of t [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"gridfs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"gridfs\",\n # The connection string of the MongoDB service.\n # connection_string=\"...\",\n\n # The database name of the MongoDB GridFs service to read/write.\n # database=\"...\",\n\n # The bucket name of the MongoDB GridFs service to read/write.\n # bucket=\"...\",\n\n # The chunk size of the MongoDB GridFs service used to break the user file into chunks.\n # chunk_size=\"1000\",\n\n # The wo [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"gridfs\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"gridfs\", {\n // The connection string of the MongoDB service.\n // connection_string: \"...\",\n\n // The database name of the MongoDB GridFs service to read/write.\n // database: \"...\",\n\n // The bucket name of the MongoDB GridFs service to read/write.\n // bucket: \"...\",\n\n // The chunk size of the MongoDB GridFs service used to break the user file into chunks.\n // chunk_size: \"1000\" [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"gridfs\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// The connection string of the MongoDB service.\n// conf.put(\"connection_string\", \"...\");\n\n// The database name of the MongoDB GridFs service to read/write.\n// conf.put(\"database\", \"...\");\n\n// The bucket name of the MongoDB GridFs service to read/write.\n// conf.put(\"bucket\", \"...\");\n\n// The chunk size of the MongoDB [...]
+ }
+ ]
+ },
+ {
+ "name": "hdfs",
+ "scheme": "hdfs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "work dir of this backend"
+ },
+ {
+ "name": "name_node",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "name node of this backend"
+ },
+ {
+ "name": "kerberos_ticket_cache_path",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "kerberos_ticket_cache_path of this backend"
+ },
+ {
+ "name": "user",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "user of this backend"
+ },
+ {
+ "name": "enable_append",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "HDFS append capability is enabled by default and this option is no longer needed."
+ },
+ "comments": "Deprecated: HDFS append capability is enabled by default."
+ },
+ {
+ "name": "atomic_write_dir",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "atomic_write_dir of this backend"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"hdfs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"hdfs\", [\n // work dir of this backend\n // (\"root\".to_string(), \"...\".to_string()),\n\n // name node of this backend\n // (\"name_node\".to_string(), \"...\".to_string()),\n\n // kerberos_ticket_cache_path of this backend\n // (\"kerberos_ticket_cache_path\".to_string(), \"...\".to_string()),\n\n // user of this backend\n // (\"user\".to_string(), \"...\".to_string()),\n\n // atomi [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"hdfs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"hdfs\",\n # work dir of this backend\n # root=\"...\",\n\n # name node of this backend\n # name_node=\"...\",\n\n # kerberos_ticket_cache_path of this backend\n # kerberos_ticket_cache_path=\"...\",\n\n # user of this backend\n # user=\"...\",\n\n # atomic_write_dir of this backend\n # atomic_write_dir=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"hdfs\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"hdfs\", {\n // work dir of this backend\n // root: \"...\",\n\n // name node of this backend\n // name_node: \"...\",\n\n // kerberos_ticket_cache_path of this backend\n // kerberos_ticket_cache_path: \"...\",\n\n // user of this backend\n // user: \"...\",\n\n // atomic_write_dir of this backend\n // atomic_write_dir: \"...\",\n\n});"
+ }
+ ]
+ },
+ {
+ "name": "hdfs-native",
+ "scheme": "hdfs-native",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "work dir of this backend"
+ },
+ {
+ "name": "name_node",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "name_node of this backend"
+ },
+ {
+ "name": "enable_append",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "HDFS Native append capability is enabled by default and this option is no longer needed."
+ },
+ "comments": "Deprecated: HDFS Native append capability is enabled by default."
+ },
+ {
+ "name": "options",
+ "type": "map",
+ "required": false,
+ "group": "General",
+ "comments": "other options for hdfs client"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"hdfs-native\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"hdfs-native\", [\n // work dir of this backend\n // (\"root\".to_string(), \"...\".to_string()),\n\n // name_node of this backend\n // (\"name_node\".to_string(), \"...\".to_string()),\n\n // other options for hdfs client\n // (\"options\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"hdfs-native\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"hdfs-native\",\n # work dir of this backend\n # root=\"...\",\n\n # name_node of this backend\n # name_node=\"...\",\n\n # other options for hdfs client\n # options=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"hdfs-native\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"hdfs-native\", {\n // work dir of this backend\n // root: \"...\",\n\n // name_node of this backend\n // name_node: \"...\",\n\n // other options for hdfs client\n // options: \"...\",\n\n});"
+ }
+ ]
+ },
+ {
+ "name": "hf",
+ "scheme": "hf",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "repo_type",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Repo type of this backend. Required."
+ },
+ {
+ "name": "repo_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Repo id of this backend.\n\nThis is required."
+ },
+ {
+ "name": "revision",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Revision of this backend.\n\nDefault is main."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root of this backend. Can be \"/path/to/dir\".\n\nDefault is \"/\"."
+ },
+ {
+ "name": "token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Token of this backend.\n\nThis is optional."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Endpoint of the Hugging Face Hub.\n\nDefault is \"https://huggingface.co\"."
+ },
+ {
+ "name": "download_mode",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Download mode. Either `xet` (default) or `http`."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"hf\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"hf\", [\n // Repo type of this backend. Required.\n // (\"repo_type\".to_string(), \"...\".to_string()),\n\n // Repo id of this backend.\n //\n // This is required.\n // (\"repo_id\".to_string(), \"...\".to_string()),\n\n // Revision of this backend.\n //\n // Default is main.\n // (\"revision\".to_string(), \"...\".to_string()),\n\n // Root of this backend. Can be \"/path/to/dir\" [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"hf\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"hf\",\n # Repo type of this backend. Required.\n # repo_type=\"...\",\n\n # Repo id of this backend.\n #\n # This is required.\n # repo_id=\"...\",\n\n # Revision of this backend.\n #\n # Default is main.\n # revision=\"...\",\n\n # Root of this backend. Can be \"/path/to/dir\".\n #\n # Default is \"/\".\n # root=\"...\",\n\n # Token of this backend.\n #\n # This is optio [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"hf\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"hf\", {\n // Repo type of this backend. Required.\n // repo_type: \"...\",\n\n // Repo id of this backend.\n //\n // This is required.\n // repo_id: \"...\",\n\n // Revision of this backend.\n //\n // Default is main.\n // revision: \"...\",\n\n // Root of this backend. Can be \"/path/to/dir\".\n //\n // Default is \"/\".\n // root: \"...\",\n\n // Token of this backend.\n //\n // This [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"hf\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// Repo type of this backend. Required.\n// conf.put(\"repo_type\", \"...\");\n\n// Repo id of this backend.\n//\n// This is required.\n// conf.put(\"repo_id\", \"...\");\n\n// Revision of this backend.\n//\n// Default is main.\n// conf.put(\"revision\", \"...\");\n\n// Root of this backend. Can be \"/path/to/dir\".\n//\n// Default is \" [...]
+ }
+ ]
+ },
+ {
+ "name": "http",
+ "scheme": "http",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "endpoint of this backend"
+ },
+ {
+ "name": "username",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "username of this backend"
+ },
+ {
+ "name": "password",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "password of this backend"
+ },
+ {
+ "name": "token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "token of this backend"
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"http\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"http\", [\n // endpoint of this backend\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // username of this backend\n // (\"username\".to_string(), \"...\".to_string()),\n\n // password of this backend\n // (\"password\".to_string(), \"...\".to_string()),\n\n // token of this backend\n // (\"token\".to_string(), \"...\".to_string()),\n\n // root of this backend\n // (\"root\ [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"http\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"http\",\n # endpoint of this backend\n # endpoint=\"...\",\n\n # username of this backend\n # username=\"...\",\n\n # password of this backend\n # password=\"...\",\n\n # token of this backend\n # token=\"...\",\n\n # root of this backend\n # root=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"http\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"http\", {\n // endpoint of this backend\n // endpoint: \"...\",\n\n // username of this backend\n // username: \"...\",\n\n // password of this backend\n // password: \"...\",\n\n // token of this backend\n // token: \"...\",\n\n // root of this backend\n // root: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"http\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// endpoint of this backend\n// conf.put(\"endpoint\", \"...\");\n\n// username of this backend\n// conf.put(\"username\", \"...\");\n\n// password of this backend\n// conf.put(\"password\", \"...\");\n\n// token of this backend\n// conf.put(\"token\", \"...\");\n\n// root of this backend\n// conf.put(\"root\", \"...\");\n\nOperator op = [...]
+ }
+ ]
+ },
+ {
+ "name": "ipfs",
+ "scheme": "ipfs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "IPFS gateway endpoint."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "IPFS root."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"ipfs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"ipfs\", [\n // IPFS gateway endpoint.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // IPFS root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"ipfs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"ipfs\",\n # IPFS gateway endpoint.\n # endpoint=\"...\",\n\n # IPFS root.\n # root=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"ipfs\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"ipfs\", {\n // IPFS gateway endpoint.\n // endpoint: \"...\",\n\n // IPFS root.\n // root: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"ipfs\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// IPFS gateway endpoint.\n// conf.put(\"endpoint\", \"...\");\n\n// IPFS root.\n// conf.put(\"root\", \"...\");\n\nOperator op = Operator.of(\"ipfs\", conf);"
+ }
+ ]
+ },
+ {
+ "name": "ipmfs",
+ "scheme": "ipmfs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root for ipfs."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Endpoint for ipfs."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"ipmfs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"ipmfs\", [\n // Root for ipfs.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // Endpoint for ipfs.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"ipmfs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"ipmfs\",\n # Root for ipfs.\n # root=\"...\",\n\n # Endpoint for ipfs.\n # endpoint=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"ipmfs\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"ipmfs\", {\n // Root for ipfs.\n // root: \"...\",\n\n // Endpoint for ipfs.\n // endpoint: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"ipmfs\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// Root for ipfs.\n// conf.put(\"root\", \"...\");\n\n// Endpoint for ipfs.\n// conf.put(\"endpoint\", \"...\");\n\nOperator op = Operator.of(\"ipmfs\", conf);"
+ }
+ ]
+ },
+ {
+ "name": "koofr",
+ "scheme": "koofr",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend.\n\nAll operations will happen under this root."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "Koofr endpoint."
+ },
+ {
+ "name": "email",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "Koofr email."
+ },
+ {
+ "name": "password",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "password of this backend. (Must be the application password)"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"koofr\", [\n (\"endpoint\".to_string(), \"...\".to_string()),\n (\"email\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"koofr\", [\n // root of this backend.\n //\n // All operations will happen under this root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // Koofr endpoint.\n (\"endpoint\".to_string(), \"...\".to_string()),\n\n // Koofr email.\n (\"email\".to_string(), \"...\".to_string()),\n\n // password of this backend. (Must be the application password)\n // (\"password\".to_string(), \". [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"koofr\",\n endpoint=\"...\",\n email=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"koofr\",\n # root of this backend.\n #\n # All operations will happen under this root.\n # root=\"...\",\n\n # Koofr endpoint.\n endpoint=\"...\",\n\n # Koofr email.\n email=\"...\",\n\n # password of this backend. (Must be the application password)\n # password=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"koofr\", {\n endpoint: \"...\",\n email: \"...\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"koofr\", {\n // root of this backend.\n //\n // All operations will happen under this root.\n // root: \"...\",\n\n // Koofr endpoint.\n endpoint: \"...\",\n\n // Koofr email.\n email: \"...\",\n\n // password of this backend. (Must be the application password)\n // password: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"endpoint\", \"...\");\nconf.put(\"email\", \"...\");\nOperator op = Operator.of(\"koofr\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// root of this backend.\n//\n// All operations will happen under this root.\n// conf.put(\"root\", \"...\");\n\n// Koofr endpoint.\nconf.put(\"endpoint\", \"...\");\n\n// Koofr email.\nconf.put(\"email\", \"...\");\n\n// password of this backend. (Must be the application password)\n// conf.put(\"password\", \"...\");\n\nOperator op = Op [...]
+ }
+ ]
+ },
+ {
+ "name": "lakefs",
+ "scheme": "lakefs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Base url.\n\nThis is required."
+ },
+ {
+ "name": "username",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Username for Lakefs basic authentication.\n\nThis is required."
+ },
+ {
+ "name": "password",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Password for Lakefs basic authentication.\n\nThis is required."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root of this backend. Can be \"/path/to/dir\".\n\nDefault is \"/\"."
+ },
+ {
+ "name": "repository",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The repository name\n\nThis is required."
+ },
+ {
+ "name": "branch",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Name of the branch or a commit ID. Default is main.\n\nThis is optional."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"lakefs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"lakefs\", [\n // Base url.\n //\n // This is required.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // Username for Lakefs basic authentication.\n //\n // This is required.\n // (\"username\".to_string(), \"...\".to_string()),\n\n // Password for Lakefs basic authentication.\n //\n // This is required.\n // (\"password\".to_string(), \"...\".to_string()),\n\n // [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"lakefs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"lakefs\",\n # Base url.\n #\n # This is required.\n # endpoint=\"...\",\n\n # Username for Lakefs basic authentication.\n #\n # This is required.\n # username=\"...\",\n\n # Password for Lakefs basic authentication.\n #\n # This is required.\n # password=\"...\",\n\n # Root of this backend. Can be \"/path/to/dir\".\n #\n # Default is \"/\".\n # root=\"...\",\n\n # The rep [...]
+ }
+ ]
+ },
+ {
+ "name": "memcached",
+ "scheme": "memcached",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "network address of the memcached service.\n\nFor example: \"tcp://localhost:11211\""
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "the working directory of the service. Can be \"/path/to/dir\"\n\ndefault is \"/\""
+ },
+ {
+ "name": "username",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Memcached username, optional."
+ },
+ {
+ "name": "password",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Memcached password, optional."
+ },
+ {
+ "name": "default_ttl",
+ "type": "duration",
+ "required": false,
+ "group": "General",
+ "comments": "The default ttl for put operations."
+ },
+ {
+ "name": "connection_pool_max_size",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "comments": "The maximum number of connections allowed.\n\ndefault is 10"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"memcached\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"memcached\", [\n // network address of the memcached service.\n //\n // For example: \"tcp://localhost:11211\"\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // the working directory of the service. Can be \"/path/to/dir\"\n //\n // default is \"/\"\n // (\"root\".to_string(), \"...\".to_string()),\n\n // Memcached username, optional.\n // (\"username\".to_string(), \"...\" [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"memcached\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"memcached\",\n # network address of the memcached service.\n #\n # For example: \"tcp://localhost:11211\"\n # endpoint=\"...\",\n\n # the working directory of the service. Can be \"/path/to/dir\"\n #\n # default is \"/\"\n # root=\"...\",\n\n # Memcached username, optional.\n # username=\"...\",\n\n # Memcached password, optional.\n # password=\"...\",\n\n # The default ttl for put o [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"memcached\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"memcached\", {\n // network address of the memcached service.\n //\n // For example: \"tcp://localhost:11211\"\n // endpoint: \"...\",\n\n // the working directory of the service. Can be \"/path/to/dir\"\n //\n // default is \"/\"\n // root: \"...\",\n\n // Memcached username, optional.\n // username: \"...\",\n\n // Memcached password, optional.\n // password: \"...\",\n\n // The default t [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"memcached\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// network address of the memcached service.\n//\n// For example: \"tcp://localhost:11211\"\n// conf.put(\"endpoint\", \"...\");\n\n// the working directory of the service. Can be \"/path/to/dir\"\n//\n// default is \"/\"\n// conf.put(\"root\", \"...\");\n\n// Memcached username, optional.\n// conf.put(\"username\", \"...\");\n\n// Memca [...]
+ }
+ ]
+ },
+ {
+ "name": "memory",
+ "scheme": "memory",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of the backend."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"memory\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"memory\", [\n // root of the backend.\n // (\"root\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"memory\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"memory\",\n # root of the backend.\n # root=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"memory\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"memory\", {\n // root of the backend.\n // root: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"memory\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// root of the backend.\n// conf.put(\"root\", \"...\");\n\nOperator op = Operator.of(\"memory\", conf);"
+ }
+ ]
+ },
+ {
+ "name": "mini_moka",
+ "scheme": "mini-moka",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "max_capacity",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "comments": "Sets the max capacity of the cache.\n\nRefer to [`mini-moka::sync::CacheBuilder::max_capacity`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.max_capacity)"
+ },
+ {
+ "name": "time_to_live",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Sets the time to live of the cache.\n\nRefer to [`mini-moka::sync::CacheBuilder::time_to_live`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.time_to_live)"
+ },
+ {
+ "name": "time_to_idle",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Sets the time to idle of the cache.\n\nRefer to [`mini-moka::sync::CacheBuilder::time_to_idle`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.time_to_idle)"
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root path of this backend"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"mini-moka\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"mini-moka\", [\n // Sets the max capacity of the cache.\n //\n // Refer to [`mini-moka::sync::CacheBuilder::max_capacity`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.max_capacity)\n // (\"max_capacity\".to_string(), \"1000\".to_string()),\n\n // Sets the time to live of the cache.\n //\n // Refer to [`mini-moka::sync::CacheBuilder::time_to_live`](https://do [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"mini-moka\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"mini-moka\",\n # Sets the max capacity of the cache.\n #\n # Refer to [`mini-moka::sync::CacheBuilder::max_capacity`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.max_capacity)\n # max_capacity=\"1000\",\n\n # Sets the time to live of the cache.\n #\n # Refer to [`mini-moka::sync::CacheBuilder::time_to_live`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.Cac [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"mini-moka\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"mini-moka\", {\n // Sets the max capacity of the cache.\n //\n // Refer to [`mini-moka::sync::CacheBuilder::max_capacity`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.max_capacity)\n // max_capacity: \"1000\",\n\n // Sets the time to live of the cache.\n //\n // Refer to [`mini-moka::sync::CacheBuilder::time_to_live`](https://docs.rs/mini-moka/latest/mini_moka/ [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"mini-moka\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// Sets the max capacity of the cache.\n//\n// Refer to [`mini-moka::sync::CacheBuilder::max_capacity`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.max_capacity)\n// conf.put(\"max_capacity\", \"1000\");\n\n// Sets the time to live of the cache.\n//\n// Refer to [`mini-moka::sync::CacheBuilder::time_to [...]
+ }
+ ]
+ },
+ {
+ "name": "moka",
+ "scheme": "moka",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "name",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Name for this cache instance."
+ },
+ {
+ "name": "max_capacity",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "comments": "Sets the max capacity of the cache.\n\nRefer to [`moka::future::CacheBuilder::max_capacity`](https://docs.rs/moka/latest/moka/future/struct.CacheBuilder.html#method.max_capacity)"
+ },
+ {
+ "name": "time_to_live",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Sets the time to live of the cache.\n\nRefer to [`moka::future::CacheBuilder::time_to_live`](https://docs.rs/moka/latest/moka/future/struct.CacheBuilder.html#method.time_to_live)"
+ },
+ {
+ "name": "time_to_idle",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Sets the time to idle of the cache.\n\nRefer to [`moka::future::CacheBuilder::time_to_idle`](https://docs.rs/moka/latest/moka/future/struct.CacheBuilder.html#method.time_to_idle)"
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root path of this backend"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"moka\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"moka\", [\n // Name for this cache instance.\n // (\"name\".to_string(), \"...\".to_string()),\n\n // Sets the max capacity of the cache.\n //\n // Refer to [`moka::future::CacheBuilder::max_capacity`](https://docs.rs/moka/latest/moka/future/struct.CacheBuilder.html#method.max_capacity)\n // (\"max_capacity\".to_string(), \"1000\".to_string()),\n\n // Sets the time to live of the cache.\n / [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"moka\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"moka\",\n # Name for this cache instance.\n # name=\"...\",\n\n # Sets the max capacity of the cache.\n #\n # Refer to [`moka::future::CacheBuilder::max_capacity`](https://docs.rs/moka/latest/moka/future/struct.CacheBuilder.html#method.max_capacity)\n # max_capacity=\"1000\",\n\n # Sets the time to live of the cache.\n #\n # Refer to [`moka::future::CacheBuilder::time_to_live`](https://docs.rs/m [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"moka\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"moka\", {\n // Name for this cache instance.\n // name: \"...\",\n\n // Sets the max capacity of the cache.\n //\n // Refer to [`moka::future::CacheBuilder::max_capacity`](https://docs.rs/moka/latest/moka/future/struct.CacheBuilder.html#method.max_capacity)\n // max_capacity: \"1000\",\n\n // Sets the time to live of the cache.\n //\n // Refer to [`moka::future::CacheBuilder::time_to_live`](htt [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"moka\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// Name for this cache instance.\n// conf.put(\"name\", \"...\");\n\n// Sets the max capacity of the cache.\n//\n// Refer to [`moka::future::CacheBuilder::max_capacity`](https://docs.rs/moka/latest/moka/future/struct.CacheBuilder.html#method.max_capacity)\n// conf.put(\"max_capacity\", \"1000\");\n\n// Sets the time to live of the cache. [...]
+ }
+ ]
+ },
+ {
+ "name": "mongodb",
+ "scheme": "mongodb",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "connection_string",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "connection string of this backend"
+ },
+ {
+ "name": "database",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "database of this backend"
+ },
+ {
+ "name": "collection",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "collection of this backend"
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend"
+ },
+ {
+ "name": "key_field",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "key field of this backend"
+ },
+ {
+ "name": "value_field",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "value field of this backend"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"mongodb\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"mongodb\", [\n // connection string of this backend\n // (\"connection_string\".to_string(), \"...\".to_string()),\n\n // database of this backend\n // (\"database\".to_string(), \"...\".to_string()),\n\n // collection of this backend\n // (\"collection\".to_string(), \"...\".to_string()),\n\n // root of this backend\n // (\"root\".to_string(), \"...\".to_string()),\n\n // key field of t [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"mongodb\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"mongodb\",\n # connection string of this backend\n # connection_string=\"...\",\n\n # database of this backend\n # database=\"...\",\n\n # collection of this backend\n # collection=\"...\",\n\n # root of this backend\n # root=\"...\",\n\n # key field of this backend\n # key_field=\"...\",\n\n # value field of this backend\n # value_field=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"mongodb\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"mongodb\", {\n // connection string of this backend\n // connection_string: \"...\",\n\n // database of this backend\n // database: \"...\",\n\n // collection of this backend\n // collection: \"...\",\n\n // root of this backend\n // root: \"...\",\n\n // key field of this backend\n // key_field: \"...\",\n\n // value field of this backend\n // value_field: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"mongodb\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// connection string of this backend\n// conf.put(\"connection_string\", \"...\");\n\n// database of this backend\n// conf.put(\"database\", \"...\");\n\n// collection of this backend\n// conf.put(\"collection\", \"...\");\n\n// root of this backend\n// conf.put(\"root\", \"...\");\n\n// key field of this backend\n// conf.put(\"key_field [...]
+ }
+ ]
+ },
+ {
+ "name": "monoiofs",
+ "scheme": "monoiofs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The Root of this backend.\n\nAll operations will happen under this root.\n\nBuilder::build will return error if not set."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"monoiofs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"monoiofs\", [\n // The Root of this backend.\n //\n // All operations will happen under this root.\n //\n // Builder::build will return error if not set.\n // (\"root\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"monoiofs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"monoiofs\",\n # The Root of this backend.\n #\n # All operations will happen under this root.\n #\n # Builder::build will return error if not set.\n # root=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"monoiofs\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"monoiofs\", {\n // The Root of this backend.\n //\n // All operations will happen under this root.\n //\n // Builder::build will return error if not set.\n // root: \"...\",\n\n});"
+ }
+ ]
+ },
+ {
+ "name": "mysql",
+ "scheme": "mysql",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "connection_string",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "This connection string is used to connect to the mysql service. There are url based formats.\n\nThe format of connect string resembles the url format of the mysql client.\nThe format is: `[scheme://][user[:[password]]@]host[:port][/schema][?attribute1=value1&attribute2=value2...`\n\n- `mysql://user@localhost`\n- `mysql://user:password@localhost`\n- `mysql://user:password@localhost:3306`\n- `mysql://user:password@localhost:3306/db`\n\nFor more information, please re [...]
+ },
+ {
+ "name": "table",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The table name for mysql."
+ },
+ {
+ "name": "key_field",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The key field name for mysql."
+ },
+ {
+ "name": "value_field",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The value field name for mysql."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The root for mysql."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"mysql\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"mysql\", [\n // This connection string is used to connect to the mysql service. There are url based formats.\n //\n // The format of connect string resembles the url format of the mysql client.\n // The format is: `[scheme://][user[:[password]]@]host[:port][/schema][?attribute1=value1&attribute2=value2...`\n //\n // - `mysql://user@localhost`\n // - `mysql://user:password@localhost`\n // - [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"mysql\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"mysql\",\n # This connection string is used to connect to the mysql service. There are url based formats.\n #\n # The format of connect string resembles the url format of the mysql client.\n # The format is: `[scheme://][user[:[password]]@]host[:port][/schema][?attribute1=value1&attribute2=value2...`\n #\n # - `mysql://user@localhost`\n # - `mysql://user:password@localhost`\n # - `mysql://user:pass [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"mysql\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"mysql\", {\n // This connection string is used to connect to the mysql service. There are url based formats.\n //\n // The format of connect string resembles the url format of the mysql client.\n // The format is: `[scheme://][user[:[password]]@]host[:port][/schema][?attribute1=value1&attribute2=value2...`\n //\n // - `mysql://user@localhost`\n // - `mysql://user:password@localhost`\n // - `mysq [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"mysql\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// This connection string is used to connect to the mysql service. There are url based formats.\n//\n// The format of connect string resembles the url format of the mysql client.\n// The format is: `[scheme://][user[:[password]]@]host[:port][/schema][?attribute1=value1&attribute2=value2...`\n//\n// - `mysql://user@localhost`\n// - `mysql [...]
+ }
+ ]
+ },
+ {
+ "name": "obs",
+ "scheme": "obs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root for obs."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Endpoint for obs."
+ },
+ {
+ "name": "access_key_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Access key id for obs."
+ },
+ {
+ "name": "secret_access_key",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Secret access key for obs."
+ },
+ {
+ "name": "bucket",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Bucket for obs."
+ },
+ {
+ "name": "enable_versioning",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "OBS versioning capability is not controlled by this option and this option is no longer needed."
+ },
+ "comments": "Deprecated: OBS versioning capability is not controlled by service config."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"obs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"obs\", [\n // Root for obs.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // Endpoint for obs.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // Access key id for obs.\n // (\"access_key_id\".to_string(), \"...\".to_string()),\n\n // Secret access key for obs.\n // (\"secret_access_key\".to_string(), \"...\".to_string()),\n\n // Bucket for obs.\n // (\"bucket\".to_s [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"obs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"obs\",\n # Root for obs.\n # root=\"...\",\n\n # Endpoint for obs.\n # endpoint=\"...\",\n\n # Access key id for obs.\n # access_key_id=\"...\",\n\n # Secret access key for obs.\n # secret_access_key=\"...\",\n\n # Bucket for obs.\n # bucket=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"obs\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"obs\", {\n // Root for obs.\n // root: \"...\",\n\n // Endpoint for obs.\n // endpoint: \"...\",\n\n // Access key id for obs.\n // access_key_id: \"...\",\n\n // Secret access key for obs.\n // secret_access_key: \"...\",\n\n // Bucket for obs.\n // bucket: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"obs\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// Root for obs.\n// conf.put(\"root\", \"...\");\n\n// Endpoint for obs.\n// conf.put(\"endpoint\", \"...\");\n\n// Access key id for obs.\n// conf.put(\"access_key_id\", \"...\");\n\n// Secret access key for obs.\n// conf.put(\"secret_access_key\", \"...\");\n\n// Bucket for obs.\n// conf.put(\"bucket\", \"...\");\n\nOperator op = Oper [...]
+ }
+ ]
+ },
+ {
+ "name": "onedrive",
+ "scheme": "onedrive",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The root path for the OneDrive service for the file access"
+ },
+ {
+ "name": "access_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Microsoft Graph API (also OneDrive API) access token"
+ },
+ {
+ "name": "refresh_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Microsoft Graph API (also OneDrive API) refresh token"
+ },
+ {
+ "name": "client_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Microsoft Graph API Application (client) ID that is in the Azure's app registration portal"
+ },
+ {
+ "name": "client_secret",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Microsoft Graph API Application client secret that is in the Azure's app registration portal"
+ },
+ {
+ "name": "enable_versioning",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "OneDrive versioning capability is enabled by default and this option is no longer needed."
+ },
+ "comments": "Deprecated: OneDrive versioning capability is enabled by default."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"onedrive\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"onedrive\", [\n // The root path for the OneDrive service for the file access\n // (\"root\".to_string(), \"...\".to_string()),\n\n // Microsoft Graph API (also OneDrive API) access token\n // (\"access_token\".to_string(), \"...\".to_string()),\n\n // Microsoft Graph API (also OneDrive API) refresh token\n // (\"refresh_token\".to_string(), \"...\".to_string()),\n\n // Microsoft Graph API App [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"onedrive\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"onedrive\",\n # The root path for the OneDrive service for the file access\n # root=\"...\",\n\n # Microsoft Graph API (also OneDrive API) access token\n # access_token=\"...\",\n\n # Microsoft Graph API (also OneDrive API) refresh token\n # refresh_token=\"...\",\n\n # Microsoft Graph API Application (client) ID that is in the Azure's app registration portal\n # client_id=\"...\",\n\n # Microso [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"onedrive\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"onedrive\", {\n // The root path for the OneDrive service for the file access\n // root: \"...\",\n\n // Microsoft Graph API (also OneDrive API) access token\n // access_token: \"...\",\n\n // Microsoft Graph API (also OneDrive API) refresh token\n // refresh_token: \"...\",\n\n // Microsoft Graph API Application (client) ID that is in the Azure's app registration portal\n // client_id: \"...\", [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"onedrive\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// The root path for the OneDrive service for the file access\n// conf.put(\"root\", \"...\");\n\n// Microsoft Graph API (also OneDrive API) access token\n// conf.put(\"access_token\", \"...\");\n\n// Microsoft Graph API (also OneDrive API) refresh token\n// conf.put(\"refresh_token\", \"...\");\n\n// Microsoft Graph API Application (cli [...]
+ }
+ ]
+ },
+ {
+ "name": "opfs",
+ "scheme": "opfs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root directory for this backend."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"opfs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"opfs\", [\n // Root directory for this backend.\n // (\"root\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"opfs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"opfs\",\n # Root directory for this backend.\n # root=\"...\",\n\n)"
+ }
+ ]
+ },
+ {
+ "name": "oss",
+ "scheme": "oss",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root for oss."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Endpoint for oss."
+ },
+ {
+ "name": "presign_endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Presign endpoint for oss."
+ },
+ {
+ "name": "bucket",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "Bucket for oss."
+ },
+ {
+ "name": "addressing_style",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Addressing style for oss."
+ },
+ {
+ "name": "presign_addressing_style",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Pre sign addressing style for oss."
+ },
+ {
+ "name": "enable_versioning",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "OSS versioning capability is enabled by default and this option is no longer needed."
+ },
+ "comments": "Deprecated: OSS versioning capability is enabled by default."
+ },
+ {
+ "name": "server_side_encryption",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Server side encryption for oss."
+ },
+ {
+ "name": "server_side_encryption_key_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Server side encryption key id for oss."
+ },
+ {
+ "name": "skip_signature",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "comments": "Skip signature will skip loading credentials and signing requests."
+ },
+ {
+ "name": "allow_anonymous",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "Please use `skip_signature` instead of `allow_anonymous`"
+ },
+ "comments": "Allow anonymous for oss."
+ },
+ {
+ "name": "access_key_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Access key id for oss.\n\n- this field if it's `is_some`\n- env value: `ALIBABA_CLOUD_ACCESS_KEY_ID`"
+ },
+ {
+ "name": "access_key_secret",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Access key secret for oss.\n\n- this field if it's `is_some`\n- env value: `ALIBABA_CLOUD_ACCESS_KEY_SECRET`"
+ },
+ {
+ "name": "security_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "`security_token` will be loaded from\n\n- this field if it's `is_some`\n- env value: `ALIBABA_CLOUD_SECURITY_TOKEN`"
+ },
+ {
+ "name": "batch_max_operations",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "OSS delete batch capability is enabled by default. Use CapabilityOverrideLayer to override delete_max_size for specific endpoints."
+ },
+ "comments": "Deprecated: OSS delete batch capability is enabled by default."
+ },
+ {
+ "name": "delete_max_size",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "OSS delete batch capability is enabled by default. Use CapabilityOverrideLayer to override delete_max_size for specific endpoints."
+ },
+ "comments": "Deprecated: OSS delete batch capability is enabled by default."
+ },
+ {
+ "name": "role_arn",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "If `role_arn` is set, we will use already known config as source\ncredential to assume role with `role_arn`.\n\n- this field if it's `is_some`\n- env value: `ALIBABA_CLOUD_ROLE_ARN`"
+ },
+ {
+ "name": "role_session_name",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "role_session_name for this backend."
+ },
+ {
+ "name": "oidc_provider_arn",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "`oidc_provider_arn` will be loaded from\n\n- this field if it's `is_some`\n- env value: `ALIBABA_CLOUD_OIDC_PROVIDER_ARN`"
+ },
+ {
+ "name": "oidc_token_file",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "`oidc_token_file` will be loaded from\n\n- this field if it's `is_some`\n- env value: `ALIBABA_CLOUD_OIDC_TOKEN_FILE`"
+ },
+ {
+ "name": "sts_endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "`sts_endpoint` will be loaded from\n\n- this field if it's `is_some`\n- env value: `ALIBABA_CLOUD_STS_ENDPOINT`"
+ },
+ {
+ "name": "external_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "external_id for this backend."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"oss\", [\n (\"bucket\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"oss\", [\n // Root for oss.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // Endpoint for oss.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // Presign endpoint for oss.\n // (\"presign_endpoint\".to_string(), \"...\".to_string()),\n\n // Bucket for oss.\n (\"bucket\".to_string(), \"...\".to_string()),\n\n // Addressing style for oss.\n // (\"addressing_style\".to_ [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"oss\",\n bucket=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"oss\",\n # Root for oss.\n # root=\"...\",\n\n # Endpoint for oss.\n # endpoint=\"...\",\n\n # Presign endpoint for oss.\n # presign_endpoint=\"...\",\n\n # Bucket for oss.\n bucket=\"...\",\n\n # Addressing style for oss.\n # addressing_style=\"...\",\n\n # Pre sign addressing style for oss.\n # presign_addressing_style=\"...\",\n\n # Server side encryption for oss.\n # server_si [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"oss\", {\n bucket: \"...\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"oss\", {\n // Root for oss.\n // root: \"...\",\n\n // Endpoint for oss.\n // endpoint: \"...\",\n\n // Presign endpoint for oss.\n // presign_endpoint: \"...\",\n\n // Bucket for oss.\n bucket: \"...\",\n\n // Addressing style for oss.\n // addressing_style: \"...\",\n\n // Pre sign addressing style for oss.\n // presign_addressing_style: \"...\",\n\n // Server side encryption for oss.\n [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"bucket\", \"...\");\nOperator op = Operator.of(\"oss\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// Root for oss.\n// conf.put(\"root\", \"...\");\n\n// Endpoint for oss.\n// conf.put(\"endpoint\", \"...\");\n\n// Presign endpoint for oss.\n// conf.put(\"presign_endpoint\", \"...\");\n\n// Bucket for oss.\nconf.put(\"bucket\", \"...\");\n\n// Addressing style for oss.\n// conf.put(\"addressing_style\", \"...\");\n\n// Pre sign addre [...]
+ }
+ ]
+ },
+ {
+ "name": "pcloud",
+ "scheme": "pcloud",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend.\n\nAll operations will happen under this root."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "pCloud endpoint address."
+ },
+ {
+ "name": "username",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "pCloud username."
+ },
+ {
+ "name": "password",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "pCloud password."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"pcloud\", [\n (\"endpoint\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"pcloud\", [\n // root of this backend.\n //\n // All operations will happen under this root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // pCloud endpoint address.\n (\"endpoint\".to_string(), \"...\".to_string()),\n\n // pCloud username.\n // (\"username\".to_string(), \"...\".to_string()),\n\n // pCloud password.\n // (\"password\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"pcloud\",\n endpoint=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"pcloud\",\n # root of this backend.\n #\n # All operations will happen under this root.\n # root=\"...\",\n\n # pCloud endpoint address.\n endpoint=\"...\",\n\n # pCloud username.\n # username=\"...\",\n\n # pCloud password.\n # password=\"...\",\n\n)"
+ }
+ ]
+ },
+ {
+ "name": "persy",
+ "scheme": "persy",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "datafile",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "That path to the persy data file. The directory in the path must already exist."
+ },
+ {
+ "name": "segment",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "That name of the persy segment."
+ },
+ {
+ "name": "index",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "That name of the persy index."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"persy\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"persy\", [\n // That path to the persy data file. The directory in the path must already exist.\n // (\"datafile\".to_string(), \"...\".to_string()),\n\n // That name of the persy segment.\n // (\"segment\".to_string(), \"...\".to_string()),\n\n // That name of the persy index.\n // (\"index\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"persy\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"persy\",\n # That path to the persy data file. The directory in the path must already exist.\n # datafile=\"...\",\n\n # That name of the persy segment.\n # segment=\"...\",\n\n # That name of the persy index.\n # index=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"persy\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"persy\", {\n // That path to the persy data file. The directory in the path must already exist.\n // datafile: \"...\",\n\n // That name of the persy segment.\n // segment: \"...\",\n\n // That name of the persy index.\n // index: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"persy\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// That path to the persy data file. The directory in the path must already exist.\n// conf.put(\"datafile\", \"...\");\n\n// That name of the persy segment.\n// conf.put(\"segment\", \"...\");\n\n// That name of the persy index.\n// conf.put(\"index\", \"...\");\n\nOperator op = Operator.of(\"persy\", conf);"
+ }
+ ]
+ },
+ {
+ "name": "postgresql",
+ "scheme": "postgresql",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root of this backend.\n\nAll operations will happen under this root.\n\nDefault to `/` if not set."
+ },
+ {
+ "name": "connection_string",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The URL should be with a scheme of either `postgres://` or `postgresql://`.\n\n- `postgresql://user@localhost`\n- `postgresql://user:password@%2Fvar%2Flib%2Fpostgresql/mydb?connect_timeout=10`\n- `postgresql://user@host1:1234,host2,host3:5678?target_session_attrs=read-write`\n- `postgresql:///mydb?user=user&host=/var/lib/postgresql`\n\nFor more information, please visit <https://docs.rs/sqlx/latest/sqlx/postgres/struct.PgConnectOptions.html>."
+ },
+ {
+ "name": "table",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "the table of postgresql"
+ },
+ {
+ "name": "key_field",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "the key field of postgresql"
+ },
+ {
+ "name": "value_field",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "the value field of postgresql"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"postgresql\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"postgresql\", [\n // Root of this backend.\n //\n // All operations will happen under this root.\n //\n // Default to `/` if not set.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // The URL should be with a scheme of either `postgres://` or `postgresql://`.\n //\n // - `postgresql://user@localhost`\n // - `postgresql://user:password@%2Fvar%2Flib%2Fpostgresql/mydb?connect_time [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"postgresql\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"postgresql\",\n # Root of this backend.\n #\n # All operations will happen under this root.\n #\n # Default to `/` if not set.\n # root=\"...\",\n\n # The URL should be with a scheme of either `postgres://` or `postgresql://`.\n #\n # - `postgresql://user@localhost`\n # - `postgresql://user:password@%2Fvar%2Flib%2Fpostgresql/mydb?connect_timeout=10`\n # - `postgresql://user@host1:1234,host [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"postgresql\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"postgresql\", {\n // Root of this backend.\n //\n // All operations will happen under this root.\n //\n // Default to `/` if not set.\n // root: \"...\",\n\n // The URL should be with a scheme of either `postgres://` or `postgresql://`.\n //\n // - `postgresql://user@localhost`\n // - `postgresql://user:password@%2Fvar%2Flib%2Fpostgresql/mydb?connect_timeout=10`\n // - `postgresql://user@host [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"postgresql\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// Root of this backend.\n//\n// All operations will happen under this root.\n//\n// Default to `/` if not set.\n// conf.put(\"root\", \"...\");\n\n// The URL should be with a scheme of either `postgres://` or `postgresql://`.\n//\n// - `postgresql://user@localhost`\n// - `postgresql://user:password@%2Fvar%2Flib%2Fpostgresql/mydb?connect [...]
+ }
+ ]
+ },
+ {
+ "name": "redb",
+ "scheme": "redb",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "datadir",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "path to the redb data directory."
+ },
+ {
+ "name": "table",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The table name for redb."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The root for redb."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"redb\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"redb\", [\n // path to the redb data directory.\n // (\"datadir\".to_string(), \"...\".to_string()),\n\n // The table name for redb.\n // (\"table\".to_string(), \"...\".to_string()),\n\n // The root for redb.\n // (\"root\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"redb\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"redb\",\n # path to the redb data directory.\n # datadir=\"...\",\n\n # The table name for redb.\n # table=\"...\",\n\n # The root for redb.\n # root=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"redb\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"redb\", {\n // path to the redb data directory.\n // datadir: \"...\",\n\n // The table name for redb.\n // table: \"...\",\n\n // The root for redb.\n // root: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"redb\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// path to the redb data directory.\n// conf.put(\"datadir\", \"...\");\n\n// The table name for redb.\n// conf.put(\"table\", \"...\");\n\n// The root for redb.\n// conf.put(\"root\", \"...\");\n\nOperator op = Operator.of(\"redb\", conf);"
+ }
+ ]
+ },
+ {
+ "name": "redis",
+ "scheme": "redis",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "network address of the Redis service. Can be \"tcp://127.0.0.1:6379\", e.g.\n\ndefault is \"tcp://127.0.0.1:6379\""
+ },
+ {
+ "name": "cluster_endpoints",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "network address of the Redis cluster service. Can be \"tcp://127.0.0.1:6379,tcp://127.0.0.1:6380,tcp://127.0.0.1:6381\", e.g.\n\ndefault is None"
+ },
+ {
+ "name": "connection_pool_max_size",
+ "type": "integer",
+ "required": false,
+ "group": "General",
+ "comments": "The maximum number of connections allowed.\n\ndefault is 10"
+ },
+ {
+ "name": "username",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "the username to connect redis service.\n\ndefault is None"
+ },
+ {
+ "name": "password",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "the password for authentication\n\ndefault is None"
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "the working directory of the Redis service. Can be \"/path/to/dir\"\n\ndefault is \"/\""
+ },
+ {
+ "name": "db",
+ "type": "integer",
+ "required": true,
+ "group": "General",
+ "comments": "the number of DBs redis can take is unlimited\n\ndefault is db 0"
+ },
+ {
+ "name": "default_ttl",
+ "type": "duration",
+ "required": false,
+ "group": "General",
+ "comments": "The default ttl for put operations."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"redis\", [\n (\"db\".to_string(), \"1000\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"redis\", [\n // network address of the Redis service. Can be \"tcp://127.0.0.1:6379\", e.g.\n //\n // default is \"tcp://127.0.0.1:6379\"\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // network address of the Redis cluster service. Can be \"tcp://127.0.0.1:6379,tcp://127.0.0.1:6380,tcp://127.0.0.1:6381\", e.g.\n //\n // default is None\n // (\"cluster_endpoints\".to_string(), \ [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"redis\",\n db=\"1000\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"redis\",\n # network address of the Redis service. Can be \"tcp://127.0.0.1:6379\", e.g.\n #\n # default is \"tcp://127.0.0.1:6379\"\n # endpoint=\"...\",\n\n # network address of the Redis cluster service. Can be \"tcp://127.0.0.1:6379,tcp://127.0.0.1:6380,tcp://127.0.0.1:6381\", e.g.\n #\n # default is None\n # cluster_endpoints=\"...\",\n\n # The maximum number of connections allowed.\n #\ [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"redis\", {\n db: \"1000\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"redis\", {\n // network address of the Redis service. Can be \"tcp://127.0.0.1:6379\", e.g.\n //\n // default is \"tcp://127.0.0.1:6379\"\n // endpoint: \"...\",\n\n // network address of the Redis cluster service. Can be \"tcp://127.0.0.1:6379,tcp://127.0.0.1:6380,tcp://127.0.0.1:6381\", e.g.\n //\n // default is None\n // cluster_endpoints: \"...\",\n\n // The maximum number of connections al [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"db\", \"1000\");\nOperator op = Operator.of(\"redis\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// network address of the Redis service. Can be \"tcp://127.0.0.1:6379\", e.g.\n//\n// default is \"tcp://127.0.0.1:6379\"\n// conf.put(\"endpoint\", \"...\");\n\n// network address of the Redis cluster service. Can be \"tcp://127.0.0.1:6379,tcp://127.0.0.1:6380,tcp://127.0.0.1:6381\", e.g.\n//\n// default is None\n// conf.put(\"cluster_ [...]
+ }
+ ]
+ },
+ {
+ "name": "rocksdb",
+ "scheme": "rocksdb",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "datadir",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The path to the rocksdb data directory."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "the working directory of the service. Can be \"/path/to/dir\"\n\ndefault is \"/\""
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"rocksdb\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"rocksdb\", [\n // The path to the rocksdb data directory.\n // (\"datadir\".to_string(), \"...\".to_string()),\n\n // the working directory of the service. Can be \"/path/to/dir\"\n //\n // default is \"/\"\n // (\"root\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"rocksdb\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"rocksdb\",\n # The path to the rocksdb data directory.\n # datadir=\"...\",\n\n # the working directory of the service. Can be \"/path/to/dir\"\n #\n # default is \"/\"\n # root=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"rocksdb\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"rocksdb\", {\n // The path to the rocksdb data directory.\n // datadir: \"...\",\n\n // the working directory of the service. Can be \"/path/to/dir\"\n //\n // default is \"/\"\n // root: \"...\",\n\n});"
+ }
+ ]
+ },
+ {
+ "name": "s3",
+ "scheme": "s3",
+ "groups": [
+ "General",
+ "Credentials",
+ "Assume role",
+ "Encryption",
+ "Behavior",
+ "Deprecated"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "default": "/",
+ "comments": "root of this backend.\n\nAll operations will happen under this root.\n\ndefault to `/` if not set."
+ },
+ {
+ "name": "bucket",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "example": "my-bucket",
+ "comments": "bucket name of this backend.\n\nrequired."
+ },
+ {
+ "name": "enable_versioning",
+ "type": "bool",
+ "required": false,
+ "group": "Deprecated",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "S3 versioning capability is enabled by default and this option is no longer needed."
+ },
+ "comments": "Deprecated: S3 versioning capability is enabled by default."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "default": "https://s3.amazonaws.com",
+ "comments": "endpoint of this backend.\n\nEndpoint must be full uri, e.g.\n\n- AWS S3: `https://s3.amazonaws.com` or `https://s3.{region}.amazonaws.com`\n- Cloudflare R2: `https://<ACCOUNT_ID>.r2.cloudflarestorage.com`\n- Aliyun OSS: `https://{region}.aliyuncs.com`\n- Tencent COS: `https://cos.{region}.myqcloud.com`\n- Minio: `http://127.0.0.1:9000`\n\nIf user inputs endpoint without scheme like \"s3.amazonaws.com\", we\nwill prepend \"https://\" before it.\n\n- If endpoint is [...]
+ },
+ {
+ "name": "region",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "example": "us-east-1",
+ "comments": "Region represent the signing region of this endpoint. This is required\nif you are using the default AWS S3 endpoint.\n\nIf using a custom endpoint,\n- If region is set, we will take user's input first.\n- If not, we will try to load it from environment."
+ },
+ {
+ "name": "access_key_id",
+ "type": "string",
+ "required": false,
+ "group": "Credentials",
+ "comments": "access_key_id of this backend.\n\n- If access_key_id is set, we will take user's input first.\n- If not, we will try to load it from environment."
+ },
+ {
+ "name": "secret_access_key",
+ "type": "string",
+ "required": false,
+ "group": "Credentials",
+ "comments": "secret_access_key of this backend.\n\n- If secret_access_key is set, we will take user's input first.\n- If not, we will try to load it from environment."
+ },
+ {
+ "name": "session_token",
+ "type": "string",
+ "required": false,
+ "group": "Credentials",
+ "comments": "session_token (aka, security token) of this backend.\n\nThis token will expire after sometime, it's recommended to set session_token\nby hand."
+ },
+ {
+ "name": "role_arn",
+ "type": "string",
+ "required": false,
+ "group": "Assume role",
+ "comments": "role_arn for this backend.\n\nIf `role_arn` is set, we will use already known config as source\ncredential to assume role with `role_arn`."
+ },
+ {
+ "name": "external_id",
+ "type": "string",
+ "required": false,
+ "group": "Assume role",
+ "comments": "external_id for this backend."
+ },
+ {
+ "name": "role_session_name",
+ "type": "string",
+ "required": false,
+ "group": "Assume role",
+ "comments": "role_session_name for this backend."
+ },
+ {
+ "name": "assume_role_duration_seconds",
+ "type": "integer",
+ "required": false,
+ "group": "Assume role",
+ "comments": "assume_role_duration_seconds for this backend."
+ },
+ {
+ "name": "assume_role_session_tags",
+ "type": "map",
+ "required": false,
+ "group": "Assume role",
+ "comments": "assume_role_session_tags for this backend."
+ },
+ {
+ "name": "disable_config_load",
+ "type": "bool",
+ "required": false,
+ "group": "Credentials",
+ "comments": "Disable config load so that opendal will not load config from\nenvironment.\n\nFor examples:\n\n- envs like `AWS_ACCESS_KEY_ID`\n- files like `~/.aws/config`"
+ },
+ {
+ "name": "disable_ec2_metadata",
+ "type": "bool",
+ "required": false,
+ "group": "Credentials",
+ "comments": "Disable load credential from ec2 metadata.\n\nThis option is used to disable the default behavior of opendal\nto load credential from ec2 metadata, a.k.a., IMDSv2"
+ },
+ {
+ "name": "skip_signature",
+ "type": "bool",
+ "required": false,
+ "group": "Credentials",
+ "comments": "Skip signature will skip loading credentials and signing requests."
+ },
+ {
+ "name": "allow_anonymous",
+ "type": "bool",
+ "required": false,
+ "group": "Deprecated",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "Please use `skip_signature` instead of `allow_anonymous`"
+ },
+ "comments": "Allow anonymous will allow opendal to send request without signing\nwhen credential is not loaded."
+ },
+ {
+ "name": "server_side_encryption",
+ "type": "string",
+ "required": false,
+ "group": "Encryption",
+ "comments": "server_side_encryption for this backend.\n\nAvailable values: `AES256`, `aws:kms`."
+ },
+ {
+ "name": "server_side_encryption_aws_kms_key_id",
+ "type": "string",
+ "required": false,
+ "group": "Encryption",
+ "comments": "server_side_encryption_aws_kms_key_id for this backend\n\n- If `server_side_encryption` set to `aws:kms`, and `server_side_encryption_aws_kms_key_id`\nis not set, S3 will use aws managed kms key to encrypt data.\n- If `server_side_encryption` set to `aws:kms`, and `server_side_encryption_aws_kms_key_id`\nis a valid kms key id, S3 will use the provided kms key to encrypt data.\n- If the `server_side_encryption_aws_kms_key_id` is invalid or not found, an error will b [...]
+ },
+ {
+ "name": "server_side_encryption_customer_algorithm",
+ "type": "string",
+ "required": false,
+ "group": "Encryption",
+ "comments": "server_side_encryption_customer_algorithm for this backend.\n\nAvailable values: `AES256`."
+ },
+ {
+ "name": "server_side_encryption_customer_key",
+ "type": "string",
+ "required": false,
+ "group": "Encryption",
+ "comments": "server_side_encryption_customer_key for this backend.\n\nValue: BASE64-encoded key that matches algorithm specified in\n`server_side_encryption_customer_algorithm`."
+ },
+ {
+ "name": "server_side_encryption_customer_key_md5",
+ "type": "string",
+ "required": false,
+ "group": "Encryption",
+ "comments": "Set server_side_encryption_customer_key_md5 for this backend.\n\nValue: MD5 digest of key specified in `server_side_encryption_customer_key`."
+ },
+ {
+ "name": "default_storage_class",
+ "type": "string",
+ "required": false,
+ "group": "Behavior",
+ "comments": "default storage_class for this backend.\n\nAvailable values:\n- `DEEP_ARCHIVE`\n- `GLACIER`\n- `GLACIER_IR`\n- `INTELLIGENT_TIERING`\n- `ONEZONE_IA`\n- `EXPRESS_ONEZONE`\n- `OUTPOSTS`\n- `REDUCED_REDUNDANCY`\n- `STANDARD`\n- `STANDARD_IA`\n\nS3 compatible services don't support all of them"
+ },
+ {
+ "name": "enable_virtual_host_style",
+ "type": "bool",
+ "required": false,
+ "group": "Behavior",
+ "comments": "Enable virtual host style so that opendal will send API requests\nin virtual host style instead of path style.\n\n- By default, opendal will send API to `https://s3.us-east-1.amazonaws.com/bucket_name`\n- Enabled, opendal will send API to `https://bucket_name.s3.us-east-1.amazonaws.com`"
+ },
+ {
+ "name": "batch_max_operations",
+ "type": "integer",
+ "required": false,
+ "group": "Deprecated",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "S3 delete batch capability is enabled by default. Use CapabilityOverrideLayer to override delete_max_size for specific endpoints."
+ },
+ "comments": "Deprecated: S3 delete batch capability is enabled by default."
+ },
+ {
+ "name": "delete_max_size",
+ "type": "integer",
+ "required": false,
+ "group": "Deprecated",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "S3 delete batch capability is enabled by default. Use CapabilityOverrideLayer to override delete_max_size for specific endpoints."
+ },
+ "comments": "Deprecated: S3 delete batch capability is enabled by default."
+ },
+ {
+ "name": "disable_stat_with_override",
+ "type": "bool",
+ "required": false,
+ "group": "Deprecated",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "S3 stat override capabilities are enabled by default. Use CapabilityOverrideLayer to override them for specific endpoints."
+ },
+ "comments": "Deprecated: S3 stat override capabilities are enabled by default."
+ },
+ {
+ "name": "checksum_algorithm",
+ "type": "string",
+ "required": false,
+ "group": "Behavior",
+ "comments": "Checksum Algorithm to use when sending checksums in HTTP headers.\nThis is necessary when writing to AWS S3 Buckets with Object Lock enabled for example.\n\nAvailable options:\n- \"crc32c\"\n- \"md5\""
+ },
+ {
+ "name": "disable_write_with_if_match",
+ "type": "bool",
+ "required": false,
+ "group": "Deprecated",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "S3 write with If-Match capability is enabled by default and this option is no longer needed."
+ },
+ "comments": "Deprecated: S3 write with If-Match capability is enabled by default."
+ },
+ {
+ "name": "enable_write_with_append",
+ "type": "bool",
+ "required": false,
+ "group": "Deprecated",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "S3 append capability is enabled by default and this option is no longer needed."
+ },
+ "comments": "Deprecated: S3 append capability is enabled by default."
+ },
+ {
+ "name": "disable_list_objects_v2",
+ "type": "bool",
+ "required": false,
+ "group": "Behavior",
+ "comments": "OpenDAL uses List Objects V2 by default to list objects.\nHowever, some legacy services do not yet support V2.\nThis option allows users to switch back to the older List Objects V1."
+ },
+ {
+ "name": "enable_request_payer",
+ "type": "bool",
+ "required": false,
+ "group": "Behavior",
+ "comments": "Indicates whether the client agrees to pay for the requests made to the S3 bucket."
+ },
+ {
+ "name": "default_acl",
+ "type": "string",
+ "required": false,
+ "group": "Behavior",
+ "comments": "Default ACL for new objects.\nNote that some s3 services like minio do not support this option."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"s3\", [\n (\"bucket\".to_string(), \"my-bucket\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"s3\", [\n // --- General ---\n // root of this backend.\n //\n // All operations will happen under this root.\n //\n // default to `/` if not set.\n // (\"root\".to_string(), \"/\".to_string()),\n\n // bucket name of this backend.\n //\n // required.\n (\"bucket\".to_string(), \"my-bucket\".to_string()),\n\n // endpoint of this backend.\n //\n // Endpoint must be full uri, [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"s3\",\n bucket=\"my-bucket\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"s3\",\n # --- General ---\n # root of this backend.\n #\n # All operations will happen under this root.\n #\n # default to `/` if not set.\n # root=\"/\",\n\n # bucket name of this backend.\n #\n # required.\n bucket=\"my-bucket\",\n\n # endpoint of this backend.\n #\n # Endpoint must be full uri, e.g.\n #\n # - AWS S3: `https://s3.amazonaws.com` or `https://s3.{region}.amaz [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"s3\", {\n bucket: \"my-bucket\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"s3\", {\n // --- General ---\n // root of this backend.\n //\n // All operations will happen under this root.\n //\n // default to `/` if not set.\n // root: \"/\",\n\n // bucket name of this backend.\n //\n // required.\n bucket: \"my-bucket\",\n\n // endpoint of this backend.\n //\n // Endpoint must be full uri, e.g.\n //\n // - AWS S3: `https://s3.amazonaws.com` or `https://s3.{region [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"bucket\", \"my-bucket\");\nOperator op = Operator.of(\"s3\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// --- General ---\n// root of this backend.\n//\n// All operations will happen under this root.\n//\n// default to `/` if not set.\n// conf.put(\"root\", \"/\");\n\n// bucket name of this backend.\n//\n// required.\nconf.put(\"bucket\", \"my-bucket\");\n\n// endpoint of this backend.\n//\n// Endpoint must be full uri, e.g.\n//\n// - AWS [...]
+ }
+ ]
+ },
+ {
+ "name": "seafile",
+ "scheme": "seafile",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend.\n\nAll operations will happen under this root."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "endpoint address of this backend."
+ },
+ {
+ "name": "username",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "username of this backend."
+ },
+ {
+ "name": "password",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "password of this backend."
+ },
+ {
+ "name": "repo_name",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "repo_name of this backend.\n\nrequired."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"seafile\", [\n (\"repo_name\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"seafile\", [\n // root of this backend.\n //\n // All operations will happen under this root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // endpoint address of this backend.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // username of this backend.\n // (\"username\".to_string(), \"...\".to_string()),\n\n // password of this backend.\n // (\"password\".to_string [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"seafile\",\n repo_name=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"seafile\",\n # root of this backend.\n #\n # All operations will happen under this root.\n # root=\"...\",\n\n # endpoint address of this backend.\n # endpoint=\"...\",\n\n # username of this backend.\n # username=\"...\",\n\n # password of this backend.\n # password=\"...\",\n\n # repo_name of this backend.\n #\n # required.\n repo_name=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"seafile\", {\n repo_name: \"...\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"seafile\", {\n // root of this backend.\n //\n // All operations will happen under this root.\n // root: \"...\",\n\n // endpoint address of this backend.\n // endpoint: \"...\",\n\n // username of this backend.\n // username: \"...\",\n\n // password of this backend.\n // password: \"...\",\n\n // repo_name of this backend.\n //\n // required.\n repo_name: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"repo_name\", \"...\");\nOperator op = Operator.of(\"seafile\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// root of this backend.\n//\n// All operations will happen under this root.\n// conf.put(\"root\", \"...\");\n\n// endpoint address of this backend.\n// conf.put(\"endpoint\", \"...\");\n\n// username of this backend.\n// conf.put(\"username\", \"...\");\n\n// password of this backend.\n// conf.put(\"password\", \"...\");\n\n// repo_nam [...]
+ }
+ ]
+ },
+ {
+ "name": "sftp",
+ "scheme": "sftp",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "endpoint of this backend"
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend"
+ },
+ {
+ "name": "user",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "user of this backend"
+ },
+ {
+ "name": "key",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "key of this backend"
+ },
+ {
+ "name": "known_hosts_strategy",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "known_hosts_strategy of this backend"
+ },
+ {
+ "name": "enable_copy",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "SFTP copy capability is enabled by default and this option is no longer needed."
+ },
+ "comments": "Deprecated: SFTP copy capability is enabled by default."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"sftp\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"sftp\", [\n // endpoint of this backend\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // root of this backend\n // (\"root\".to_string(), \"...\".to_string()),\n\n // user of this backend\n // (\"user\".to_string(), \"...\".to_string()),\n\n // key of this backend\n // (\"key\".to_string(), \"...\".to_string()),\n\n // known_hosts_strategy of this backend\n // (\"known_hos [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"sftp\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"sftp\",\n # endpoint of this backend\n # endpoint=\"...\",\n\n # root of this backend\n # root=\"...\",\n\n # user of this backend\n # user=\"...\",\n\n # key of this backend\n # key=\"...\",\n\n # known_hosts_strategy of this backend\n # known_hosts_strategy=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"sftp\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"sftp\", {\n // endpoint of this backend\n // endpoint: \"...\",\n\n // root of this backend\n // root: \"...\",\n\n // user of this backend\n // user: \"...\",\n\n // key of this backend\n // key: \"...\",\n\n // known_hosts_strategy of this backend\n // known_hosts_strategy: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"sftp\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// endpoint of this backend\n// conf.put(\"endpoint\", \"...\");\n\n// root of this backend\n// conf.put(\"root\", \"...\");\n\n// user of this backend\n// conf.put(\"user\", \"...\");\n\n// key of this backend\n// conf.put(\"key\", \"...\");\n\n// known_hosts_strategy of this backend\n// conf.put(\"known_hosts_strategy\", \"...\");\n\nO [...]
+ }
+ ]
+ },
+ {
+ "name": "sled",
+ "scheme": "sled",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "datadir",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "That path to the sled data directory."
+ },
+ {
+ "name": "tree",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The tree for sled."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The root for sled."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"sled\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"sled\", [\n // That path to the sled data directory.\n // (\"datadir\".to_string(), \"...\".to_string()),\n\n // The tree for sled.\n // (\"tree\".to_string(), \"...\".to_string()),\n\n // The root for sled.\n // (\"root\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"sled\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"sled\",\n # That path to the sled data directory.\n # datadir=\"...\",\n\n # The tree for sled.\n # tree=\"...\",\n\n # The root for sled.\n # root=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"sled\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"sled\", {\n // That path to the sled data directory.\n // datadir: \"...\",\n\n // The tree for sled.\n // tree: \"...\",\n\n // The root for sled.\n // root: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"sled\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// That path to the sled data directory.\n// conf.put(\"datadir\", \"...\");\n\n// The tree for sled.\n// conf.put(\"tree\", \"...\");\n\n// The root for sled.\n// conf.put(\"root\", \"...\");\n\nOperator op = Operator.of(\"sled\", conf);"
+ }
+ ]
+ },
+ {
+ "name": "sqlite",
+ "scheme": "sqlite",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "connection_string",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Set the connection_string of the sqlite service.\n\nThis connection string is used to connect to the sqlite service.\n\nThe format of connect string resembles the url format of the sqlite client:\n\n- `sqlite::memory:`\n- `sqlite:data.db`\n- `sqlite://data.db`\n\nFor more information, please visit <https://docs.rs/sqlx/latest/sqlx/sqlite/struct.SqliteConnectOptions.html>."
+ },
+ {
+ "name": "table",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Set the table name of the sqlite service to read/write."
+ },
+ {
+ "name": "key_field",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Set the key field name of the sqlite service to read/write.\n\nDefault to `key` if not specified."
+ },
+ {
+ "name": "value_field",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Set the value field name of the sqlite service to read/write.\n\nDefault to `value` if not specified."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "set the working directory, all operations will be performed under it.\n\ndefault: \"/\""
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"sqlite\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"sqlite\", [\n // Set the connection_string of the sqlite service.\n //\n // This connection string is used to connect to the sqlite service.\n //\n // The format of connect string resembles the url format of the sqlite client:\n //\n // - `sqlite::memory:`\n // - `sqlite:data.db`\n // - `sqlite://data.db`\n //\n // For more information, please visit <https://docs.rs/sqlx/latest/sql [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"sqlite\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"sqlite\",\n # Set the connection_string of the sqlite service.\n #\n # This connection string is used to connect to the sqlite service.\n #\n # The format of connect string resembles the url format of the sqlite client:\n #\n # - `sqlite::memory:`\n # - `sqlite:data.db`\n # - `sqlite://data.db`\n #\n # For more information, please visit <https://docs.rs/sqlx/latest/sqlx/sqlite/struct.Sqlit [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"sqlite\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"sqlite\", {\n // Set the connection_string of the sqlite service.\n //\n // This connection string is used to connect to the sqlite service.\n //\n // The format of connect string resembles the url format of the sqlite client:\n //\n // - `sqlite::memory:`\n // - `sqlite:data.db`\n // - `sqlite://data.db`\n //\n // For more information, please visit <https://docs.rs/sqlx/latest/sqlx/sqlite/st [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"sqlite\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// Set the connection_string of the sqlite service.\n//\n// This connection string is used to connect to the sqlite service.\n//\n// The format of connect string resembles the url format of the sqlite client:\n//\n// - `sqlite::memory:`\n// - `sqlite:data.db`\n// - `sqlite://data.db`\n//\n// For more information, please visit <https://do [...]
+ }
+ ]
+ },
+ {
+ "name": "surrealdb",
+ "scheme": "surrealdb",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "connection_string",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The connection string for surrealdb."
+ },
+ {
+ "name": "username",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The username for surrealdb."
+ },
+ {
+ "name": "password",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The password for surrealdb."
+ },
+ {
+ "name": "namespace",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The namespace for surrealdb."
+ },
+ {
+ "name": "database",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The database for surrealdb."
+ },
+ {
+ "name": "table",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The table for surrealdb."
+ },
+ {
+ "name": "key_field",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The key field for surrealdb."
+ },
+ {
+ "name": "value_field",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The value field for surrealdb."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The root for surrealdb."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"surrealdb\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"surrealdb\", [\n // The connection string for surrealdb.\n // (\"connection_string\".to_string(), \"...\".to_string()),\n\n // The username for surrealdb.\n // (\"username\".to_string(), \"...\".to_string()),\n\n // The password for surrealdb.\n // (\"password\".to_string(), \"...\".to_string()),\n\n // The namespace for surrealdb.\n // (\"namespace\".to_string(), \"...\".to_string()),\n\n [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"surrealdb\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"surrealdb\",\n # The connection string for surrealdb.\n # connection_string=\"...\",\n\n # The username for surrealdb.\n # username=\"...\",\n\n # The password for surrealdb.\n # password=\"...\",\n\n # The namespace for surrealdb.\n # namespace=\"...\",\n\n # The database for surrealdb.\n # database=\"...\",\n\n # The table for surrealdb.\n # table=\"...\",\n\n # The key field for s [...]
+ }
+ ]
+ },
+ {
+ "name": "swift",
+ "scheme": "swift",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The endpoint for Swift."
+ },
+ {
+ "name": "container",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The container for Swift."
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The root for Swift."
+ },
+ {
+ "name": "token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The token for Swift."
+ },
+ {
+ "name": "temp_url_key",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The TempURL key for generating presigned URLs.\n\nThis corresponds to the `X-Account-Meta-Temp-URL-Key` or\n`X-Container-Meta-Temp-URL-Key` header value configured on the\nSwift account or container."
+ },
+ {
+ "name": "temp_url_hash_algorithm",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The hash algorithm for TempURL signing.\n\nSupported values: `sha1`, `sha256`, `sha512`. Defaults to `sha256`.\nThe cluster must have the chosen algorithm in its\n`tempurl.allowed_digests` (check `GET /info`)."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"swift\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"swift\", [\n // The endpoint for Swift.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // The container for Swift.\n // (\"container\".to_string(), \"...\".to_string()),\n\n // The root for Swift.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // The token for Swift.\n // (\"token\".to_string(), \"...\".to_string()),\n\n // The TempURL key for generating presigned URLs. [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"swift\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"swift\",\n # The endpoint for Swift.\n # endpoint=\"...\",\n\n # The container for Swift.\n # container=\"...\",\n\n # The root for Swift.\n # root=\"...\",\n\n # The token for Swift.\n # token=\"...\",\n\n # The TempURL key for generating presigned URLs.\n #\n # This corresponds to the `X-Account-Meta-Temp-URL-Key` or\n # `X-Container-Meta-Temp-URL-Key` header value configured on the\n [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"swift\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"swift\", {\n // The endpoint for Swift.\n // endpoint: \"...\",\n\n // The container for Swift.\n // container: \"...\",\n\n // The root for Swift.\n // root: \"...\",\n\n // The token for Swift.\n // token: \"...\",\n\n // The TempURL key for generating presigned URLs.\n //\n // This corresponds to the `X-Account-Meta-Temp-URL-Key` or\n // `X-Container-Meta-Temp-URL-Key` header value config [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"swift\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// The endpoint for Swift.\n// conf.put(\"endpoint\", \"...\");\n\n// The container for Swift.\n// conf.put(\"container\", \"...\");\n\n// The root for Swift.\n// conf.put(\"root\", \"...\");\n\n// The token for Swift.\n// conf.put(\"token\", \"...\");\n\n// The TempURL key for generating presigned URLs.\n//\n// This corresponds to the ` [...]
+ }
+ ]
+ },
+ {
+ "name": "tikv",
+ "scheme": "tikv",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "endpoints",
+ "type": "list",
+ "required": false,
+ "group": "General",
+ "comments": "network address of the TiKV service."
+ },
+ {
+ "name": "insecure",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "comments": "whether using insecure connection to TiKV"
+ },
+ {
+ "name": "ca_path",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "certificate authority file path"
+ },
+ {
+ "name": "cert_path",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "cert path"
+ },
+ {
+ "name": "key_path",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "key path"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"tikv\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"tikv\", [\n // network address of the TiKV service.\n // (\"endpoints\".to_string(), \"value1,value2\".to_string()),\n\n // whether using insecure connection to TiKV\n // (\"insecure\".to_string(), \"true\".to_string()),\n\n // certificate authority file path\n // (\"ca_path\".to_string(), \"...\".to_string()),\n\n // cert path\n // (\"cert_path\".to_string(), \"...\".to_string()),\n\n / [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"tikv\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"tikv\",\n # network address of the TiKV service.\n # endpoints=\"value1,value2\",\n\n # whether using insecure connection to TiKV\n # insecure=\"true\",\n\n # certificate authority file path\n # ca_path=\"...\",\n\n # cert path\n # cert_path=\"...\",\n\n # key path\n # key_path=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"tikv\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"tikv\", {\n // network address of the TiKV service.\n // endpoints: \"value1,value2\",\n\n // whether using insecure connection to TiKV\n // insecure: \"true\",\n\n // certificate authority file path\n // ca_path: \"...\",\n\n // cert path\n // cert_path: \"...\",\n\n // key path\n // key_path: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"tikv\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// network address of the TiKV service.\n// conf.put(\"endpoints\", \"value1,value2\");\n\n// whether using insecure connection to TiKV\n// conf.put(\"insecure\", \"true\");\n\n// certificate authority file path\n// conf.put(\"ca_path\", \"...\");\n\n// cert path\n// conf.put(\"cert_path\", \"...\");\n\n// key path\n// conf.put(\"key_pat [...]
+ }
+ ]
+ },
+ {
+ "name": "tos",
+ "scheme": "tos",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend.\n\nAll operations will happen under this root.\n\ndefault to `/` if not set."
+ },
+ {
+ "name": "bucket",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "bucket name of this backend.\n\nrequired."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "endpoint of this backend.\n\nEndpoint must be full uri, e.g.\n- TOS: `https://tos-cn-beijing.volces.com`\n- TOS with region: `https://tos-{region}.volces.com`\n\nIf user inputs endpoint without scheme like \"tos-cn-beijing.volces.com\", we\nwill prepend \"https://\" before it."
+ },
+ {
+ "name": "region",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Region represent the signing region of this endpoint.\n\nRequired if endpoint is not provided.\n\n- If region is set, we will take user's input first.\n- If not, we will try to load it from environment.\n- If still not set, default to `cn-beijing`."
+ },
+ {
+ "name": "access_key_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "access_key_id of this backend.\n\n- If access_key_id is set, we will take user's input first.\n- If not, we will try to load it from environment."
+ },
+ {
+ "name": "secret_access_key",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "secret_access_key of this backend.\n\n- If secret_access_key is set, we will take user's input first.\n- If not, we will try to load it from environment."
+ },
+ {
+ "name": "security_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "security_token of this backend.\n\nThis token will expire after sometime, it's recommended to set security_token\nby hand."
+ },
+ {
+ "name": "disable_config_load",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "comments": "Disable config load so that opendal will not load config from\nenvironment.\n\nFor examples:\n- envs like `TOS_ACCESS_KEY_ID`"
+ },
+ {
+ "name": "skip_signature",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "comments": "Skip signature will skip loading credentials and signing requests."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"tos\", [\n (\"bucket\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"tos\", [\n // root of this backend.\n //\n // All operations will happen under this root.\n //\n // default to `/` if not set.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // bucket name of this backend.\n //\n // required.\n (\"bucket\".to_string(), \"...\".to_string()),\n\n // endpoint of this backend.\n //\n // Endpoint must be full uri, e.g.\n // - TOS: `https [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"tos\",\n bucket=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"tos\",\n # root of this backend.\n #\n # All operations will happen under this root.\n #\n # default to `/` if not set.\n # root=\"...\",\n\n # bucket name of this backend.\n #\n # required.\n bucket=\"...\",\n\n # endpoint of this backend.\n #\n # Endpoint must be full uri, e.g.\n # - TOS: `https://tos-cn-beijing.volces.com`\n # - TOS with region: `https://tos-{region}.volces. [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"tos\", {\n bucket: \"...\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"tos\", {\n // root of this backend.\n //\n // All operations will happen under this root.\n //\n // default to `/` if not set.\n // root: \"...\",\n\n // bucket name of this backend.\n //\n // required.\n bucket: \"...\",\n\n // endpoint of this backend.\n //\n // Endpoint must be full uri, e.g.\n // - TOS: `https://tos-cn-beijing.volces.com`\n // - TOS with region: `https://tos-{region}. [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"bucket\", \"...\");\nOperator op = Operator.of(\"tos\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// root of this backend.\n//\n// All operations will happen under this root.\n//\n// default to `/` if not set.\n// conf.put(\"root\", \"...\");\n\n// bucket name of this backend.\n//\n// required.\nconf.put(\"bucket\", \"...\");\n\n// endpoint of this backend.\n//\n// Endpoint must be full uri, e.g.\n// - TOS: `https://tos-cn-beijing.vo [...]
+ }
+ ]
+ },
+ {
+ "name": "upyun",
+ "scheme": "upyun",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend.\n\nAll operations will happen under this root."
+ },
+ {
+ "name": "bucket",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "bucket address of this backend."
+ },
+ {
+ "name": "operator",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "username of this backend."
+ },
+ {
+ "name": "password",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "password of this backend."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"upyun\", [\n (\"bucket\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"upyun\", [\n // root of this backend.\n //\n // All operations will happen under this root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // bucket address of this backend.\n (\"bucket\".to_string(), \"...\".to_string()),\n\n // username of this backend.\n // (\"operator\".to_string(), \"...\".to_string()),\n\n // password of this backend.\n // (\"password\".to_string(), \"... [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"upyun\",\n bucket=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"upyun\",\n # root of this backend.\n #\n # All operations will happen under this root.\n # root=\"...\",\n\n # bucket address of this backend.\n bucket=\"...\",\n\n # username of this backend.\n # operator=\"...\",\n\n # password of this backend.\n # password=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"upyun\", {\n bucket: \"...\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"upyun\", {\n // root of this backend.\n //\n // All operations will happen under this root.\n // root: \"...\",\n\n // bucket address of this backend.\n bucket: \"...\",\n\n // username of this backend.\n // operator: \"...\",\n\n // password of this backend.\n // password: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"bucket\", \"...\");\nOperator op = Operator.of(\"upyun\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// root of this backend.\n//\n// All operations will happen under this root.\n// conf.put(\"root\", \"...\");\n\n// bucket address of this backend.\nconf.put(\"bucket\", \"...\");\n\n// username of this backend.\n// conf.put(\"operator\", \"...\");\n\n// password of this backend.\n// conf.put(\"password\", \"...\");\n\nOperator op = Oper [...]
+ }
+ ]
+ },
+ {
+ "name": "vercel-artifacts",
+ "scheme": "vercel-artifacts",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "access_token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The access token for Vercel."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The endpoint for the Vercel artifacts API.\n\nDefaults to `https://api.vercel.com`."
+ },
+ {
+ "name": "team_id",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The Vercel team ID. When set, the `teamId` query parameter\nis appended to all API requests."
+ },
+ {
+ "name": "team_slug",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The Vercel team slug. When set, the `slug` query parameter\nis appended to all API requests."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"vercel-artifacts\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"vercel-artifacts\", [\n // The access token for Vercel.\n // (\"access_token\".to_string(), \"...\".to_string()),\n\n // The endpoint for the Vercel artifacts API.\n //\n // Defaults to `https://api.vercel.com`.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // The Vercel team ID. When set, the `teamId` query parameter\n // is appended to all API requests.\n // (\"team_id\".to [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"vercel-artifacts\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"vercel-artifacts\",\n # The access token for Vercel.\n # access_token=\"...\",\n\n # The endpoint for the Vercel artifacts API.\n #\n # Defaults to `https://api.vercel.com`.\n # endpoint=\"...\",\n\n # The Vercel team ID. When set, the `teamId` query parameter\n # is appended to all API requests.\n # team_id=\"...\",\n\n # The Vercel team slug. When set, the `slug` query parameter\n # is a [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"vercel-artifacts\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"vercel-artifacts\", {\n // The access token for Vercel.\n // access_token: \"...\",\n\n // The endpoint for the Vercel artifacts API.\n //\n // Defaults to `https://api.vercel.com`.\n // endpoint: \"...\",\n\n // The Vercel team ID. When set, the `teamId` query parameter\n // is appended to all API requests.\n // team_id: \"...\",\n\n // The Vercel team slug. When set, the `slug` query paramet [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"vercel-artifacts\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// The access token for Vercel.\n// conf.put(\"access_token\", \"...\");\n\n// The endpoint for the Vercel artifacts API.\n//\n// Defaults to `https://api.vercel.com`.\n// conf.put(\"endpoint\", \"...\");\n\n// The Vercel team ID. When set, the `teamId` query parameter\n// is appended to all API requests.\n// conf.put(\"team_id\", \"...\ [...]
+ }
+ ]
+ },
+ {
+ "name": "vercel-blob",
+ "scheme": "vercel-blob",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend.\n\nAll operations will happen under this root."
+ },
+ {
+ "name": "token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "vercel blob token."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"vercel-blob\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"vercel-blob\", [\n // root of this backend.\n //\n // All operations will happen under this root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // vercel blob token.\n // (\"token\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"vercel-blob\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"vercel-blob\",\n # root of this backend.\n #\n # All operations will happen under this root.\n # root=\"...\",\n\n # vercel blob token.\n # token=\"...\",\n\n)"
+ }
+ ]
+ },
+ {
+ "name": "webdav",
+ "scheme": "webdav",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "endpoint of this backend"
+ },
+ {
+ "name": "username",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "username of this backend"
+ },
+ {
+ "name": "password",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "password of this backend"
+ },
+ {
+ "name": "token",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "token of this backend"
+ },
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend"
+ },
+ {
+ "name": "disable_copy",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "WebDAV copy capability is enabled by default and this option is no longer needed."
+ },
+ "comments": "Deprecated: WebDAV copy capability is enabled by default."
+ },
+ {
+ "name": "disable_create_dir",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "comments": "Disable automatic parent directory creation before write operations.\n\nBy default, OpenDAL creates parent directories using MKCOL before writing files.\nThis requires PROPFIND support to check directory existence.\n\nSome WebDAV-compatible servers (e.g., bazel-remote) don't support PROPFIND\nor don't require explicit directory creation. Enable this option to skip\nthe MKCOL calls and write files directly.\n\nDefault: false"
+ },
+ {
+ "name": "enable_user_metadata",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "deprecated": {
+ "since": "0.57.0",
+ "note": "WebDAV user metadata capability is enabled by default. Use CapabilityOverrideLayer to override write_with_user_metadata for endpoints without PROPPATCH support."
+ },
+ "comments": "Deprecated: WebDAV user metadata capability is enabled by default."
+ },
+ {
+ "name": "user_metadata_prefix",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The XML namespace prefix for user metadata properties.\n\nThis prefix is used in PROPPATCH/PROPFIND XML requests.\nDifferent servers may require different prefixes.\n\nDefault: \"opendal\""
+ },
+ {
+ "name": "user_metadata_uri",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "The XML namespace URI for user metadata properties.\n\nThis URI uniquely identifies the namespace for custom properties.\nDifferent servers may require different namespace URIs.\nFor example, Nextcloud might work better with its own namespace.\n\nDefault: `https://opendal.apache.org/ns`"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"webdav\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"webdav\", [\n // endpoint of this backend\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // username of this backend\n // (\"username\".to_string(), \"...\".to_string()),\n\n // password of this backend\n // (\"password\".to_string(), \"...\".to_string()),\n\n // token of this backend\n // (\"token\".to_string(), \"...\".to_string()),\n\n // root of this backend\n // (\"roo [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"webdav\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"webdav\",\n # endpoint of this backend\n # endpoint=\"...\",\n\n # username of this backend\n # username=\"...\",\n\n # password of this backend\n # password=\"...\",\n\n # token of this backend\n # token=\"...\",\n\n # root of this backend\n # root=\"...\",\n\n # Disable automatic parent directory creation before write operations.\n #\n # By default, OpenDAL creates parent directori [...]
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"webdav\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"webdav\", {\n // endpoint of this backend\n // endpoint: \"...\",\n\n // username of this backend\n // username: \"...\",\n\n // password of this backend\n // password: \"...\",\n\n // token of this backend\n // token: \"...\",\n\n // root of this backend\n // root: \"...\",\n\n // Disable automatic parent directory creation before write operations.\n //\n // By default, OpenDAL creates par [...]
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"webdav\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// endpoint of this backend\n// conf.put(\"endpoint\", \"...\");\n\n// username of this backend\n// conf.put(\"username\", \"...\");\n\n// password of this backend\n// conf.put(\"password\", \"...\");\n\n// token of this backend\n// conf.put(\"token\", \"...\");\n\n// root of this backend\n// conf.put(\"root\", \"...\");\n\n// Disable au [...]
+ }
+ ]
+ },
+ {
+ "name": "webhdfs",
+ "scheme": "webhdfs",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Root for webhdfs."
+ },
+ {
+ "name": "endpoint",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Endpoint for webhdfs."
+ },
+ {
+ "name": "user_name",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Name of the user for webhdfs."
+ },
+ {
+ "name": "delegation",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "Delegation token for webhdfs."
+ },
+ {
+ "name": "disable_list_batch",
+ "type": "bool",
+ "required": false,
+ "group": "General",
+ "comments": "Disable batch listing"
+ },
+ {
+ "name": "atomic_write_dir",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "atomic_write_dir of this backend"
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"webhdfs\", [\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"webhdfs\", [\n // Root for webhdfs.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // Endpoint for webhdfs.\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // Name of the user for webhdfs.\n // (\"user_name\".to_string(), \"...\".to_string()),\n\n // Delegation token for webhdfs.\n // (\"delegation\".to_string(), \"...\".to_string()),\n\n // Disable batch listing\n // [...]
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"webhdfs\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"webhdfs\",\n # Root for webhdfs.\n # root=\"...\",\n\n # Endpoint for webhdfs.\n # endpoint=\"...\",\n\n # Name of the user for webhdfs.\n # user_name=\"...\",\n\n # Delegation token for webhdfs.\n # delegation=\"...\",\n\n # Disable batch listing\n # disable_list_batch=\"true\",\n\n # atomic_write_dir of this backend\n # atomic_write_dir=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"webhdfs\", {\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"webhdfs\", {\n // Root for webhdfs.\n // root: \"...\",\n\n // Endpoint for webhdfs.\n // endpoint: \"...\",\n\n // Name of the user for webhdfs.\n // user_name: \"...\",\n\n // Delegation token for webhdfs.\n // delegation: \"...\",\n\n // Disable batch listing\n // disable_list_batch: \"true\",\n\n // atomic_write_dir of this backend\n // atomic_write_dir: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nOperator op = Operator.of(\"webhdfs\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// Root for webhdfs.\n// conf.put(\"root\", \"...\");\n\n// Endpoint for webhdfs.\n// conf.put(\"endpoint\", \"...\");\n\n// Name of the user for webhdfs.\n// conf.put(\"user_name\", \"...\");\n\n// Delegation token for webhdfs.\n// conf.put(\"delegation\", \"...\");\n\n// Disable batch listing\n// conf.put(\"disable_list_batch\", \"true [...]
+ }
+ ]
+ },
+ {
+ "name": "yandex-disk",
+ "scheme": "yandex-disk",
+ "groups": [
+ "General"
+ ],
+ "configs": [
+ {
+ "name": "root",
+ "type": "string",
+ "required": false,
+ "group": "General",
+ "comments": "root of this backend.\n\nAll operations will happen under this root."
+ },
+ {
+ "name": "access_token",
+ "type": "string",
+ "required": true,
+ "group": "General",
+ "comments": "yandex disk oauth access_token."
+ }
+ ],
+ "examples": [
+ {
+ "binding": "rust",
+ "language": "rust",
+ "minimal": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"yandex-disk\", [\n (\"access_token\".to_string(), \"...\".to_string()),\n])?;",
+ "full": "use opendal::Operator;\n\nlet op = Operator::via_iter(\"yandex-disk\", [\n // root of this backend.\n //\n // All operations will happen under this root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // yandex disk oauth access_token.\n (\"access_token\".to_string(), \"...\".to_string()),\n\n])?;"
+ },
+ {
+ "binding": "python",
+ "language": "python",
+ "minimal": "import opendal\n\nop = opendal.Operator(\n \"yandex-disk\",\n access_token=\"...\",\n)",
+ "full": "import opendal\n\nop = opendal.Operator(\n \"yandex-disk\",\n # root of this backend.\n #\n # All operations will happen under this root.\n # root=\"...\",\n\n # yandex disk oauth access_token.\n access_token=\"...\",\n\n)"
+ },
+ {
+ "binding": "nodejs",
+ "language": "javascript",
+ "minimal": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"yandex-disk\", {\n access_token: \"...\",\n});",
+ "full": "import { Operator } from \"opendal\";\n\nconst op = new Operator(\"yandex-disk\", {\n // root of this backend.\n //\n // All operations will happen under this root.\n // root: \"...\",\n\n // yandex disk oauth access_token.\n access_token: \"...\",\n\n});"
+ },
+ {
+ "binding": "java",
+ "language": "java",
+ "minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\nconf.put(\"access_token\", \"...\");\nOperator op = Operator.of(\"yandex-disk\", conf);",
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap<String, String> conf = new HashMap<>();\n// root of this backend.\n//\n// All operations will happen under this root.\n// conf.put(\"root\", \"...\");\n\n// yandex disk oauth access_token.\nconf.put(\"access_token\", \"...\");\n\nOperator op = Operator.of(\"yandex-disk\", conf);"
+ }
+ ]
+ }
+ ]
+}
diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js
index 72e659482..fdc2e33c4 100644
--- a/website/docusaurus.config.js
+++ b/website/docusaurus.config.js
@@ -162,6 +162,8 @@ const config = {
},
],
require.resolve("docusaurus-lunr-search"),
+ // Generates the /services section from data/services.json.
+ require.resolve("./plugins/services-docs-plugin"),
// This plugin will download all images to local and rewrite the url in html.
require.resolve("./plugins/image-ssr-plugin"),
[
@@ -302,6 +304,11 @@ const config = {
position: "right",
label: "Docs",
},
+ {
+ to: "/services",
+ label: "Services",
+ position: "right",
+ },
{
to: "/blog",
label: "Blog",
@@ -385,7 +392,7 @@ const config = {
prism: {
theme: themes.github,
darkTheme: themes.dracula,
- additionalLanguages: ["rust", "java", "groovy"],
+ additionalLanguages: ["rust", "java", "groovy", "python"],
},
zoom: {
selector: "img:not(a img)",
diff --git a/website/plugins/services-docs-plugin.js b/website/plugins/services-docs-plugin.js
new file mode 100644
index 000000000..416f1d44a
--- /dev/null
+++ b/website/plugins/services-docs-plugin.js
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// Generates the `/services` documentation section from `data/services.json`
+// (produced by `just generate docs`). Every service gets a page with language
+// tabs, and every supported (service, binding) pair gets a deep-linkable page
+// such as `/services/s3/python`. These routes are registered programmatically
+// so they stay out of the autogenerated docs sidebar while remaining real,
+// statically rendered URLs.
+
+const path = require("path");
+const fs = require("fs");
+
+// Join path segments under the site's baseUrl, collapsing duplicate slashes.
+// Avoids depending on @docusaurus/utils, which pnpm does not hoist to a place
+// resolvable from this plugin file.
+function joinUrl(parts) {
+ const joined = parts.join("/").replace(/\/{2,}/g, "/");
+ return joined.startsWith("/") ? joined : `/${joined}`;
+}
+
+module.exports = function servicesDocsPlugin(context) {
+ const { baseUrl } = context;
+
+ return {
+ name: "opendal-services-docs",
+
+ async loadContent() {
+ const dataPath = path.resolve(__dirname, "../data/services.json");
+ const raw = fs.readFileSync(dataPath, "utf8");
+ return JSON.parse(raw);
+ },
+
+ async contentLoaded({ content, actions }) {
+ const { createData, addRoute } = actions;
+ const { bindings, services } = content;
+
+ const indexComponent =
+ "@site/src/components/services/ServicesIndex.jsx";
+ const pageComponent = "@site/src/components/services/ServicePage.jsx";
+
+ // The index only needs a slim summary per service, not full snippets.
+ const summary = services.map((s) => ({
+ name: s.name,
+ scheme: s.scheme,
+ bindings: s.examples.map((e) => e.binding),
+ configCount: s.configs.length,
+ }));
+ const indexData = await createData(
+ "services-index.json",
+ JSON.stringify({ bindings, services: summary })
+ );
+ addRoute({
+ path: joinUrl([baseUrl, "services"]),
+ component: indexComponent,
+ modules: { data: indexData },
+ exact: true,
+ });
+
+ for (const service of services) {
+ const data = await createData(
+ `service-${service.scheme}.json`,
+ JSON.stringify({ bindings, service })
+ );
+ addRoute({
+ path: joinUrl([baseUrl, "services", service.scheme]),
+ component: pageComponent,
+ modules: { data },
+ exact: true,
+ });
+ for (const example of service.examples) {
+ addRoute({
+ path: joinUrl([
+ baseUrl,
+ "services",
+ service.scheme,
+ example.binding,
+ ]),
+ component: pageComponent,
+ modules: { data },
+ exact: true,
+ });
+ }
+ }
+ },
+ };
+};
diff --git a/website/src/components/services/ServicePage.jsx b/website/src/components/services/ServicePage.jsx
new file mode 100644
index 000000000..fc2e3b92f
--- /dev/null
+++ b/website/src/components/services/ServicePage.jsx
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useEffect, useState } from "react";
+import Layout from "@theme/Layout";
+import CodeBlock from "@theme/CodeBlock";
+import Link from "@docusaurus/Link";
+import { useLocation } from "@docusaurus/router";
+import styles from "./styles.module.css";
+
+// Renders inline `code` spans inside an otherwise plain doc comment so the
+// reference table stays readable without pulling in a full markdown renderer.
+function renderComment(text) {
+ if (!text) return null;
+ const parts = text.split(/(`[^`]+`)/g);
+ return parts.map((part, i) => {
+ if (part.startsWith("`") && part.endsWith("`") && part.length > 1) {
+ return <code key={i}>{part.slice(1, -1)}</code>;
+ }
+ return <span key={i}>{part}</span>;
+ });
+}
+
+// One group's worth of options, rendered as a table. Default/example values
+// (extracted from the config source) surface as chips next to the key.
+function ConfigTable({ rows }) {
+ return (
+ <div className={styles.tableWrap}>
+ <table className={styles.table}>
+ <thead>
+ <tr>
+ <th>Key</th>
+ <th>Type</th>
+ <th>Required</th>
+ <th>Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ {rows.map((c) => (
+ <tr key={c.name} className={c.deprecated ? styles.deprecatedRow : ""}>
+ <td>
+ <code>{c.name}</code>
+ {c.deprecated && <span className={styles.badge}>deprecated</span>}
+ {c.default != null && (
+ <span className={styles.chip}>
+ default <code>{c.default}</code>
+ </span>
+ )}
+ {c.default == null && c.example != null && (
+ <span className={styles.chip}>
+ e.g. <code>{c.example}</code>
+ </span>
+ )}
+ </td>
+ <td>{c.type}</td>
+ <td>{c.required ? "yes" : "no"}</td>
+ <td className={styles.desc}>
+ {renderComment(c.comments)}
+ {c.deprecated && c.deprecated.note && (
+ <div className={styles.deprecatedNote}>
+ Deprecated
+ {c.deprecated.since ? ` since ${c.deprecated.since}` : ""}:{" "}
+ {renderComment(c.deprecated.note)}
+ </div>
+ )}
+ </td>
+ </tr>
+ ))}
+ </tbody>
+ </table>
+ </div>
+ );
+}
+
+// The deep-link routes (`/services/<scheme>/<binding>`) share this component
+// with the bare service page; the trailing segment, when it names one of the
+// available bindings, selects the initial tab.
+function bindingFromPath(pathname, scheme, available) {
+ const segments = pathname.split("/").filter(Boolean);
+ const idx = segments.lastIndexOf(scheme);
+ const tail = idx >= 0 ? segments[idx + 1] : undefined;
+ return tail && available.includes(tail) ? tail : undefined;
+}
+
+export default function ServicePage({ data }) {
+ const { bindings, service } = data;
+ const location = useLocation();
+
+ const labelOf = Object.fromEntries(bindings.map((b) => [b.id, b.label]));
+ const available = service.examples.map((e) => e.binding);
+ const initial =
+ bindingFromPath(location.pathname, service.scheme, available) ||
+ available[0];
+
+ const [active, setActive] = useState(initial);
+ useEffect(() => {
+ setActive(initial);
+ // Re-sync when navigating between deep-link pages on the client.
+ }, [location.pathname]);
+
+ const example = service.examples.find((e) => e.binding === active);
+
+ const title = `${service.scheme} | Services`;
+ const description = `Configuration reference and copy-paste setup for the OpenDAL ${service.scheme} service.`;
+
+ return (
+ <Layout title={title} description={description}>
+ <div className={styles.page}>
+ <nav className={styles.breadcrumb} aria-label="Breadcrumb">
+ <Link to="/services">Services</Link>
+ <span aria-hidden="true"> / </span>
+ <span>{service.scheme}</span>
+ </nav>
+
+ <header className={styles.header}>
+ <h1 className={styles.title}>{service.scheme}</h1>
+ <p className={styles.subtitle}>
+ {service.configs.length} configuration option
+ {service.configs.length === 1 ? "" : "s"} · available in{" "}
+ {available.map((id) => labelOf[id] || id).join(", ")}
+ </p>
+ </header>
+
+ {example && (
+ <section className={styles.section}>
+ <div
+ className={styles.tabs}
+ role="tablist"
+ aria-label="Choose a binding"
+ >
+ {service.examples.map((e) => (
+ <button
+ key={e.binding}
+ type="button"
+ role="tab"
+ aria-selected={e.binding === active}
+ className={`${styles.tab} ${
+ e.binding === active ? styles.tabActive : ""
+ }`}
+ onClick={() => setActive(e.binding)}
+ >
+ {labelOf[e.binding] || e.binding}
+ </button>
+ ))}
+ </div>
+
+ <CodeBlock language={example.language} title="Quick start">
+ {example.minimal}
+ </CodeBlock>
+
+ <details className={styles.details}>
+ <summary>All configuration options (copy & trim)</summary>
+ <CodeBlock language={example.language} title="Full reference">
+ {example.full}
+ </CodeBlock>
+ </details>
+
+ <p className={styles.hint}>
+ Every option is passed as a string key; OpenDAL parses it into the
+ right type. Some services may require building the binding with the
+ matching <code>services-*</code> feature enabled.
+ </p>
+ </section>
+ )}
+
+ <section className={styles.section}>
+ <h2>Configuration reference</h2>
+ {service.configs.length === 0 ? (
+ <p>This service takes no configuration options.</p>
+ ) : (
+ (service.groups.length ? service.groups : ["General"]).map(
+ (group, i) => {
+ const rows = service.configs.filter(
+ (c) => (c.group || "General") === group
+ );
+ if (rows.length === 0) return null;
+ // First group expanded; later (advanced) groups collapsed so the
+ // page opens focused on the essentials.
+ return (
+ <details
+ key={group}
+ className={styles.group}
+ open={i === 0}
+ >
+ <summary className={styles.groupSummary}>
+ {group}
+ <span className={styles.groupCount}>{rows.length}</span>
+ </summary>
+ <ConfigTable rows={rows} />
+ </details>
+ );
+ }
+ )
+ )}
+ </section>
+ </div>
+ </Layout>
+ );
+}
diff --git a/website/src/components/services/ServicesIndex.jsx b/website/src/components/services/ServicesIndex.jsx
new file mode 100644
index 000000000..f8962599c
--- /dev/null
+++ b/website/src/components/services/ServicesIndex.jsx
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useMemo, useState } from "react";
+import Layout from "@theme/Layout";
+import Link from "@docusaurus/Link";
+import styles from "./styles.module.css";
+
+export default function ServicesIndex({ data }) {
+ const { services } = data;
+ const [query, setQuery] = useState("");
+
+ const filtered = useMemo(() => {
+ const q = query.trim().toLowerCase();
+ const list = q
+ ? services.filter((s) => s.scheme.includes(q) || s.name.includes(q))
+ : services;
+ return [...list].sort((a, b) => a.scheme.localeCompare(b.scheme));
+ }, [services, query]);
+
+ return (
+ <Layout
+ title="Services"
+ description="Browse every storage service OpenDAL supports, with a copy-paste configuration reference for each binding."
+ >
+ <div className={styles.page}>
+ <header className={styles.header}>
+ <h1 className={styles.title}>Services</h1>
+ <p className={styles.subtitle}>
+ Every storage service OpenDAL supports. Open one for its full
+ configuration reference and ready-to-copy setup code in each binding.
+ </p>
+ </header>
+
+ <input
+ type="search"
+ className={styles.search}
+ placeholder={`Filter ${services.length} services…`}
+ value={query}
+ onChange={(e) => setQuery(e.target.value)}
+ aria-label="Filter services"
+ />
+
+ {filtered.length === 0 ? (
+ <p>No service matches “{query}”.</p>
+ ) : (
+ <ul className={styles.grid}>
+ {filtered.map((s) => (
+ <li key={s.scheme}>
+ <Link to={`/services/${s.scheme}`} className={styles.card}>
+ <span className={styles.cardName}>{s.scheme}</span>
+ <span className={styles.cardMeta}>
+ {s.configCount} option{s.configCount === 1 ? "" : "s"}
+ </span>
+ </Link>
+ </li>
+ ))}
+ </ul>
+ )}
+ </div>
+ </Layout>
+ );
+}
diff --git a/website/src/components/services/styles.module.css b/website/src/components/services/styles.module.css
new file mode 100644
index 000000000..c7fa95fc3
--- /dev/null
+++ b/website/src/components/services/styles.module.css
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+.page {
+ max-width: 960px;
+ margin: 0 auto;
+ padding: 2.5rem 1rem 4rem;
+}
+
+.breadcrumb {
+ font-size: 0.9rem;
+ color: var(--ifm-color-emphasis-600);
+ margin-bottom: 1rem;
+}
+
+.header {
+ margin-bottom: 2rem;
+}
+
+.title {
+ font-family: var(--ifm-font-family-monospace);
+ margin-bottom: 0.5rem;
+ word-break: break-word;
+}
+
+.subtitle {
+ color: var(--ifm-color-emphasis-700);
+ margin: 0;
+}
+
+.search {
+ width: 100%;
+ padding: 0.7rem 1rem;
+ font-size: 1rem;
+ border: 1px solid var(--ifm-color-emphasis-300);
+ border-radius: var(--ifm-global-radius);
+ background: var(--ifm-background-color);
+ color: var(--ifm-font-color-base);
+ margin-bottom: 2rem;
+}
+
+.search:focus {
+ outline: none;
+ border-color: var(--ifm-color-primary);
+}
+
+.grid {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+ gap: 1rem;
+}
+
+.card {
+ display: flex;
+ flex-direction: column;
+ gap: 0.35rem;
+ height: 100%;
+ padding: 1rem 1.1rem;
+ border: 1px solid var(--ifm-color-emphasis-200);
+ border-radius: var(--ifm-global-radius);
+ background: var(--ifm-card-background-color, var(--ifm-background-surface-color));
+ transition:
+ border-color 0.15s ease,
+ transform 0.15s ease,
+ box-shadow 0.15s ease;
+}
+
+.card:hover {
+ text-decoration: none;
+ border-color: var(--ifm-color-primary);
+ transform: translateY(-2px);
+ box-shadow: var(--ifm-global-shadow-lw);
+}
+
+.cardName {
+ font-family: var(--ifm-font-family-monospace);
+ font-size: 1.1rem;
+ font-weight: 600;
+ color: var(--ifm-heading-color);
+ word-break: break-word;
+}
+
+.cardMeta {
+ font-size: 0.85rem;
+ color: var(--ifm-color-emphasis-600);
+}
+
+.section {
+ margin-top: 2.5rem;
+}
+
+.tabs {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.25rem;
+ margin-bottom: 1rem;
+ border-bottom: 1px solid var(--ifm-color-emphasis-200);
+}
+
+.tab {
+ appearance: none;
+ background: transparent;
+ border: none;
+ border-bottom: 2px solid transparent;
+ padding: 0.5rem 0.9rem;
+ font-size: 0.95rem;
+ font-weight: 500;
+ color: var(--ifm-color-emphasis-600);
+ cursor: pointer;
+}
+
+.tab:hover {
+ color: var(--ifm-color-primary);
+}
+
+.tabActive {
+ color: var(--ifm-color-primary);
+ border-bottom-color: var(--ifm-color-primary);
+}
+
+.details {
+ margin-top: 0.5rem;
+}
+
+.details > summary {
+ cursor: pointer;
+ font-weight: 500;
+ padding: 0.5rem 0;
+ color: var(--ifm-color-emphasis-700);
+}
+
+.hint {
+ margin-top: 1rem;
+ font-size: 0.85rem;
+ color: var(--ifm-color-emphasis-600);
+}
+
+.group {
+ border: 1px solid var(--ifm-color-emphasis-200);
+ border-radius: var(--ifm-global-radius);
+ margin-bottom: 0.75rem;
+ overflow: hidden;
+}
+
+.groupSummary {
+ cursor: pointer;
+ font-weight: 600;
+ padding: 0.7rem 1rem;
+ background: var(--ifm-color-emphasis-100);
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.groupCount {
+ font-size: 0.75rem;
+ font-weight: 500;
+ color: var(--ifm-color-emphasis-600);
+ background: var(--ifm-background-color);
+ border: 1px solid var(--ifm-color-emphasis-300);
+ border-radius: 999px;
+ padding: 0 0.5rem;
+}
+
+.chip {
+ display: inline-block;
+ margin-left: 0.4rem;
+ padding: 0.05rem 0.4rem;
+ font-size: 0.72rem;
+ border-radius: var(--ifm-global-radius);
+ background: var(--ifm-color-emphasis-100);
+ color: var(--ifm-color-emphasis-700);
+ white-space: nowrap;
+}
+
+.chip code {
+ font-size: 0.72rem;
+ background: transparent;
+ border: none;
+ padding: 0;
+}
+
+.tableWrap {
+ overflow-x: auto;
+}
+
+.table {
+ width: 100%;
+ display: table;
+ border-collapse: collapse;
+}
+
+.table th,
+.table td {
+ text-align: left;
+ vertical-align: top;
+ padding: 0.6rem 0.75rem;
+ border-bottom: 1px solid var(--ifm-color-emphasis-200);
+}
+
+.table th {
+ font-size: 0.8rem;
+ text-transform: uppercase;
+ letter-spacing: 0.03em;
+ color: var(--ifm-color-emphasis-600);
+}
+
+.desc {
+ white-space: pre-wrap;
+ font-size: 0.9rem;
+ color: var(--ifm-color-emphasis-800);
+}
+
+.deprecatedRow code {
+ text-decoration: line-through;
+}
+
+.badge {
+ display: inline-block;
+ margin-left: 0.4rem;
+ padding: 0.05rem 0.4rem;
+ font-size: 0.7rem;
+ border-radius: var(--ifm-global-radius);
+ background: var(--ifm-color-warning-contrast-background);
+ color: var(--ifm-color-warning-darkest);
+}
+
+.deprecatedNote {
+ margin-top: 0.35rem;
+ font-size: 0.8rem;
+ color: var(--ifm-color-warning-darkest);
+}