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 0e41a17e0 refactor: Supabase is now an S3-compatible servcices (#5663)
0e41a17e0 is described below

commit 0e41a17e0b5535a67d7e89bca7d6cba142c1fffe
Author: Xuanwo <[email protected]>
AuthorDate: Wed Feb 26 15:26:23 2025 +0800

    refactor: Supabase is now an S3-compatible servcices (#5663)
    
    * refactor: Supabase is now an S3-compatible servcices
    
    Signed-off-by: Xuanwo <[email protected]>
    
    * Remove supabase
    
    Signed-off-by: Xuanwo <[email protected]>
    
    ---------
    
    Signed-off-by: Xuanwo <[email protected]>
---
 .env.example                                       |   4 -
 .github/workflows/ci_core.yml                      |   1 -
 bindings/c/include/opendal.h                       |   2 +-
 bindings/c/src/operator.rs                         |   2 +-
 bindings/java/Cargo.toml                           |   2 -
 .../java/org/apache/opendal/ServiceConfig.java     |  46 ----
 bindings/lua/src/operator_doc.lua                  |  10 +-
 bindings/nodejs/Cargo.toml                         |   2 -
 bindings/python/Cargo.toml                         |   2 -
 bindings/python/python/opendal/__base.pyi          |  12 -
 core/Cargo.toml                                    |   1 -
 core/fuzz/Cargo.toml                               |   1 -
 core/src/services/mod.rs                           |   3 -
 core/src/services/supabase/backend.rs              | 219 ------------------
 core/src/services/supabase/config.rs               |  50 -----
 core/src/services/supabase/core.rs                 | 244 ---------------------
 core/src/services/supabase/docs.md                 |  51 -----
 core/src/services/supabase/error.rs                |  82 -------
 core/src/services/supabase/mod.rs                  |  31 ---
 core/src/services/supabase/writer.rs               |  62 ------
 core/src/types/operator/builder.rs                 |   2 -
 core/src/types/scheme.rs                           |   6 -
 core/tests/behavior/async_delete.rs                |   5 -
 core/tests/behavior/async_read.rs                  |   5 -
 core/tests/behavior/async_stat.rs                  |   5 -
 core/tests/behavior/async_write.rs                 |   5 -
 core/tests/behavior/blocking_stat.rs               |   5 -
 core/tests/behavior/blocking_write.rs              |   5 -
 28 files changed, 7 insertions(+), 858 deletions(-)

diff --git a/.env.example b/.env.example
index 934c0f061..814ab27a3 100644
--- a/.env.example
+++ b/.env.example
@@ -79,10 +79,6 @@ OPENDAL_WEBHDFS_ENDPOINT=http://127.0.0.1:9870
 OPENDAL_WEBHDFS_DELEGATION=<delegation>
 OPENDAL_WEBHDFS_ATOMIC_WRITE_DIR=.opendal_tmp/
 OPENDAL_WEBHDFS_DISABLE_LIST_BATCH=false
-# supbase
-OPENDAL_SUPABASE_BUCKET=<bucket>
-OPENDAL_SUPABASE_ENDPOINT=<endpoint>
-OPENDAL_SUPABASE_KEY=<service_key>
 # vercel artifacts
 OPENDAL_VERCEL_ARTIFACTS_ACCESS_TOKEN=<token>
 # onedrive
diff --git a/.github/workflows/ci_core.yml b/.github/workflows/ci_core.yml
index 0d0137309..323dcc246 100644
--- a/.github/workflows/ci_core.yml
+++ b/.github/workflows/ci_core.yml
@@ -207,7 +207,6 @@ jobs:
             # services-sftp
             services-sled
             services-swift
-            services-supabase
             services-tikv
             services-vercel-artifacts
             services-webdav
diff --git a/bindings/c/include/opendal.h b/bindings/c/include/opendal.h
index 2597edbdb..53bc1b0e7 100644
--- a/bindings/c/include/opendal.h
+++ b/bindings/c/include/opendal.h
@@ -735,7 +735,7 @@ void opendal_operator_free(const struct opendal_operator 
*ptr);
  * reference the 
[documentation](https://opendal.apache.org/docs/category/services/) for
  * each service, especially for the **Configuration Part**.
  *
- * @param scheme the service scheme you want to specify, e.g. "fs", "s3", 
"supabase"
+ * @param scheme the service scheme you want to specify, e.g. "fs", "s3"
  * @param options the pointer to the options for this operator, it could be 
NULL, which means no
  * option is set
  * @see opendal_operator_options
diff --git a/bindings/c/src/operator.rs b/bindings/c/src/operator.rs
index 3aa8b2e2a..c2fb30b2d 100644
--- a/bindings/c/src/operator.rs
+++ b/bindings/c/src/operator.rs
@@ -108,7 +108,7 @@ fn build_operator(
 /// reference the 
[documentation](https://opendal.apache.org/docs/category/services/) for
 /// each service, especially for the **Configuration Part**.
 ///
-/// @param scheme the service scheme you want to specify, e.g. "fs", "s3", 
"supabase"
+/// @param scheme the service scheme you want to specify, e.g. "fs", "s3"
 /// @param options the pointer to the options for this operator, it could be 
NULL, which means no
 /// option is set
 /// @see opendal_operator_options
diff --git a/bindings/java/Cargo.toml b/bindings/java/Cargo.toml
index 817ddc18c..0f2d6b7ce 100644
--- a/bindings/java/Cargo.toml
+++ b/bindings/java/Cargo.toml
@@ -78,7 +78,6 @@ services-all = [
   # FIXME: rocksdb will lead to "cannot allocate memory in static TLS block" 
while linking.
   # "services-rocksdb",
   "services-sled",
-  "services-supabase",
   "services-tikv",
   "services-vercel-artifacts",
   "services-mongodb",
@@ -143,7 +142,6 @@ services-seafile = ["opendal/services-seafile"]
 services-sftp = ["opendal/services-sftp"]
 services-sled = ["opendal/services-sled"]
 services-sqlite = ["opendal/services-sqlite"]
-services-supabase = ["opendal/services-supabase"]
 services-swift = ["opendal/services-swift"]
 services-tikv = ["opendal/services-tikv"]
 services-upyun = ["opendal/services-upyun"]
diff --git a/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java 
b/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java
index d609e3778..e1f092105 100644
--- a/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java
+++ b/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java
@@ -3192,52 +3192,6 @@ public interface ServiceConfig {
         }
     }
 
-    /**
-     * Configuration for service supabase.
-     */
-    @Builder
-    @Data
-    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
-    class Supabase implements ServiceConfig {
-        /**
-         * <p>The bucket for supabase service.</p>
-         */
-        public final @NonNull String bucket;
-        /**
-         * <p>The root for supabase service.</p>
-         */
-        public final String root;
-        /**
-         * <p>The endpoint for supabase service.</p>
-         */
-        public final String endpoint;
-        /**
-         * <p>The key for supabase service.</p>
-         */
-        public final String key;
-
-        @Override
-        public String scheme() {
-            return "supabase";
-        }
-
-        @Override
-        public Map<String, String> configMap() {
-            final HashMap<String, String> map = new HashMap<>();
-            map.put("bucket", bucket);
-            if (root != null) {
-                map.put("root", root);
-            }
-            if (endpoint != null) {
-                map.put("endpoint", endpoint);
-            }
-            if (key != null) {
-                map.put("key", key);
-            }
-            return map;
-        }
-    }
-
     /**
      * Configuration for service surrealdb.
      */
diff --git a/bindings/lua/src/operator_doc.lua 
b/bindings/lua/src/operator_doc.lua
index d3ee1413f..01bd90894 100644
--- a/bindings/lua/src/operator_doc.lua
+++ b/bindings/lua/src/operator_doc.lua
@@ -25,24 +25,24 @@
 
 local _M = {}
 
---- Construct an operator based on scheme and option. Uses an table of 
key-value pairs to initialize 
---- the operator based on provided scheme and options. For each scheme, i.e. 
Backend, 
+--- Construct an operator based on scheme and option. Uses an table of 
key-value pairs to initialize
+--- the operator based on provided scheme and options. For each scheme, i.e. 
Backend,
 --- different options could be set, you may  reference the 
https://opendal.apache.org/docs/category/services/
 --- for each service, especially for the **Configuration Part**.
--- @param string scheme the service scheme you want to specify, e.g. "fs", 
"s3", "supabase"
+-- @param string scheme the service scheme you want to specify, e.g. "fs", "s3"
 -- @param table options the table to the options for this operators
 -- @return table, error  opendal operator table which contain opendal operator 
instance, error nil if success, others otherwise
 -- @function new
 
 
---- Blockingly write raw bytes to path. 
+--- Blockingly write raw bytes to path.
 ---  Write the bytes into the path blockingly, returns nil if success, others 
otherwise
 -- @param string path the designated path you want to write your bytes in
 -- @param string bytes the bytes to be written
 -- @return error nil if success, otherwise error message
 -- @function write
 
---- Blockingly read raw bytes from path. 
+--- Blockingly read raw bytes from path.
 ---  Read the data out from `path` blockingly by operator, returns the string 
if success, others otherwise
 -- @param string path the designated path you want to write your bytes in
 -- @return string, error read data, error nil if success, otherwise error 
message
diff --git a/bindings/nodejs/Cargo.toml b/bindings/nodejs/Cargo.toml
index 46557e33b..0b0482dfb 100644
--- a/bindings/nodejs/Cargo.toml
+++ b/bindings/nodejs/Cargo.toml
@@ -75,7 +75,6 @@ services-all = [
   # FIXME how to support rocksdb services in bindings?
   # "services-rocksdb",
   "services-sled",
-  "services-supabase",
   "services-swift",
   # FIXME this service need protoc
   # "services-tikv",
@@ -141,7 +140,6 @@ services-seafile = ["opendal/services-seafile"]
 services-sftp = ["opendal/services-sftp"]
 services-sled = ["opendal/services-sled"]
 services-sqlite = ["opendal/services-sqlite"]
-services-supabase = ["opendal/services-supabase"]
 services-swift = ["opendal/services-swift"]
 services-tikv = ["opendal/services-tikv"]
 services-upyun = ["opendal/services-upyun"]
diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml
index b0afb08ee..3d73acf50 100644
--- a/bindings/python/Cargo.toml
+++ b/bindings/python/Cargo.toml
@@ -78,7 +78,6 @@ services-all = [
   # FIXME how to support rocksdb services in bindings?
   # "services-rocksdb",
   "services-sled",
-  "services-supabase",
   "services-swift",
   # FIXME this service need protoc
   # "services-tikv",
@@ -144,7 +143,6 @@ services-seafile = ["opendal/services-seafile"]
 services-sftp = ["opendal/services-sftp"]
 services-sled = ["opendal/services-sled"]
 services-sqlite = ["opendal/services-sqlite"]
-services-supabase = ["opendal/services-supabase"]
 services-swift = ["opendal/services-swift"]
 services-tikv = ["opendal/services-tikv"]
 services-upyun = ["opendal/services-upyun"]
diff --git a/bindings/python/python/opendal/__base.pyi 
b/bindings/python/python/opendal/__base.pyi
index 680420f68..5bce6711c 100644
--- a/bindings/python/python/opendal/__base.pyi
+++ b/bindings/python/python/opendal/__base.pyi
@@ -717,18 +717,6 @@ class _Base:
         root: str = ...,
     ) -> None: ...
 
-    @overload
-    def __init__(
-        self,
-        scheme: Literal["supabase"],
-        /,
-        *,
-        bucket: str,
-        root: str = ...,
-        endpoint: str = ...,
-        key: str = ...,
-    ) -> None: ...
-
     @overload
     def __init__(
         self,
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 0c7cf270d..5e279d58e 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -196,7 +196,6 @@ services-seafile = []
 services-sftp = ["dep:openssh", "dep:openssh-sftp-client", "dep:bb8"]
 services-sled = ["dep:sled", "internal-tokio-rt"]
 services-sqlite = ["dep:sqlx", "sqlx?/sqlite", "dep:ouroboros"]
-services-supabase = []
 services-surrealdb = ["dep:surrealdb"]
 services-swift = []
 services-tikv = ["tikv-client"]
diff --git a/core/fuzz/Cargo.toml b/core/fuzz/Cargo.toml
index 2600c0ba4..b5f342cc4 100644
--- a/core/fuzz/Cargo.toml
+++ b/core/fuzz/Cargo.toml
@@ -68,7 +68,6 @@ services-seafile = ["opendal/services-seafile"]
 services-sftp = ["opendal/services-sftp"]
 services-sled = ["opendal/services-sled"]
 services-sqlite = ["opendal/services-sqlite"]
-services-supabase = ["opendal/services-supabase"]
 services-swift = ["opendal/services-swift"]
 services-tikv = ["opendal/services-tikv"]
 services-upyun = ["opendal/services-upyun"]
diff --git a/core/src/services/mod.rs b/core/src/services/mod.rs
index a84bb2097..c9a98ea4f 100644
--- a/core/src/services/mod.rs
+++ b/core/src/services/mod.rs
@@ -187,9 +187,6 @@ pub use self::sled::*;
 mod sqlite;
 pub use self::sqlite::*;
 
-mod supabase;
-pub use supabase::*;
-
 mod surrealdb;
 pub use surrealdb::*;
 
diff --git a/core/src/services/supabase/backend.rs 
b/core/src/services/supabase/backend.rs
deleted file mode 100644
index a9c13fdd0..000000000
--- a/core/src/services/supabase/backend.rs
+++ /dev/null
@@ -1,219 +0,0 @@
-// 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.
-
-use std::fmt::Debug;
-use std::fmt::Formatter;
-use std::sync::Arc;
-
-use http::Response;
-use http::StatusCode;
-use log::debug;
-
-use super::core::*;
-use super::error::parse_error;
-use super::writer::*;
-use crate::raw::*;
-use crate::services::SupabaseConfig;
-use crate::*;
-
-impl Configurator for SupabaseConfig {
-    type Builder = SupabaseBuilder;
-    fn into_builder(self) -> Self::Builder {
-        SupabaseBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
-
-/// [Supabase](https://supabase.com/) service support
-#[doc = include_str!("docs.md")]
-#[derive(Default)]
-pub struct SupabaseBuilder {
-    config: SupabaseConfig,
-    http_client: Option<HttpClient>,
-}
-
-impl Debug for SupabaseBuilder {
-    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-        let mut d = f.debug_struct("SupabaseBuilder");
-        d.field("config", &self.config);
-        d.finish_non_exhaustive()
-    }
-}
-
-impl SupabaseBuilder {
-    /// Set root of this backend.
-    ///
-    /// All operations will happen under this root.
-    pub fn root(mut self, root: &str) -> Self {
-        self.config.root = if root.is_empty() {
-            None
-        } else {
-            Some(root.to_string())
-        };
-
-        self
-    }
-
-    /// Set bucket name of this backend.
-    pub fn bucket(mut self, bucket: &str) -> Self {
-        self.config.bucket = bucket.to_string();
-        self
-    }
-
-    /// Set endpoint of this backend.
-    ///
-    /// Endpoint must be full uri
-    pub fn endpoint(mut self, endpoint: &str) -> Self {
-        self.config.endpoint = if endpoint.is_empty() {
-            None
-        } else {
-            Some(endpoint.trim_end_matches('/').to_string())
-        };
-
-        self
-    }
-
-    /// Set the authorization key for this backend
-    /// Do not set this key if you want to read public bucket
-    pub fn key(mut self, key: &str) -> Self {
-        self.config.key = Some(key.to_string());
-        self
-    }
-
-    /// Specify the http client that used by this service.
-    ///
-    /// # Notes
-    ///
-    /// This API is part of OpenDAL's Raw API. `HttpClient` could be changed
-    /// during minor updates.
-    pub fn http_client(mut self, client: HttpClient) -> Self {
-        self.http_client = Some(client);
-        self
-    }
-}
-
-impl Builder for SupabaseBuilder {
-    const SCHEME: Scheme = Scheme::Supabase;
-    type Config = SupabaseConfig;
-
-    fn build(self) -> Result<impl Access> {
-        let root = normalize_root(&self.config.root.unwrap_or_default());
-        debug!("backend use root {}", &root);
-
-        let bucket = &self.config.bucket;
-
-        let endpoint = self.config.endpoint.unwrap_or_default();
-
-        let http_client = if let Some(client) = self.http_client {
-            client
-        } else {
-            HttpClient::new().map_err(|err| {
-                err.with_operation("Builder::build")
-                    .with_context("service", Scheme::Supabase)
-            })?
-        };
-
-        let key = self.config.key.as_ref().map(|k| k.to_owned());
-
-        let core = SupabaseCore::new(&root, bucket, &endpoint, key, 
http_client);
-
-        let core = Arc::new(core);
-
-        Ok(SupabaseBackend { core })
-    }
-}
-
-#[derive(Debug)]
-pub struct SupabaseBackend {
-    core: Arc<SupabaseCore>,
-}
-
-impl Access for SupabaseBackend {
-    type Reader = HttpBody;
-    type Writer = oio::OneShotWriter<SupabaseWriter>;
-    // todo: implement Lister to support list
-    type Lister = ();
-    type Deleter = ();
-    type BlockingReader = ();
-    type BlockingWriter = ();
-    type BlockingLister = ();
-    type BlockingDeleter = ();
-
-    fn info(&self) -> Arc<AccessorInfo> {
-        let am = AccessorInfo::default();
-        am.set_scheme(Scheme::Supabase)
-            .set_root(&self.core.root)
-            .set_name(&self.core.bucket)
-            .set_native_capability(Capability {
-                stat: true,
-
-                read: true,
-
-                write: true,
-
-                shared: true,
-
-                ..Default::default()
-            });
-
-        am.into()
-    }
-
-    async fn stat(&self, path: &str, _args: OpStat) -> Result<RpStat> {
-        // The get_object_info does not contain the file size. Therefore
-        // we first try the get the metadata through head, if we fail,
-        // we then use get_object_info to get the actual error info
-        let mut resp = self.core.supabase_head_object(path).await?;
-
-        match resp.status() {
-            StatusCode::OK => parse_into_metadata(path, 
resp.headers()).map(RpStat::new),
-            _ => {
-                resp = self.core.supabase_get_object_info(path).await?;
-                match resp.status() {
-                    StatusCode::NOT_FOUND if path.ends_with('/') => {
-                        Ok(RpStat::new(Metadata::new(EntryMode::DIR)))
-                    }
-                    _ => Err(parse_error(resp)),
-                }
-            }
-        }
-    }
-
-    async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, 
Self::Reader)> {
-        let resp = self.core.supabase_get_object(path, args.range()).await?;
-
-        let status = resp.status();
-
-        match status {
-            StatusCode::OK | StatusCode::PARTIAL_CONTENT => Ok((RpRead::new(), 
resp.into_body())),
-            _ => {
-                let (part, mut body) = resp.into_parts();
-                let buf = body.to_buffer().await?;
-                Err(parse_error(Response::from_parts(part, buf)))
-            }
-        }
-    }
-
-    async fn write(&self, path: &str, args: OpWrite) -> Result<(RpWrite, 
Self::Writer)> {
-        Ok((
-            RpWrite::default(),
-            oio::OneShotWriter::new(SupabaseWriter::new(self.core.clone(), 
path, args)),
-        ))
-    }
-}
diff --git a/core/src/services/supabase/config.rs 
b/core/src/services/supabase/config.rs
deleted file mode 100644
index 83c26cd7a..000000000
--- a/core/src/services/supabase/config.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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.
-
-use std::fmt::Debug;
-use std::fmt::Formatter;
-
-use serde::Deserialize;
-use serde::Serialize;
-
-/// Config for supabase service support.
-#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
-#[serde(default)]
-#[non_exhaustive]
-pub struct SupabaseConfig {
-    /// The root for supabase service.
-    pub root: Option<String>,
-    /// The bucket for supabase service.
-    pub bucket: String,
-    /// The endpoint for supabase service.
-    pub endpoint: Option<String>,
-    /// The key for supabase service.
-    pub key: Option<String>,
-    // TODO(1) optional public, currently true always
-    // TODO(2) optional file_size_limit, currently 0
-    // TODO(3) optional allowed_mime_types, currently only string
-}
-
-impl Debug for SupabaseConfig {
-    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-        f.debug_struct("SupabaseConfig")
-            .field("root", &self.root)
-            .field("bucket", &self.bucket)
-            .field("endpoint", &self.endpoint)
-            .finish_non_exhaustive()
-    }
-}
diff --git a/core/src/services/supabase/core.rs 
b/core/src/services/supabase/core.rs
deleted file mode 100644
index 578a8b5f3..000000000
--- a/core/src/services/supabase/core.rs
+++ /dev/null
@@ -1,244 +0,0 @@
-// 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.
-
-use std::fmt::Debug;
-
-use http::header::CONTENT_LENGTH;
-use http::header::CONTENT_TYPE;
-use http::HeaderValue;
-use http::Request;
-use http::Response;
-
-use crate::raw::*;
-use crate::*;
-
-pub struct SupabaseCore {
-    pub root: String,
-    pub bucket: String,
-    pub endpoint: String,
-
-    /// The key used for authorization
-    /// If loaded, the read operation will always access the nonpublic 
resources.
-    /// If you want to read the public resources, please do not set the key.
-    pub key: Option<String>,
-
-    pub http_client: HttpClient,
-}
-
-impl Debug for SupabaseCore {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.debug_struct("SupabaseCore")
-            .field("root", &self.root)
-            .field("bucket", &self.bucket)
-            .field("endpoint", &self.endpoint)
-            .finish_non_exhaustive()
-    }
-}
-
-impl SupabaseCore {
-    pub fn new(
-        root: &str,
-        bucket: &str,
-        endpoint: &str,
-        key: Option<String>,
-        client: HttpClient,
-    ) -> Self {
-        Self {
-            root: root.to_string(),
-            bucket: bucket.to_string(),
-            endpoint: endpoint.to_string(),
-            key,
-            http_client: client,
-        }
-    }
-
-    /// Add authorization header to the request if the key is set. Otherwise 
leave
-    /// the request as-is.
-    pub fn sign<T>(&self, req: &mut Request<T>) -> Result<()> {
-        if let Some(k) = &self.key {
-            let v = HeaderValue::from_str(&format!("Bearer {}", k)).unwrap();
-            req.headers_mut().insert(http::header::AUTHORIZATION, v);
-        }
-        Ok(())
-    }
-}
-
-// requests
-impl SupabaseCore {
-    pub fn supabase_upload_object_request(
-        &self,
-        path: &str,
-        size: Option<usize>,
-        content_type: Option<&str>,
-        body: Buffer,
-    ) -> Result<Request<Buffer>> {
-        let p = build_abs_path(&self.root, path);
-        let url = format!(
-            "{}/storage/v1/object/{}/{}",
-            self.endpoint,
-            self.bucket,
-            percent_encode_path(&p)
-        );
-
-        let mut req = Request::post(&url);
-
-        if let Some(size) = size {
-            req = req.header(CONTENT_LENGTH, size)
-        }
-
-        if let Some(mime) = content_type {
-            req = req.header(CONTENT_TYPE, mime)
-        }
-
-        let req = req.body(body).map_err(new_request_build_error)?;
-
-        Ok(req)
-    }
-
-    pub fn supabase_get_object_public_request(
-        &self,
-        path: &str,
-        _: BytesRange,
-    ) -> Result<Request<Buffer>> {
-        let p = build_abs_path(&self.root, path);
-        let url = format!(
-            "{}/storage/v1/object/public/{}/{}",
-            self.endpoint,
-            self.bucket,
-            percent_encode_path(&p)
-        );
-
-        let req = Request::get(&url);
-
-        req.body(Buffer::new()).map_err(new_request_build_error)
-    }
-
-    pub fn supabase_get_object_auth_request(
-        &self,
-        path: &str,
-        _: BytesRange,
-    ) -> Result<Request<Buffer>> {
-        let p = build_abs_path(&self.root, path);
-        let url = format!(
-            "{}/storage/v1/object/authenticated/{}/{}",
-            self.endpoint,
-            self.bucket,
-            percent_encode_path(&p)
-        );
-
-        let req = Request::get(&url);
-
-        req.body(Buffer::new()).map_err(new_request_build_error)
-    }
-
-    pub fn supabase_head_object_public_request(&self, path: &str) -> 
Result<Request<Buffer>> {
-        let p = build_abs_path(&self.root, path);
-        let url = format!(
-            "{}/storage/v1/object/public/{}/{}",
-            self.endpoint,
-            self.bucket,
-            percent_encode_path(&p)
-        );
-
-        Request::head(&url)
-            .body(Buffer::new())
-            .map_err(new_request_build_error)
-    }
-
-    pub fn supabase_head_object_auth_request(&self, path: &str) -> 
Result<Request<Buffer>> {
-        let p = build_abs_path(&self.root, path);
-        let url = format!(
-            "{}/storage/v1/object/authenticated/{}/{}",
-            self.endpoint,
-            self.bucket,
-            percent_encode_path(&p)
-        );
-
-        Request::head(&url)
-            .body(Buffer::new())
-            .map_err(new_request_build_error)
-    }
-
-    pub fn supabase_get_object_info_public_request(&self, path: &str) -> 
Result<Request<Buffer>> {
-        let p = build_abs_path(&self.root, path);
-        let url = format!(
-            "{}/storage/v1/object/info/public/{}/{}",
-            self.endpoint,
-            self.bucket,
-            percent_encode_path(&p)
-        );
-
-        Request::get(&url)
-            .body(Buffer::new())
-            .map_err(new_request_build_error)
-    }
-
-    pub fn supabase_get_object_info_auth_request(&self, path: &str) -> 
Result<Request<Buffer>> {
-        let p = build_abs_path(&self.root, path);
-        let url = format!(
-            "{}/storage/v1/object/info/authenticated/{}/{}",
-            self.endpoint,
-            self.bucket,
-            percent_encode_path(&p)
-        );
-
-        Request::get(&url)
-            .body(Buffer::new())
-            .map_err(new_request_build_error)
-    }
-}
-
-// core utils
-impl SupabaseCore {
-    pub async fn send(&self, req: Request<Buffer>) -> Result<Response<Buffer>> 
{
-        self.http_client.send(req).await
-    }
-
-    pub async fn supabase_get_object(
-        &self,
-        path: &str,
-        range: BytesRange,
-    ) -> Result<Response<HttpBody>> {
-        let mut req = if self.key.is_some() {
-            self.supabase_get_object_auth_request(path, range)?
-        } else {
-            self.supabase_get_object_public_request(path, range)?
-        };
-        self.sign(&mut req)?;
-        self.http_client.fetch(req).await
-    }
-
-    pub async fn supabase_head_object(&self, path: &str) -> 
Result<Response<Buffer>> {
-        let mut req = if self.key.is_some() {
-            self.supabase_head_object_auth_request(path)?
-        } else {
-            self.supabase_head_object_public_request(path)?
-        };
-        self.sign(&mut req)?;
-        self.send(req).await
-    }
-
-    pub async fn supabase_get_object_info(&self, path: &str) -> 
Result<Response<Buffer>> {
-        let mut req = if self.key.is_some() {
-            self.supabase_get_object_info_auth_request(path)?
-        } else {
-            self.supabase_get_object_info_public_request(path)?
-        };
-        self.sign(&mut req)?;
-        self.send(req).await
-    }
-}
diff --git a/core/src/services/supabase/docs.md 
b/core/src/services/supabase/docs.md
deleted file mode 100644
index 629d28a77..000000000
--- a/core/src/services/supabase/docs.md
+++ /dev/null
@@ -1,51 +0,0 @@
-## Capabilities
-
-- [x] stat
-- [x] read
-- [x] write
-- [x] create_dir
-- [x] delete
-- [ ] copy
-- [ ] rename
-- [ ] list
-- [ ] presign
-- [ ] blocking
-
-## Configuration
-
-- `root`: Set the work dir for backend.
-- `bucket`: Set the container name for backend.
-- `endpoint`: Set the endpoint for backend.
-- `key`: Set the authorization key for the backend, do not set if you want to 
read public bucket
-
-### Authorization keys
-
-There are two types of key in the Supabase, one is anon_key(Client key), 
another one is
-service_role_key(Secret key). The former one can only write public resources 
while the latter one
-can access all resources. Note that if you want to read public resources, do 
not set the key.
-
-## Example
-
-### Via Builder
-
-```rust,no_run
-use anyhow::Result;
-use opendal::services::Supabase;
-use opendal::Operator;
-
-#[tokio::main]
-async fn main() -> Result<()> {
-    let mut builder = Supabase::default()
-        .root("/")
-        .bucket("test_bucket")
-        .endpoint("http://127.0.0.1:54321";)
-        // this sets up the anon_key, which means this operator can only write 
public resource
-        .key("some_anon_key");
-
-    let op: Operator = Operator::new(builder)?.finish();
-
-    Ok(())
-}
-```
-
- 
diff --git a/core/src/services/supabase/error.rs 
b/core/src/services/supabase/error.rs
deleted file mode 100644
index 273addb90..000000000
--- a/core/src/services/supabase/error.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-// 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.
-
-use http::Response;
-use http::StatusCode;
-use serde::Deserialize;
-use serde_json::from_slice;
-
-use crate::raw::*;
-use crate::*;
-
-#[derive(Default, Debug, Deserialize)]
-#[serde(default, rename_all = "camelCase")]
-/// The error returned by Supabase
-struct SupabaseError {
-    status_code: String,
-    error: String,
-    message: String,
-}
-
-/// Parse the supabase error type to the OpenDAL error type
-pub(super) fn parse_error(resp: Response<Buffer>) -> Error {
-    let (parts, body) = resp.into_parts();
-    let bs = body.to_bytes();
-
-    // Check HTTP status code first/
-    let (mut kind, mut retryable) = match parts.status.as_u16() {
-        500 | 502 | 503 | 504 => (ErrorKind::Unexpected, true),
-        _ => (ErrorKind::Unexpected, false),
-    };
-
-    // Than extrace the error message.
-    let (message, _) = from_slice::<SupabaseError>(&bs)
-        .map(|sb_err| {
-            (kind, retryable) = parse_supabase_error(&sb_err);
-            (format!("{sb_err:?}"), Some(sb_err))
-        })
-        .unwrap_or_else(|_| (String::from_utf8_lossy(&bs).into_owned(), None));
-
-    let mut err = Error::new(kind, message);
-
-    err = with_error_response_context(err, parts);
-
-    if retryable {
-        err = err.set_temporary();
-    }
-
-    err
-}
-
-// Return the error kind and whether it is retryable
-fn parse_supabase_error(err: &SupabaseError) -> (ErrorKind, bool) {
-    let code = err.status_code.parse::<u16>().unwrap();
-    let status_code = StatusCode::from_u16(code).unwrap();
-    match status_code {
-        StatusCode::CONFLICT => (ErrorKind::AlreadyExists, false),
-        StatusCode::NOT_FOUND => (ErrorKind::NotFound, false),
-        StatusCode::FORBIDDEN => (ErrorKind::PermissionDenied, false),
-        StatusCode::PRECONDITION_FAILED | StatusCode::NOT_MODIFIED => {
-            (ErrorKind::ConditionNotMatch, false)
-        }
-        StatusCode::INTERNAL_SERVER_ERROR
-        | StatusCode::BAD_GATEWAY
-        | StatusCode::SERVICE_UNAVAILABLE
-        | StatusCode::GATEWAY_TIMEOUT => (ErrorKind::Unexpected, true),
-        _ => (ErrorKind::Unexpected, false),
-    }
-}
diff --git a/core/src/services/supabase/mod.rs 
b/core/src/services/supabase/mod.rs
deleted file mode 100644
index 4b485a2f1..000000000
--- a/core/src/services/supabase/mod.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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.
-
-#[cfg(feature = "services-supabase")]
-mod core;
-#[cfg(feature = "services-supabase")]
-mod error;
-#[cfg(feature = "services-supabase")]
-mod writer;
-
-#[cfg(feature = "services-supabase")]
-mod backend;
-#[cfg(feature = "services-supabase")]
-pub use backend::SupabaseBuilder as Supabase;
-
-mod config;
-pub use config::SupabaseConfig;
diff --git a/core/src/services/supabase/writer.rs 
b/core/src/services/supabase/writer.rs
deleted file mode 100644
index fd31acd77..000000000
--- a/core/src/services/supabase/writer.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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.
-
-use std::sync::Arc;
-
-use http::StatusCode;
-
-use super::core::*;
-use super::error::parse_error;
-use crate::raw::*;
-use crate::*;
-
-pub struct SupabaseWriter {
-    core: Arc<SupabaseCore>,
-
-    op: OpWrite,
-    path: String,
-}
-
-impl SupabaseWriter {
-    pub fn new(core: Arc<SupabaseCore>, path: &str, op: OpWrite) -> Self {
-        SupabaseWriter {
-            core,
-            op,
-            path: path.to_string(),
-        }
-    }
-}
-
-impl oio::OneShotWrite for SupabaseWriter {
-    async fn write_once(&self, bs: Buffer) -> Result<Metadata> {
-        let mut req = self.core.supabase_upload_object_request(
-            &self.path,
-            Some(bs.len()),
-            self.op.content_type(),
-            bs,
-        )?;
-
-        self.core.sign(&mut req)?;
-
-        let resp = self.core.send(req).await?;
-
-        match resp.status() {
-            StatusCode::OK => Ok(Metadata::default()),
-            _ => Err(parse_error(resp)),
-        }
-    }
-}
diff --git a/core/src/types/operator/builder.rs 
b/core/src/types/operator/builder.rs
index 7c393649b..f739b5fbf 100644
--- a/core/src/types/operator/builder.rs
+++ b/core/src/types/operator/builder.rs
@@ -268,8 +268,6 @@ impl Operator {
             Scheme::Sled => Self::from_iter::<services::Sled>(iter)?.finish(),
             #[cfg(feature = "services-sqlite")]
             Scheme::Sqlite => 
Self::from_iter::<services::Sqlite>(iter)?.finish(),
-            #[cfg(feature = "services-supabase")]
-            Scheme::Supabase => 
Self::from_iter::<services::Supabase>(iter)?.finish(),
             #[cfg(feature = "services-swift")]
             Scheme::Swift => 
Self::from_iter::<services::Swift>(iter)?.finish(),
             #[cfg(feature = "services-tikv")]
diff --git a/core/src/types/scheme.rs b/core/src/types/scheme.rs
index ad34feddd..dfa22d8b6 100644
--- a/core/src/types/scheme.rs
+++ b/core/src/types/scheme.rs
@@ -135,8 +135,6 @@ pub enum Scheme {
     Sftp,
     /// [sled][crate::services::Sled]: Sled services
     Sled,
-    /// [Supabase][crate::services::Supabase]: Supabase storage service
-    Supabase,
     /// [swift][crate::services::Swift]: Swift backend support.
     Swift,
     /// [Vercel Artifacts][crate::services::VercelArtifacts]: Vercel Artifacts 
service, as known as Vercel Remote Caching.
@@ -289,8 +287,6 @@ impl Scheme {
             Scheme::Sled,
             #[cfg(feature = "services-sqlite")]
             Scheme::Sqlite,
-            #[cfg(feature = "services-supabase")]
-            Scheme::Supabase,
             #[cfg(feature = "services-swift")]
             Scheme::Swift,
             #[cfg(feature = "services-tikv")]
@@ -392,7 +388,6 @@ impl FromStr for Scheme {
             "pcloud" => Ok(Scheme::Pcloud),
             "sftp" => Ok(Scheme::Sftp),
             "sled" => Ok(Scheme::Sled),
-            "supabase" => Ok(Scheme::Supabase),
             "swift" => Ok(Scheme::Swift),
             "oss" => Ok(Scheme::Oss),
             "vercel_artifacts" => Ok(Scheme::VercelArtifacts),
@@ -460,7 +455,6 @@ impl From<Scheme> for &'static str {
             Scheme::Seafile => "seafile",
             Scheme::Sftp => "sftp",
             Scheme::Sled => "sled",
-            Scheme::Supabase => "supabase",
             Scheme::Swift => "swift",
             Scheme::VercelArtifacts => "vercel_artifacts",
             Scheme::VercelBlob => "vercel_blob",
diff --git a/core/tests/behavior/async_delete.rs 
b/core/tests/behavior/async_delete.rs
index 199d8965b..c860ab638 100644
--- a/core/tests/behavior/async_delete.rs
+++ b/core/tests/behavior/async_delete.rs
@@ -76,11 +76,6 @@ pub async fn test_delete_empty_dir(op: Operator) -> 
Result<()> {
 
 /// Delete file with special chars should succeed.
 pub async fn test_delete_with_special_chars(op: Operator) -> Result<()> {
-    // Ignore test for supabase until 
https://github.com/apache/opendal/issues/2194 addressed.
-    if op.info().scheme() == opendal::Scheme::Supabase {
-        warn!("ignore test for supabase until 
https://github.com/apache/opendal/issues/2194 is resolved");
-        return Ok(());
-    }
     // Ignore test for atomicserver until 
https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
     if op.info().scheme() == opendal::Scheme::Atomicserver {
         warn!("ignore test for atomicserver until 
https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");
diff --git a/core/tests/behavior/async_read.rs 
b/core/tests/behavior/async_read.rs
index d643851a1..e3afeb534 100644
--- a/core/tests/behavior/async_read.rs
+++ b/core/tests/behavior/async_read.rs
@@ -383,11 +383,6 @@ pub async fn test_read_with_dir_path(op: Operator) -> 
anyhow::Result<()> {
 
 /// Read file with special chars should succeed.
 pub async fn test_read_with_special_chars(op: Operator) -> anyhow::Result<()> {
-    // Ignore test for supabase until 
https://github.com/apache/opendal/issues/2194 addressed.
-    if op.info().scheme() == opendal::Scheme::Supabase {
-        warn!("ignore test for supabase until 
https://github.com/apache/opendal/issues/2194 is resolved");
-        return Ok(());
-    }
     // Ignore test for atomicserver until 
https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
     if op.info().scheme() == opendal::Scheme::Atomicserver {
         warn!("ignore test for atomicserver until 
https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");
diff --git a/core/tests/behavior/async_stat.rs 
b/core/tests/behavior/async_stat.rs
index b4b004a7d..ac9a8a551 100644
--- a/core/tests/behavior/async_stat.rs
+++ b/core/tests/behavior/async_stat.rs
@@ -130,11 +130,6 @@ pub async fn test_stat_nested_parent_dir(op: Operator) -> 
Result<()> {
 
 /// Stat existing file with special chars should return metadata
 pub async fn test_stat_with_special_chars(op: Operator) -> Result<()> {
-    // Ignore test for supabase until 
https://github.com/apache/opendal/issues/2194 addressed.
-    if op.info().scheme() == opendal::Scheme::Supabase {
-        warn!("ignore test for supabase until 
https://github.com/apache/opendal/issues/2194 is resolved");
-        return Ok(());
-    }
     // Ignore test for atomicserver until 
https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
     if op.info().scheme() == opendal::Scheme::Atomicserver {
         warn!("ignore test for atomicserver until 
https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");
diff --git a/core/tests/behavior/async_write.rs 
b/core/tests/behavior/async_write.rs
index 3ed3bf00f..817c5bf72 100644
--- a/core/tests/behavior/async_write.rs
+++ b/core/tests/behavior/async_write.rs
@@ -114,11 +114,6 @@ pub async fn test_write_with_dir_path(op: Operator) -> 
Result<()> {
 
 /// Write a single file with special chars should succeed.
 pub async fn test_write_with_special_chars(op: Operator) -> Result<()> {
-    // Ignore test for supabase until 
https://github.com/apache/opendal/issues/2194 addressed.
-    if op.info().scheme() == opendal::Scheme::Supabase {
-        warn!("ignore test for supabase until 
https://github.com/apache/opendal/issues/2194 is resolved");
-        return Ok(());
-    }
     // Ignore test for atomicserver until 
https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
     if op.info().scheme() == opendal::Scheme::Atomicserver {
         warn!("ignore test for atomicserver until 
https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");
diff --git a/core/tests/behavior/blocking_stat.rs 
b/core/tests/behavior/blocking_stat.rs
index fac31481f..b6c17e41c 100644
--- a/core/tests/behavior/blocking_stat.rs
+++ b/core/tests/behavior/blocking_stat.rs
@@ -64,11 +64,6 @@ pub fn test_blocking_stat_dir(op: BlockingOperator) -> 
Result<()> {
 
 /// Stat existing file with special chars should return metadata
 pub fn test_blocking_stat_with_special_chars(op: BlockingOperator) -> 
Result<()> {
-    // Ignore test for supabase until 
https://github.com/apache/opendal/issues/2194 addressed.
-    if op.info().scheme() == opendal::Scheme::Supabase {
-        warn!("ignore test for supabase until 
https://github.com/apache/opendal/issues/2194 is resolved");
-        return Ok(());
-    }
     // Ignore test for atomicserver until 
https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
     if op.info().scheme() == opendal::Scheme::Atomicserver {
         warn!("ignore test for atomicserver until 
https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");
diff --git a/core/tests/behavior/blocking_write.rs 
b/core/tests/behavior/blocking_write.rs
index f6b4b2c1a..b3fc3d208 100644
--- a/core/tests/behavior/blocking_write.rs
+++ b/core/tests/behavior/blocking_write.rs
@@ -74,11 +74,6 @@ pub fn test_blocking_write_with_dir_path(op: 
BlockingOperator) -> Result<()> {
 
 /// Write a single file with special chars should succeed.
 pub fn test_blocking_write_with_special_chars(op: BlockingOperator) -> 
Result<()> {
-    // Ignore test for supabase until 
https://github.com/apache/opendal/issues/2194 addressed.
-    if op.info().scheme() == opendal::Scheme::Supabase {
-        warn!("ignore test for supabase until 
https://github.com/apache/opendal/issues/2194 is resolved");
-        return Ok(());
-    }
     // Ignore test for atomicserver until 
https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
     if op.info().scheme() == opendal::Scheme::Atomicserver {
         warn!("ignore test for atomicserver until 
https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");


Reply via email to