Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add components subcommand #197

Merged
merged 13 commits into from
Feb 12, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
29 changes: 18 additions & 11 deletions crates/api-client/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -3266,9 +3266,9 @@
},
"dynamic_fields": {
"type": "array",
"description": "List of dynamic fields",
"description": "List of configuration fields",
"items": {
"$ref": "#/components/schemas/DynamicFieldsItem"
"$ref": "#/components/schemas/ConfigurationField"
}
},
"changelog": {
Expand All @@ -3284,30 +3284,37 @@
}
}
},
"DynamicFieldsItem": {
"ConfigurationField": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the dynamic field."
"description": "The name of the configuration field."
},
"title": {
"type": "string",
"description": "The title of the dynamic field."
"description": "The title of the configuration field."
},
"type": {
"type": "string",
"description": "The type of the dynamic field."
"description": "The type of the configuration field.",
"enum": ["string", "boolean", "number"]
},
"required": {
"type": "boolean",
"description": "Whether the dynamic field is required."
"description": "Whether the configuration field is required."
},
"description": {
"type": "string",
"description": "The description of the dynamic field."
"description": "The description of the configuration field."
}
}
},
"required": [
"name",
"title",
"type",
"required"
]
},
"ComponentCreateInput": {
"type": "object",
Expand Down Expand Up @@ -3410,9 +3417,9 @@
},
"dynamic_fields": {
"type": "array",
"description": "List of dynamic fields",
"description": "List of configuration fields",
"items": {
"$ref": "#/components/schemas/DynamicFieldsItem"
"$ref": "#/components/schemas/ConfigurationField"
}
},
"changelog": {
Expand Down
45 changes: 37 additions & 8 deletions crates/cli/src/commands/components/push.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use crate::components::manifest::Manifest;
use edgee_api_client::types as api_types;

#[derive(Debug, clap::Parser)]
pub struct Options {
/// Which organization to create the component into if not existing already.
Expand All @@ -7,9 +10,9 @@ pub struct Options {
}

pub async fn run(opts: Options) -> anyhow::Result<()> {
use edgee_api_client::{auth::Credentials, types, ResultExt};
use edgee_api_client::{auth::Credentials, ResultExt};

use crate::components::manifest::{self, Manifest};
use crate::components::manifest;

let creds = Credentials::load()?;
creds.check_api_token()?;
Expand Down Expand Up @@ -55,16 +58,26 @@ pub async fn run(opts: Options) -> anyhow::Result<()> {
client
.create_component()
.body(
types::ComponentCreateInput::builder()
api_types::ComponentCreateInput::builder()
.organization_id(organization.id.clone())
.name(&manifest.package.name)
.description(manifest.package.description)
.description(manifest.package.description.clone())
.category(manifest.package.category)
.subcategory(manifest.package.subcategory)
.documentation_link(
manifest.package.documentation.map(|url| url.to_string()),
manifest
.package
.documentation
.as_ref()
.map(|url| url.to_string()),
)
.repo_link(manifest.package.repository.map(|url| url.to_string())),
.repo_link(
manifest
.package
.repository
.as_ref()
.map(|url| url.to_string()),
),
)
.send()
.await
Expand All @@ -85,10 +98,11 @@ pub async fn run(opts: Options) -> anyhow::Result<()> {
.org_slug(organization.slug)
.component_slug(&manifest.package.name)
.body(
types::ComponentVersionCreateInput::builder()
api_types::ComponentVersionCreateInput::builder()
.version(&manifest.package.version)
.wit_world_version(&manifest.package.wit_world_version)
.wasm_url(asset_url),
.wasm_url(asset_url)
.dynamic_fields(convert_manifest_config_fields(&manifest)),
)
.send()
.await
Expand All @@ -102,3 +116,18 @@ pub async fn run(opts: Options) -> anyhow::Result<()> {

Ok(())
}

fn convert_manifest_config_fields(manifest: &Manifest) -> Vec<api_types::ConfigurationField> {
manifest
.package
.config_fields
.iter()
.map(|(name, field)| api_types::ConfigurationField {
name: name.clone(),
title: field.title.clone(),
type_: field.type_,
required: field.required,
description: field.description.clone(),
})
.collect()
}
31 changes: 29 additions & 2 deletions crates/cli/src/components/manifest.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::path::{Path, PathBuf};
use std::{
collections::HashMap,
path::{Path, PathBuf},
};

use anyhow::{Context, Result};
use serde::Deserialize;
Expand All @@ -15,6 +18,7 @@ pub struct Manifest {
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct Package {
pub name: String,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there anything else that we might want here? like something the web console supports and we don't support yet with the CLI?

maybe the component image/logo?

pub version: String,
Expand All @@ -29,9 +33,11 @@ pub struct Package {
#[serde(default)]
pub repository: Option<url::Url>,

#[serde(rename = "wit-world-version")]
pub wit_world_version: String,

#[serde(default)]
pub config_fields: HashMap<String, ConfigField>,

pub build: Build,
}

Expand All @@ -55,6 +61,27 @@ pub enum SubCategory {
Attribution,
}

#[derive(Debug, Deserialize)]
pub struct ConfigField {
pub title: String,
#[serde(rename = "type", with = "ConfigFieldType")]
pub type_: api_types::ConfigurationFieldType,
#[serde(default)]
pub required: bool,
pub description: Option<String>,
}

#[derive(Debug, Clone, Copy, Deserialize)]
#[serde(
remote = "api_types::ConfigurationFieldType",
rename_all = "kebab-case"
)]
pub enum ConfigFieldType {
String,
Boolean,
Number,
}

#[derive(Debug, Deserialize)]
pub struct Build {
pub command: String,
Expand Down
Loading