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 4c2b68f44 refactor(services/opfs): split opfs service into separate
crate (#7021)
4c2b68f44 is described below
commit 4c2b68f44baa760314f1cad651406cf4cacef2ab
Author: Zhiqiang ZHOU <[email protected]>
AuthorDate: Tue Dec 16 19:48:44 2025 -0800
refactor(services/opfs): split opfs service into separate crate (#7021)
* refactor(services/opfs): split opfs service into separate crate
Move OPFS service from core/src/services/opfs to services/opfs as a
standalone crate. This follows the ongoing service extraction pattern
to improve modularity and reduce core dependencies.
Changes:
- Create new services/opfs crate with its own Cargo.toml
- Move all OPFS implementation files to services/opfs/src
- Remove OPFS-specific dependencies from core/Cargo.toml
- Update service feature flag to use opendal-service-opfs dependency
- Re-export opfs module in src/lib.rs
Co-Authored-By: Claude <[email protected]>
* chore: apply taplo formatting
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* refactor(services/opfs): split opfs service into separate crate
Update opfs service export to use opendal_service_opfs crate with
appropriate target architecture constraints for wasm32.
Co-Authored-By: Claude <[email protected]>
* refactor(services/opfs): move dependency to wasm32 target-specific section
The OPFS service only works in WebAssembly environments, so the
dependency is now correctly placed under the wasm32 target-specific
dependencies section instead of the main dependencies.
Co-Authored-By: Claude <[email protected]>
---------
Co-authored-by: Claude <[email protected]>
---
core/Cargo.lock | 18 ++++++--
core/Cargo.toml | 5 ++-
core/core/Cargo.toml | 22 ----------
core/core/src/services/mod.rs | 3 --
core/services/opfs/Cargo.toml | 51 ++++++++++++++++++++++
.../services/opfs => services/opfs/src}/backend.rs | 30 +++++++++++--
.../services/opfs => services/opfs/src}/config.rs | 20 ++++++++-
.../services/opfs => services/opfs/src}/core.rs | 5 +--
.../services/opfs => services/opfs/src}/docs.md | 0
.../services/opfs => services/opfs/src}/error.rs | 3 +-
.../opfs/mod.rs => services/opfs/src/lib.rs} | 10 +++++
.../services/opfs => services/opfs/src}/utils.rs | 12 ++---
core/src/lib.rs | 2 +
13 files changed, 137 insertions(+), 44 deletions(-)
diff --git a/core/Cargo.lock b/core/Cargo.lock
index 6173f05e6..e03ff0760 100644
--- a/core/Cargo.lock
+++ b/core/Cargo.lock
@@ -5574,6 +5574,7 @@ dependencies = [
"opendal-service-moka",
"opendal-service-mysql",
"opendal-service-obs",
+ "opendal-service-opfs",
"opendal-service-oss",
"opendal-service-persy",
"opendal-service-postgresql",
@@ -5648,7 +5649,6 @@ dependencies = [
"http 1.4.0",
"http-body 1.0.1",
"jiff",
- "js-sys",
"libtest-mimic",
"log",
"md-5",
@@ -5680,9 +5680,6 @@ dependencies = [
"tracing-subscriber",
"url",
"uuid",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "web-sys",
"web-time",
]
@@ -6215,6 +6212,19 @@ dependencies = [
"serde",
]
+[[package]]
+name = "opendal-service-opfs"
+version = "0.55.0"
+dependencies = [
+ "ctor",
+ "js-sys",
+ "opendal-core",
+ "serde",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+]
+
[[package]]
name = "opendal-service-oss"
version = "0.55.0"
diff --git a/core/Cargo.toml b/core/Cargo.toml
index b17ae5ea3..e6231e25f 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -141,7 +141,7 @@ services-monoiofs = ["opendal-core/services-monoiofs"]
services-mysql = ["dep:opendal-service-mysql"]
services-obs = ["dep:opendal-service-obs"]
services-onedrive = ["opendal-core/services-onedrive"]
-services-opfs = ["opendal-core/services-opfs"]
+services-opfs = ["dep:opendal-service-opfs"]
services-oss = ["dep:opendal-service-oss"]
services-pcloud = ["opendal-core/services-pcloud"]
services-persy = ["dep:opendal-service-persy"]
@@ -266,3 +266,6 @@ tracing-subscriber = { version = "0.3", features = [
"tracing-log",
] }
uuid = { workspace = true, features = ["serde", "v4"] }
+
+[target.'cfg(target_arch = "wasm32")'.dependencies]
+opendal-service-opfs = { path = "services/opfs", version = "0.55.0", optional
= true, default-features = false }
diff --git a/core/core/Cargo.toml b/core/core/Cargo.toml
index 298db1678..edfaefc7d 100644
--- a/core/core/Cargo.toml
+++ b/core/core/Cargo.toml
@@ -74,13 +74,6 @@ services-memory = []
services-mongodb = ["dep:mongodb", "dep:mongodb-internal-macros"]
services-monoiofs = ["dep:monoio", "dep:flume"]
services-onedrive = []
-services-opfs = [
- "dep:js-sys",
- "dep:wasm-bindgen",
- "dep:wasm-bindgen-futures",
- "dep:web-sys",
-]
-
services-pcloud = []
services-redis = ["dep:redis", "dep:fastpool", "redis?/tokio-rustls-comp"]
services-redis-native-tls = ["services-redis", "redis?/tokio-native-tls-comp"]
@@ -187,21 +180,6 @@ monoio = { version = "0.2.4", optional = true, features = [
"unlinkat",
"renameat",
] }
-# for service-opfs
-js-sys = { version = "0.3.77", optional = true }
-wasm-bindgen = { version = "0.2.100", optional = true }
-wasm-bindgen-futures = { version = "0.4.50", optional = true }
-web-sys = { version = "0.3.77", optional = true, features = [
- "Window",
- "File",
- "FileSystemDirectoryHandle",
- "FileSystemFileHandle",
- "FileSystemGetDirectoryOptions",
- "FileSystemGetFileOptions",
- "FileSystemWritableFileStream",
- "Navigator",
- "StorageManager",
-] }
# Layers
# for layers-dtrace
diff --git a/core/core/src/services/mod.rs b/core/core/src/services/mod.rs
index e89d1a6d9..e1553e71d 100644
--- a/core/core/src/services/mod.rs
+++ b/core/core/src/services/mod.rs
@@ -163,6 +163,3 @@ pub use webhdfs::*;
mod yandex_disk;
#[cfg(feature = "services-yandex-disk")]
pub use yandex_disk::*;
-
-#[cfg(all(target_arch = "wasm32", feature = "services-opfs"))]
-mod opfs;
diff --git a/core/services/opfs/Cargo.toml b/core/services/opfs/Cargo.toml
new file mode 100644
index 000000000..336b2e422
--- /dev/null
+++ b/core/services/opfs/Cargo.toml
@@ -0,0 +1,51 @@
+# 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.
+
+[package]
+description = "Apache OpenDAL OPFS service implementation"
+name = "opendal-service-opfs"
+
+authors = { workspace = true }
+edition = { workspace = true }
+homepage = { workspace = true }
+license = { workspace = true }
+repository = { workspace = true }
+rust-version = { workspace = true }
+version = { workspace = true }
+
+[package.metadata.docs.rs]
+all-features = true
+
+[dependencies]
+opendal-core = { path = "../../core", version = "0.55.0", default-features =
false }
+
+ctor = { workspace = true }
+js-sys = "0.3.77"
+serde = { workspace = true, features = ["derive"] }
+wasm-bindgen = "0.2.100"
+wasm-bindgen-futures = "0.4.50"
+web-sys = { version = "0.3.77", features = [
+ "Window",
+ "File",
+ "FileSystemDirectoryHandle",
+ "FileSystemFileHandle",
+ "FileSystemGetDirectoryOptions",
+ "FileSystemGetFileOptions",
+ "FileSystemWritableFileStream",
+ "Navigator",
+ "StorageManager",
+] }
diff --git a/core/core/src/services/opfs/backend.rs
b/core/services/opfs/src/backend.rs
similarity index 68%
rename from core/core/src/services/opfs/backend.rs
rename to core/services/opfs/src/backend.rs
index c7c6db0b6..9e28868a5 100644
--- a/core/core/src/services/opfs/backend.rs
+++ b/core/services/opfs/src/backend.rs
@@ -20,9 +20,25 @@ use std::sync::Arc;
use web_sys::FileSystemGetDirectoryOptions;
+use super::OPFS_SCHEME;
+use super::config::OpfsConfig;
use super::utils::*;
-use crate::raw::*;
-use crate::*;
+use opendal_core::raw::*;
+use opendal_core::*;
+
+#[doc = include_str!("docs.md")]
+#[derive(Default, Debug)]
+pub struct OpfsBuilder {
+ pub(super) config: OpfsConfig,
+}
+
+impl Builder for OpfsBuilder {
+ type Config = OpfsConfig;
+
+ fn build(self) -> Result<impl Access> {
+ Ok(OpfsBackend {})
+ }
+}
/// OPFS Service backend
#[derive(Default, Debug, Clone)]
@@ -38,7 +54,15 @@ impl Access for OpfsBackend {
type Deleter = ();
fn info(&self) -> Arc<AccessorInfo> {
- Arc::new(AccessorInfo::default())
+ let info = AccessorInfo::default();
+ info.set_scheme(OPFS_SCHEME);
+ info.set_name("opfs");
+ info.set_root("/");
+ info.set_native_capability(Capability {
+ create_dir: true,
+ ..Default::default()
+ });
+ Arc::new(info)
}
async fn create_dir(&self, path: &str, _: OpCreateDir) ->
Result<RpCreateDir> {
diff --git a/core/core/src/services/opfs/config.rs
b/core/services/opfs/src/config.rs
similarity index 69%
rename from core/core/src/services/opfs/config.rs
rename to core/services/opfs/src/config.rs
index 7bf938233..38bd72c21 100644
--- a/core/core/src/services/opfs/config.rs
+++ b/core/services/opfs/src/config.rs
@@ -15,11 +15,29 @@
// specific language governing permissions and limitations
// under the License.
+use std::fmt::Debug;
+
use serde::Deserialize;
use serde::Serialize;
+use super::backend::OpfsBuilder;
+
/// Config for OPFS.
#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
#[serde(default)]
#[non_exhaustive]
-pub struct OPFSConfig {}
+pub struct OpfsConfig {}
+
+impl Debug for OpfsConfig {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("OpfsConfig").finish_non_exhaustive()
+ }
+}
+
+impl opendal_core::Configurator for OpfsConfig {
+ type Builder = OpfsBuilder;
+
+ fn into_builder(self) -> Self::Builder {
+ OpfsBuilder { config: self }
+ }
+}
diff --git a/core/core/src/services/opfs/core.rs
b/core/services/opfs/src/core.rs
similarity index 96%
rename from core/core/src/services/opfs/core.rs
rename to core/services/opfs/src/core.rs
index 643af84bd..10cd1da91 100644
--- a/core/core/src/services/opfs/core.rs
+++ b/core/services/opfs/src/core.rs
@@ -22,8 +22,8 @@ use wasm_bindgen_futures::JsFuture;
use web_sys::File;
use web_sys::FileSystemWritableFileStream;
-use crate::Error;
-use crate::Result;
+use opendal_core::Error;
+use opendal_core::Result;
use super::error::*;
use super::utils::*;
@@ -41,7 +41,6 @@ impl OpfsCore {
.and_then(JsCast::dyn_into)
.map_err(parse_js_error)?;
- // QuotaExceeded or NotAllowed
JsFuture::from(
writable
.write_with_u8_array(content)
diff --git a/core/core/src/services/opfs/docs.md
b/core/services/opfs/src/docs.md
similarity index 100%
rename from core/core/src/services/opfs/docs.md
rename to core/services/opfs/src/docs.md
diff --git a/core/core/src/services/opfs/error.rs
b/core/services/opfs/src/error.rs
similarity index 94%
rename from core/core/src/services/opfs/error.rs
rename to core/services/opfs/src/error.rs
index 1f7d5cb87..5f2a1a0fe 100644
--- a/core/core/src/services/opfs/error.rs
+++ b/core/services/opfs/src/error.rs
@@ -17,7 +17,8 @@
use wasm_bindgen::JsValue;
-use crate::{Error, ErrorKind};
+use opendal_core::Error;
+use opendal_core::ErrorKind;
pub(crate) fn parse_js_error(msg: JsValue) -> Error {
Error::new(
diff --git a/core/core/src/services/opfs/mod.rs b/core/services/opfs/src/lib.rs
similarity index 80%
rename from core/core/src/services/opfs/mod.rs
rename to core/services/opfs/src/lib.rs
index dd1b80048..0c391e162 100644
--- a/core/core/src/services/opfs/mod.rs
+++ b/core/services/opfs/src/lib.rs
@@ -18,8 +18,18 @@
/// Default scheme for opfs service.
pub const OPFS_SCHEME: &str = "opfs";
+use opendal_core::DEFAULT_OPERATOR_REGISTRY;
+
mod backend;
mod config;
mod core;
mod error;
mod utils;
+
+pub use backend::OpfsBuilder as Opfs;
+pub use config::OpfsConfig;
+
+#[ctor::ctor]
+fn register_opfs_service() {
+ DEFAULT_OPERATOR_REGISTRY.register::<Opfs>(OPFS_SCHEME);
+}
diff --git a/core/core/src/services/opfs/utils.rs
b/core/services/opfs/src/utils.rs
similarity index 91%
rename from core/core/src/services/opfs/utils.rs
rename to core/services/opfs/src/utils.rs
index 9cc3bd25e..4c2997a73 100644
--- a/core/core/src/services/opfs/utils.rs
+++ b/core/services/opfs/src/utils.rs
@@ -15,13 +15,14 @@
// specific language governing permissions and limitations
// under the License.
-use crate::Result;
+use opendal_core::Result;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;
-use web_sys::{
- FileSystemDirectoryHandle, FileSystemFileHandle,
FileSystemGetDirectoryOptions,
- FileSystemGetFileOptions, window,
-};
+use web_sys::FileSystemDirectoryHandle;
+use web_sys::FileSystemFileHandle;
+use web_sys::FileSystemGetDirectoryOptions;
+use web_sys::FileSystemGetFileOptions;
+use web_sys::window;
use super::error::*;
@@ -59,7 +60,6 @@ pub(crate) async fn get_handle_by_filename(filename: &str) ->
Result<FileSystemF
.and_then(JsCast::dyn_into)
.map_err(parse_js_error)?;
- // maybe the option should be exposed?
let opt = FileSystemGetFileOptions::new();
opt.set_create(true);
diff --git a/core/src/lib.rs b/core/src/lib.rs
index 34edce71d..055936fe5 100644
--- a/core/src/lib.rs
+++ b/core/src/lib.rs
@@ -76,6 +76,8 @@ pub mod services {
pub use opendal_service_mysql::*;
#[cfg(feature = "services-obs")]
pub use opendal_service_obs::*;
+ #[cfg(all(target_arch = "wasm32", feature = "services-opfs"))]
+ pub use opendal_service_opfs::*;
#[cfg(feature = "services-oss")]
pub use opendal_service_oss::*;
#[cfg(feature = "services-persy")]