Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ OPENDAL_WEBHDFS_ATOMIC_WRITE_DIR=.opendal_tmp/
OPENDAL_WEBHDFS_DISABLE_LIST_BATCH=false
# vercel artifacts
OPENDAL_VERCEL_ARTIFACTS_ACCESS_TOKEN=<token>
# OPENDAL_VERCEL_ARTIFACTS_ENDPOINT=https://api.vercel.com
# OPENDAL_VERCEL_ARTIFACTS_TEAM_ID=<team_id>
# OPENDAL_VERCEL_ARTIFACTS_TEAM_SLUG=<team_slug>
# onedrive
OPENDAL_ONEDRIVE_ACCESS_TOKEN=<access_token>
# foundationdb
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,24 @@ public sealed class VercelArtifactsServiceConfig : IServiceConfig
/// </summary>
public string? AccessToken { get; init; }

/// <summary>
/// The endpoint for the Vercel artifacts API.
/// Defaults to <c>https://api.vercel.com</c>.
/// </summary>
public string? Endpoint { get; init; }

/// <summary>
/// The Vercel team ID. When set, the <c>teamId</c> query parameter
/// is appended to all API requests.
/// </summary>
public string? TeamId { get; init; }

/// <summary>
/// The Vercel team slug. When set, the <c>slug</c> query parameter
/// is appended to all API requests.
/// </summary>
public string? TeamSlug { get; init; }

public string Scheme => "vercel_artifacts";

public IReadOnlyDictionary<string, string> ToOptions()
Expand All @@ -42,6 +60,18 @@ public IReadOnlyDictionary<string, string> ToOptions()
{
map["access_token"] = Utilities.ToOptionString(AccessToken);
}
if (Endpoint is not null)
{
map["endpoint"] = Utilities.ToOptionString(Endpoint);
}
if (TeamId is not null)
{
map["team_id"] = Utilities.ToOptionString(TeamId);
}
if (TeamSlug is not null)
{
map["team_slug"] = Utilities.ToOptionString(TeamSlug);
}
return map;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3323,6 +3323,21 @@ class VercelArtifacts implements ServiceConfig {
* <p>The access token for Vercel.</p>
*/
public final String accessToken;
/**
* <p>The endpoint for the Vercel artifacts API.</p>
* <p>Defaults to <code>https://api.vercel.com</code>.</p>
*/
public final String endpoint;
/**
* <p>The Vercel team ID. When set, the <code>teamId</code> query parameter
* is appended to all API requests.</p>
*/
public final String teamId;
/**
* <p>The Vercel team slug. When set, the <code>slug</code> query parameter
* is appended to all API requests.</p>
*/
public final String teamSlug;

@Override
public String scheme() {
Expand All @@ -3335,6 +3350,15 @@ public Map<String, String> configMap() {
if (accessToken != null) {
map.put("access_token", accessToken);
}
if (endpoint != null) {
map.put("endpoint", endpoint);
}
if (teamId != null) {
map.put("team_id", teamId);
}
if (teamSlug != null) {
map.put("team_slug", teamSlug);
}
return map;
}
}
Expand Down
18 changes: 18 additions & 0 deletions bindings/python/python/opendal/operator.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2331,6 +2331,9 @@ class AsyncOperator:
/,
*,
access_token: builtins.str = ...,
endpoint: builtins.str = ...,
team_id: builtins.str = ...,
team_slug: builtins.str = ...,
) -> typing_extensions.Self:
r"""
Create a new `AsyncOperator` for `vercel-artifacts` service.
Expand All @@ -2339,6 +2342,12 @@ class AsyncOperator:
----------
access_token : builtins.str, optional
The access token for Vercel.
endpoint : builtins.str, optional
The endpoint for the Vercel artifacts API. Defaults to ``https://api.vercel.com``.
team_id : builtins.str, optional
The Vercel team ID.
team_slug : builtins.str, optional
The Vercel team slug.

Returns
-------
Expand Down Expand Up @@ -4571,6 +4580,9 @@ class Operator:
/,
*,
access_token: builtins.str = ...,
endpoint: builtins.str = ...,
team_id: builtins.str = ...,
team_slug: builtins.str = ...,
) -> typing_extensions.Self:
r"""
Create a new `Operator` for `vercel-artifacts` service.
Expand All @@ -4579,6 +4591,12 @@ class Operator:
----------
access_token : builtins.str, optional
The access token for Vercel.
endpoint : builtins.str, optional
The endpoint for the Vercel artifacts API. Defaults to ``https://api.vercel.com``.
team_id : builtins.str, optional
The Vercel team ID.
team_slug : builtins.str, optional
The Vercel team slug.

Returns
-------
Expand Down
18 changes: 18 additions & 0 deletions bindings/python/src/services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2343,6 +2343,9 @@ submit! {
/,
*,
access_token: builtins.str = ...,
endpoint: builtins.str = ...,
team_id: builtins.str = ...,
team_slug: builtins.str = ...,
) -> typing_extensions.Self:
r"""
Create a new `Operator` for `vercel-artifacts` service.
Expand All @@ -2351,6 +2354,12 @@ submit! {
----------
access_token : builtins.str, optional
The access token for Vercel.
endpoint : builtins.str, optional
The endpoint for the Vercel artifacts API. Defaults to ``https://api.vercel.com``.
team_id : builtins.str, optional
The Vercel team ID.
team_slug : builtins.str, optional
The Vercel team slug.
Returns
-------
Operator
Expand Down Expand Up @@ -4677,6 +4686,9 @@ submit! {
/,
*,
access_token: builtins.str = ...,
endpoint: builtins.str = ...,
team_id: builtins.str = ...,
team_slug: builtins.str = ...,
) -> typing_extensions.Self:
r"""
Create a new `AsyncOperator` for `vercel-artifacts` service.
Expand All @@ -4685,6 +4697,12 @@ submit! {
----------
access_token : builtins.str, optional
The access token for Vercel.
endpoint : builtins.str, optional
The endpoint for the Vercel artifacts API. Defaults to ``https://api.vercel.com``.
team_id : builtins.str, optional
The Vercel team ID.
team_slug : builtins.str, optional
The Vercel team slug.
Returns
-------
AsyncOperator
Expand Down
68 changes: 60 additions & 8 deletions core/services/vercel-artifacts/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,36 @@ impl VercelArtifactsBuilder {
self.config.access_token = Some(access_token.to_string());
self
}

/// Set the endpoint for the Vercel artifacts API.
///
/// Default: `https://api.vercel.com`
pub fn endpoint(mut self, endpoint: &str) -> Self {
if !endpoint.is_empty() {
self.config.endpoint = Some(endpoint.trim_end_matches('/').to_string());
}
self
}

/// Set the Vercel team ID.
///
/// When set, the `teamId` query parameter is appended to all requests.
pub fn team_id(mut self, team_id: &str) -> Self {
if !team_id.is_empty() {
self.config.team_id = Some(team_id.to_string());
}
self
}

/// Set the Vercel team slug.
///
/// When set, the `slug` query parameter is appended to all requests.
pub fn team_slug(mut self, team_slug: &str) -> Self {
if !team_slug.is_empty() {
self.config.team_slug = Some(team_slug.to_string());
}
self
}
}

impl Builder for VercelArtifactsBuilder {
Expand All @@ -68,14 +98,36 @@ impl Builder for VercelArtifactsBuilder {
..Default::default()
});

match self.config.access_token.clone() {
Some(access_token) => Ok(VercelArtifactsBackend {
core: Arc::new(VercelArtifactsCore {
info: Arc::new(info),
access_token,
}),
}),
None => Err(Error::new(ErrorKind::ConfigInvalid, "access_token not set")),
let access_token = self
.config
.access_token
.ok_or_else(|| Error::new(ErrorKind::ConfigInvalid, "access_token not set"))?;

let endpoint = self
.config
.endpoint
.unwrap_or_else(|| "https://api.vercel.com".to_string());

let mut query_params = Vec::new();
if let Some(team_id) = &self.config.team_id {
query_params.push(format!("teamId={team_id}"));
}
if let Some(slug) = &self.config.team_slug {
query_params.push(format!("slug={slug}"));
}
let query_string = if query_params.is_empty() {
String::new()
} else {
format!("?{}", query_params.join("&"))
};

Ok(VercelArtifactsBackend {
core: Arc::new(VercelArtifactsCore {
info: Arc::new(info),
access_token,
endpoint,
query_string,
}),
})
}
}
45 changes: 45 additions & 0 deletions core/services/vercel-artifacts/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ use super::builder::VercelArtifactsBuilder;
pub struct VercelArtifactsConfig {
/// The access token for Vercel.
pub access_token: Option<String>,
/// The endpoint for the Vercel artifacts API.
///
/// Defaults to `https://api.vercel.com`.
pub endpoint: Option<String>,
/// The Vercel team ID. When set, the `teamId` query parameter
/// is appended to all API requests.
pub team_id: Option<String>,
/// The Vercel team slug. When set, the `slug` query parameter
/// is appended to all API requests.
pub team_slug: Option<String>,
}

impl Debug for VercelArtifactsConfig {
Expand Down Expand Up @@ -67,4 +77,39 @@ mod tests {
let cfg = VercelArtifactsConfig::from_uri(&uri).unwrap();
assert_eq!(cfg.access_token.as_deref(), Some("token123"));
}

#[test]
fn from_uri_loads_all_options() {
let uri = OperatorUri::new(
"vercel-artifacts://cache",
vec![
("access_token".to_string(), "token123".to_string()),
(
"endpoint".to_string(),
"https://custom.api.example.com".to_string(),
),
("team_id".to_string(), "team_abc".to_string()),
("team_slug".to_string(), "my-team".to_string()),
],
)
.unwrap();

let cfg = VercelArtifactsConfig::from_uri(&uri).unwrap();
assert_eq!(cfg.access_token.as_deref(), Some("token123"));
assert_eq!(
cfg.endpoint.as_deref(),
Some("https://custom.api.example.com")
);
assert_eq!(cfg.team_id.as_deref(), Some("team_abc"));
assert_eq!(cfg.team_slug.as_deref(), Some("my-team"));
}

#[test]
fn defaults_are_none() {
let cfg = VercelArtifactsConfig::default();
assert!(cfg.access_token.is_none());
assert!(cfg.endpoint.is_none());
assert!(cfg.team_id.is_none());
assert!(cfg.team_slug.is_none());
}
}
20 changes: 14 additions & 6 deletions core/services/vercel-artifacts/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ use opendal_core::*;
pub struct VercelArtifactsCore {
pub info: Arc<AccessorInfo>,
pub(crate) access_token: String,
pub(crate) endpoint: String,
pub(crate) query_string: String,
}

impl Debug for VercelArtifactsCore {
Expand All @@ -45,8 +47,10 @@ impl VercelArtifactsCore {
_: &OpRead,
) -> Result<Response<HttpBody>> {
let url: String = format!(
"https://api.vercel.com/v8/artifacts/{}",
percent_encode_path(hash)
"{}/v8/artifacts/{}{}",
self.endpoint,
percent_encode_path(hash),
self.query_string
);

let mut req = Request::get(&url);
Expand All @@ -72,8 +76,10 @@ impl VercelArtifactsCore {
body: Buffer,
) -> Result<Response<Buffer>> {
let url = format!(
"https://api.vercel.com/v8/artifacts/{}",
percent_encode_path(hash)
"{}/v8/artifacts/{}{}",
self.endpoint,
percent_encode_path(hash),
self.query_string
);

let mut req = Request::put(&url);
Expand All @@ -92,8 +98,10 @@ impl VercelArtifactsCore {

pub(crate) async fn vercel_artifacts_stat(&self, hash: &str) -> Result<Response<Buffer>> {
let url = format!(
"https://api.vercel.com/v8/artifacts/{}",
percent_encode_path(hash)
"{}/v8/artifacts/{}{}",
self.endpoint,
percent_encode_path(hash),
self.query_string
);

let mut req = Request::head(&url);
Expand Down
7 changes: 6 additions & 1 deletion core/services/vercel-artifacts/src/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ This service can be used to:
## Configuration

- `access_token`: set the access_token for Rest API
- `endpoint`: set the API endpoint (default: `https://api.vercel.com`)
- `team_id`: optional Vercel team ID, appended as `teamId` query parameter
- `team_slug`: optional Vercel team slug, appended as `slug` query parameter

You can refer to [`VercelArtifactsBuilder`]'s docs for more information

Expand All @@ -31,7 +34,9 @@ use opendal_core::Operator;
async fn main() -> Result<()> {
// create backend builder
let mut builder = VercelArtifacts::default()
.access_token("xxx");
.access_token("xxx")
.endpoint("https://my-vercel-api.example.com")
.team_id("team_xxx");

let op: Operator = Operator::new(builder)?.finish();
Ok(())
Expand Down
Loading