Compare commits

..

No commits in common. "3d916f1ff4c4469dd5d10408e177b1a4b3d16e2a" and "8744fb6acf25f60477ee392ae23e14b3e32a5c14" have entirely different histories.

25 changed files with 1055 additions and 110968 deletions

View file

@ -25,7 +25,7 @@ SITEMAP_ALLOWED_HOST="https://api.example.com"
## THESE VARIABLES ARE FOR SIMPLE-PAYMENT-GATEWAY APP ## THESE VARIABLES ARE FOR SIMPLE-PAYMENT-GATEWAY APP
#To see all possible options, check simple-payment-gateway/src/app:GatewayTypes #To see all possible options, check simple-payment-gateway/src/app:GatewayTypes
ACTIVE_PAYMENT_METHODS="cod,cash,transfer" ACTIVE_GATEWAYS="cod,cash,transfer"
# only Sk,En available :). Determines what language the gateway names will be in storefront # only Sk,En available :). Determines what language the gateway names will be in storefront
LOCALE="Sk" LOCALE="Sk"
# uses https://crates.io/crates/iso_currency # uses https://crates.io/crates/iso_currency

1725
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -35,7 +35,7 @@ iso_currency = { version = "0.4.4", features = ["with-serde", "iterator"] }
pulldown-cmark = "0.11.0" pulldown-cmark = "0.11.0"
http = "1" http = "1"
thiserror = "1.0.61" thiserror = "1.0.61"
wasm-bindgen = "=0.2.93" wasm-bindgen = "=0.2.92"
console_error_panic_hook = "0.1" console_error_panic_hook = "0.1"
leptos = { version = "0.6", features = ["nightly"] } leptos = { version = "0.6", features = ["nightly"] }
leptos_axum = { version = "0.6" } leptos_axum = { version = "0.6" }

View file

@ -31,8 +31,8 @@ dependencies = [
[tasks.push-containers] [tasks.push-containers]
workspace = false workspace = false
script = ''' script = '''
docker push ghcr.io/djkato/saleor-app-sitemap-generator:latest docker push ghcr.io/djkato/saleor-sitemap-generator:latest
docker push ghcr.io/djkato/saleor-app-simple-payment-gateway:latest docker push ghcr.io/djkato/saleor-simple-payment-gateway:latest
''' '''
[tasks.delete-images] [tasks.delete-images]

View file

@ -36,28 +36,17 @@ http = { workspace = true }
pulldown-cmark = { workspace = true } pulldown-cmark = { workspace = true }
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true } serde_json = { workspace = true }
saleor-app-sdk = { workspace = true, features = ["bridge"], optional = true }
dotenvy = { workspace = true } dotenvy = { workspace = true }
envy = { workspace = true } envy = { workspace = true }
cynic = { workspace = true, features = ["http-surf"], optional = true } cynic = { workspace = true, features = ["http-surf"], optional = true }
surf = { workspace = true, optional = true } surf = { workspace = true, optional = true }
[target.'cfg(target_family = "unix")'.dependencies]
saleor-app-sdk = { workspace = true, optional = true, features = [
"file_apl",
"redis_apl",
"tracing",
"middleware",
"webhook_utils",
] }
[target.'cfg(target_family = "wasm")'.dependencies]
saleor-app-sdk = { workspace = true, optional = true, features = ["bridge"] }
[build-dependencies] [build-dependencies]
cynic-codegen = { workspace = true, optional = true } cynic-codegen = { workspace = true, optional = true }
[features] [features]
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
ssr = [ ssr = [
"dep:axum", "dep:axum",
"dep:tokio", "dep:tokio",
@ -66,11 +55,6 @@ ssr = [
"dep:leptos_axum", "dep:leptos_axum",
"dep:tracing", "dep:tracing",
"dep:saleor-app-sdk", "dep:saleor-app-sdk",
"saleor-app-sdk/file_apl",
"saleor-app-sdk/redis_apl",
"saleor-app-sdk/tracing",
"saleor-app-sdk/middleware",
"saleor-app-sdk/webhook_utils",
"dep:tracing-subscriber", "dep:tracing-subscriber",
"dep:anyhow", "dep:anyhow",
"dep:cynic", "dep:cynic",
@ -80,13 +64,6 @@ ssr = [
"leptos_meta/ssr", "leptos_meta/ssr",
"leptos_router/ssr", "leptos_router/ssr",
] ]
hydrate = [
"leptos/hydrate",
"leptos_meta/hydrate",
"leptos_router/hydrate",
"dep:saleor-app-sdk",
"saleor-app-sdk/bridge",
]
# Defines a size-optimized profile for the WASM bundle in release mode # Defines a size-optimized profile for the WASM bundle in release mode
@ -118,7 +95,7 @@ tailwind-input-file = "style/base.css"
assets-dir = "public" assets-dir = "public"
# The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup. # The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup.
site-addr = "0.0.0.0:3000" site-addr = "127.0.0.1:3000"
# The port to use for automatic reload monitoring # The port to use for automatic reload monitoring
reload-port = 3001 reload-port = 3001

View file

@ -1,5 +1,4 @@
use crate::error_template::{AppError, ErrorTemplate}; use crate::error_template::{AppError, ErrorTemplate};
use crate::routes::extensions::order_to_pdf::Pdf;
use crate::routes::home::Home; use crate::routes::home::Home;
use leptos::*; use leptos::*;
use leptos_meta::*; use leptos_meta::*;
@ -14,22 +13,22 @@ pub struct UrlAppParams {
pub fn App() -> impl IntoView { pub fn App() -> impl IntoView {
// Provides context that manages stylesheets, titles, meta tags, etc. // Provides context that manages stylesheets, titles, meta tags, etc.
provide_meta_context(); provide_meta_context();
view! { view! {
<Stylesheet id="leptos" href="/pkg/saleor-app-template-ui.css" /> <Stylesheet id="leptos" href="/pkg/saleor-app-template-ui.css"/>
// sets the document title // sets the document title
<Title text="Example UI App template in Rust" /> <Title text="Example UI App template in Rust"/>
// content for this welcome page // content for this welcome page
<Router fallback=|| { <Router fallback=|| {
let mut outside_errors = Errors::default(); let mut outside_errors = Errors::default();
outside_errors.insert_with_default_key(AppError::NotFound); outside_errors.insert_with_default_key(AppError::NotFound);
view! { <ErrorTemplate outside_errors /> }.into_view() view! { <ErrorTemplate outside_errors/> }.into_view()
}> }>
<main class="p-4 md:p-8 md:px-16"> <main class="p-4 md:p-8 md:px-16">
<Routes> <Routes>
<Route path="/" view=Home /> <Route path="/" view=Home/>
<Route path="/extensions/order_to_pdf" view=Pdf />
</Routes> </Routes>
</main> </main>
</Router> </Router>

View file

@ -13,21 +13,21 @@ mod queries;
mod app; mod app;
mod components; mod components;
mod error_template;
mod routes; mod routes;
mod error_template;
#[tokio::main] #[tokio::main]
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
async fn main() -> Result<(), std::io::Error> { async fn main() -> Result<(), std::io::Error> {
use app::*;
use axum::{ use std::sync::Arc;
middleware, use axum::{middleware, routing::{get, post}, Router};
routing::{get, post},
Router,
};
use fileserv::file_and_error_handler;
use leptos::*; use leptos::*;
use leptos_axum::{generate_route_list, LeptosRoutes}; use leptos_axum::{generate_route_list, LeptosRoutes };
use app::*;
use fileserv::file_and_error_handler;
use saleor_app_sdk::middleware::verify_webhook_signature::webhook_signature_verifier;
use tokio::sync::Mutex;
use saleor_app_sdk::{ use saleor_app_sdk::{
cargo_info, cargo_info,
config::Config, config::Config,
@ -35,12 +35,6 @@ async fn main() -> Result<(), std::io::Error> {
webhooks::{AsyncWebhookEventType, WebhookManifestBuilder}, webhooks::{AsyncWebhookEventType, WebhookManifestBuilder},
SaleorApp, SaleorApp,
}; };
use saleor_app_sdk::{
manifest::{extension::AppExtensionBuilder, AppExtensionMount, AppExtensionTarget},
middleware::verify_webhook_signature::webhook_signature_verifier,
};
use std::sync::Arc;
use tokio::sync::Mutex;
use crate::routes::api::{manifest::manifest, register::register, webhooks::webhooks}; use crate::routes::api::{manifest::manifest, register::register, webhooks::webhooks};
@ -55,23 +49,51 @@ async fn main() -> Result<(), std::io::Error> {
let saleor_app = SaleorApp::new(&config).unwrap(); let saleor_app = SaleorApp::new(&config).unwrap();
let app_manifest = AppManifestBuilder::new(&config, cargo_info!()) let app_manifest = AppManifestBuilder::new(&config, cargo_info!())
.add_permission(AppPermission::ManageProducts) .add_webhook(
.add_extension( WebhookManifestBuilder::new(&config)
AppExtensionBuilder::new() .set_query(
.set_url("/extensions/order_to_pdf") r#"
.set_label("Order to PDF") subscription QueryProductsChanged {
.add_permissions(vec![ event {
AppPermission::ManageOrders, ... on ProductUpdated {
AppPermission::ManageProducts, product {
AppPermission::ManageProductTypesAndAttributes, ... BaseProduct
}
}
... on ProductCreated {
product {
... BaseProduct
}
}
... on ProductDeleted {
product {
... BaseProduct
}
}
}
}
fragment BaseProduct on Product {
id
slug
name
category {
slug
}
}
"#,
)
.add_async_events(vec![
AsyncWebhookEventType::ProductCreated,
AsyncWebhookEventType::ProductUpdated,
AsyncWebhookEventType::ProductDeleted,
]) ])
.set_mount(AppExtensionMount::OrderDetailsMoreActions)
.set_target(AppExtensionTarget::Popup)
.build(), .build(),
) )
.add_permission(AppPermission::ManageProducts)
.build(); .build();
let app_state = AppState { let app_state = AppState{
manifest: app_manifest, manifest: app_manifest,
config: config.clone(), config: config.clone(),
saleor_app: Arc::new(Mutex::new(saleor_app)), saleor_app: Arc::new(Mutex::new(saleor_app)),
@ -79,22 +101,12 @@ async fn main() -> Result<(), std::io::Error> {
}; };
let state_1 = app_state.clone(); let state_1 = app_state.clone();
let app = Router::new() let app =
.leptos_routes_with_context( Router::new()
&app_state, .leptos_routes_with_context(&app_state, routes,move || provide_context(state_1.clone()) , App)
routes,
move || provide_context(state_1.clone()),
App,
)
.fallback(file_and_error_handler) .fallback(file_and_error_handler)
.route( .route("/api/webhooks", post(webhooks).route_layer(middleware::from_fn(webhook_signature_verifier)))
"/api/webhooks", .route("/api/register", post(register).route_layer(middleware::from_fn(webhook_signature_verifier)))
post(webhooks).route_layer(middleware::from_fn(webhook_signature_verifier)),
)
.route(
"/api/register",
post(register).route_layer(middleware::from_fn(webhook_signature_verifier)),
)
.route("/api/manifest", get(manifest)) .route("/api/manifest", get(manifest))
.with_state(app_state.clone()); .with_state(app_state.clone());
@ -110,19 +122,19 @@ async fn main() -> Result<(), std::io::Error> {
.await?; .await?;
tracing::debug!("listening on {}", listener.local_addr()?); tracing::debug!("listening on {}", listener.local_addr()?);
let _ = axum::serve(listener, app.into_make_service()).await; let _= axum::serve(listener, app.into_make_service())
.await;
Ok(()) Ok(())
} }
#[cfg(not(feature = "ssr"))] #[cfg(not(feature = "ssr"))]
pub fn main() { pub fn main() {
use saleor_app_sdk::bridge::AppBridge;
let app_bridge = AppBridge::new(Some(true)).unwrap();
// no client-side main function // no client-side main function
// unless we want this to work with e.g., Trunk for a purely client-side app // unless we want this to work with e.g., Trunk for a purely client-side app
// see lib.rs for hydration function instead // see lib.rs for hydration function instead
} }
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
use saleor_app_sdk::config::Config; use saleor_app_sdk::config::Config;
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
@ -132,13 +144,8 @@ pub fn trace_to_std(config: &Config) -> Result<(), envy::Error> {
let filter = EnvFilter::builder() let filter = EnvFilter::builder()
.with_default_directive(LevelFilter::DEBUG.into()) .with_default_directive(LevelFilter::DEBUG.into())
.from_env() .from_env().unwrap()
.unwrap() .add_directive(format!("{}={}", env!("CARGO_PKG_NAME"), config.log_level).parse().unwrap());
.add_directive(
format!("{}={}", env!("CARGO_PKG_NAME"), config.log_level)
.parse()
.unwrap(),
);
tracing_subscriber::fmt() tracing_subscriber::fmt()
.with_max_level(config.log_level) .with_max_level(config.log_level)
.with_env_filter(filter) .with_env_filter(filter)
@ -147,3 +154,5 @@ pub fn trace_to_std(config: &Config) -> Result<(), envy::Error> {
.init(); .init();
Ok(()) Ok(())
} }

View file

@ -1 +0,0 @@
pub mod order_to_pdf;

View file

@ -1,9 +0,0 @@
use leptos::*;
#[component]
pub fn Pdf() -> impl IntoView {
view! {
<h1>Yello!</h1>
<p class="italic text-lg">r#"Loading AppBridge, please wait..."#</p>
}
}

View file

@ -1,4 +1,3 @@
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
pub mod api; pub mod api;
pub mod extensions;
pub mod home; pub mod home;

View file

@ -1,15 +0,0 @@
{
"lspconfig": {
"rust_analyzer": {
"rust-analyzer.cargo.features": "all"
/*
use this only when working with leptos
*/
// "rust-analyzer.rustfmt.overrideCommand": [
// "leptosfmt",
// "--stdin",
// "--rustfmt"
// ]
}
}
}

View file

@ -48,7 +48,7 @@ tracing-subscriber = { workspace = true, optional = true }
## Needed for bridge ## Needed for bridge
wasm-bindgen = { workspace = true, optional = true } wasm-bindgen = { workspace = true, optional = true }
serde-wasm-bindgen = { version = "0.6.5", optional = true } serde-wasm-bindgen = { version = "0.6.5", optional = true }
# bus = { version = "2.4.1", optional = true } bus = { version = "2.4.1", optional = true }
[dependencies.web-sys] [dependencies.web-sys]
optional = true optional = true
@ -66,7 +66,7 @@ features = [
[dev-dependencies] [dev-dependencies]
[features] [features]
default = [] default = ["middleware", "redis_apl", "webhook_utils", "tracing"]
middleware = [ middleware = [
"dep:axum", "dep:axum",
"dep:jsonwebtoken", "dep:jsonwebtoken",
@ -80,7 +80,7 @@ webhook_utils = ["dep:http"]
tracing = ["dep:tracing", "dep:tracing-subscriber"] tracing = ["dep:tracing", "dep:tracing-subscriber"]
bridge = [ bridge = [
"dep:wasm-bindgen", "dep:wasm-bindgen",
# "dep:bus", "dep:bus",
"dep:serde-wasm-bindgen", "dep:serde-wasm-bindgen",
"dep:web-sys", "dep:web-sys",
] ]

View file

@ -1,66 +1,65 @@
use crate::locales::LocaleCode; use crate::locales::LocaleCode;
use super::ThemeType; use super::ThemeType;
// use bus::{Bus, BusReader}; use bus::{Bus, BusReader};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
// use strum_macros::EnumIter; use strum_macros::EnumIter;
// use web_sys::js_sys::Object;
// pub struct EventChannels { pub struct EventChannels {
// pub handshake: Bus<PayloadHanshake>, pub handshake: Bus<PayloadHanshake>,
// pub response: Bus<PayloadResponse>, pub response: Bus<PayloadResponse>,
// pub redirect: Bus<PayloadRedirect>, pub redirect: Bus<PayloadRedirect>,
// pub theme: Bus<PayloadTheme>, pub theme: Bus<PayloadTheme>,
// pub locale_changed: Bus<PayloadLocaleChanged>, pub locale_changed: Bus<PayloadLocaleChanged>,
// pub token_refreshed: Bus<PayloadTokenRefreshed>, pub token_refreshed: Bus<PayloadTokenRefreshed>,
// } }
//
// impl EventChannels {
// pub fn new() -> Self {
// Self {
// handshake: Bus::new(10),
// response: Bus::new(10),
// redirect: Bus::new(10),
// theme: Bus::new(10),
// locale_changed: Bus::new(10),
// token_refreshed: Bus::new(10),
// }
// }
//
// pub fn subscribe_handshake(&mut self) -> BusReader<PayloadHanshake> {
// self.handshake.add_rx()
// }
//
// pub fn subscribe_response(&mut self) -> BusReader<PayloadResponse> {
// self.response.add_rx()
// }
//
// pub fn subscribe_redirect(&mut self) -> BusReader<PayloadRedirect> {
// self.redirect.add_rx()
// }
//
// pub fn subscribe_theme(&mut self) -> BusReader<PayloadTheme> {
// self.theme.add_rx()
// }
//
// pub fn subscribe_locale_changed(&mut self) -> BusReader<PayloadLocaleChanged> {
// self.locale_changed.add_rx()
// }
//
// pub fn subscribe_token_refreshed(&mut self) -> BusReader<PayloadTokenRefreshed> {
// self.token_refreshed.add_rx()
// }
// }
// #[derive(EnumIter, Debug)] impl EventChannels {
// pub enum EventType { pub fn new() -> Self {
// Handshake, Self {
// Response, handshake: Bus::new(10),
// Redirect, response: Bus::new(10),
// Theme, redirect: Bus::new(10),
// LocaleChanged, theme: Bus::new(10),
// TokenRefreshed, locale_changed: Bus::new(10),
// } token_refreshed: Bus::new(10),
}
}
pub fn subscribe_handshake(&mut self) -> BusReader<PayloadHanshake> {
self.handshake.add_rx()
}
pub fn subscribe_response(&mut self) -> BusReader<PayloadResponse> {
self.response.add_rx()
}
pub fn subscribe_redirect(&mut self) -> BusReader<PayloadRedirect> {
self.redirect.add_rx()
}
pub fn subscribe_theme(&mut self) -> BusReader<PayloadTheme> {
self.theme.add_rx()
}
pub fn subscribe_locale_changed(&mut self) -> BusReader<PayloadLocaleChanged> {
self.locale_changed.add_rx()
}
pub fn subscribe_token_refreshed(&mut self) -> BusReader<PayloadTokenRefreshed> {
self.token_refreshed.add_rx()
}
}
#[derive(EnumIter, Debug)]
pub enum EventType {
Handshake,
Response,
Redirect,
Theme,
LocaleChanged,
TokenRefreshed,
}
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
#[serde(tag = "type", content = "payload")] #[serde(tag = "type", content = "payload")]
@ -72,7 +71,6 @@ pub enum Event {
Theme(PayloadTheme), Theme(PayloadTheme),
LocaleChanged(PayloadLocaleChanged), LocaleChanged(PayloadLocaleChanged),
TokenRefreshed(PayloadTokenRefreshed), TokenRefreshed(PayloadTokenRefreshed),
NotifyReady(String),
} }
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]

View file

@ -4,17 +4,18 @@ use std::str::FromStr;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use strum_macros::{EnumString, IntoStaticStr}; use strum_macros::{EnumString, IntoStaticStr};
use tracing::{debug, error, warn};
use wasm_bindgen::{closure::Closure, JsCast, JsValue}; use wasm_bindgen::{closure::Closure, JsCast, JsValue};
use crate::{locales::LocaleCode, manifest::AppPermission}; use crate::{locales::LocaleCode, manifest::AppPermission};
use self::event::Event; use self::event::{Event, EventChannels};
use web_sys::console; use web_sys::console;
pub struct AppBridge { pub struct AppBridge {
pub state: AppBridgeState, pub state: AppBridgeState,
pub referer_origin: Option<String>, pub referer_origin: Option<String>,
// pub event_channels: EventChannels, pub event_channels: EventChannels,
/** /**
* Should automatically emit Actions.NotifyReady. * Should automatically emit Actions.NotifyReady.
* If app loading time is longer, this can be disabled and sent manually. * If app loading time is longer, this can be disabled and sent manually.
@ -76,7 +77,7 @@ impl AppBridgeState {
state.locale = loc state.locale = loc
} }
} }
// debug!("state from window: {:?}", &state); debug!("state from window: {:?}", &state);
console::log_1(&format!("state from window: {:?}", &state).into()); console::log_1(&format!("state from window: {:?}", &state).into());
Ok(state) Ok(state)
} }
@ -121,10 +122,10 @@ impl Default for ThemeType {
impl AppBridge { impl AppBridge {
pub fn new(auto_notify_ready: Option<bool>) -> Result<Self, AppBridgeError> { pub fn new(auto_notify_ready: Option<bool>) -> Result<Self, AppBridgeError> {
// debug!("creating app bridge"); debug!("creating app bridge");
console::log_1(&"creating app bridge".into()); console::log_1(&"creating app bridge".into());
if web_sys::Window::is_type_of(&JsValue::from_str("undefined")) { if web_sys::Window::is_type_of(&JsValue::from_str("undefined")) {
// error!("Window is undefined"); error!("Window is undefined");
console::log_1(&"Window is undefined".into()); console::log_1(&"Window is undefined".into());
return Err(AppBridgeError::WindowIsUndefined); return Err(AppBridgeError::WindowIsUndefined);
} }
@ -136,7 +137,7 @@ impl AppBridge {
}) })
}); });
if referrer.is_none() { if referrer.is_none() {
// warn!("Referrer origin is none"); warn!("Referrer origin is none");
console::log_1(&"Referrer origin is none".into()); console::log_1(&"Referrer origin is none".into());
} }
@ -147,6 +148,7 @@ impl AppBridge {
Err(e) => return Err(AppBridgeError::JsValue(e)), Err(e) => return Err(AppBridgeError::JsValue(e)),
}, },
referer_origin: referrer, referer_origin: referrer,
event_channels: EventChannels::new(),
}; };
if bridge.auto_notify_ready.unwrap_or(false) { if bridge.auto_notify_ready.unwrap_or(false) {
bridge.notify_ready()?; bridge.notify_ready()?;
@ -159,7 +161,7 @@ impl AppBridge {
let cb = Closure::wrap(Box::new(|e: JsValue| { let cb = Closure::wrap(Box::new(|e: JsValue| {
let event_data: Result<SaleorIframeEvent, _> = serde_wasm_bindgen::from_value(e); let event_data: Result<SaleorIframeEvent, _> = serde_wasm_bindgen::from_value(e);
web_sys::console::log_1(&format!("{:?}", &event_data).into()); web_sys::console::log_1(&format!("{:?}", &event_data).into());
// debug!("{:?}", &event_data); debug!("{:?}", &event_data);
}) as Box<dyn FnMut(_)>); }) as Box<dyn FnMut(_)>);
window window
.add_event_listener_with_callback("message", &cb.as_ref().unchecked_ref()) .add_event_listener_with_callback("message", &cb.as_ref().unchecked_ref())
@ -180,8 +182,7 @@ impl AppBridge {
todo!() todo!()
} }
pub fn notify_ready(&mut self) -> Result<&mut Self, AppBridgeError> { pub fn notify_ready(&mut self) -> Result<&mut Self, AppBridgeError> {
self.dispatch_event(Event::NotifyReady("{}".to_owned()))?; todo!()
Ok(self)
} }
} }

2
sdk/src/fetch_jwks.rs Normal file
View file

@ -0,0 +1,2 @@

View file

@ -9,8 +9,6 @@ pub mod manifest;
pub mod middleware; pub mod middleware;
pub mod webhooks; pub mod webhooks;
use anyhow::bail;
use apl::{AplType, APL}; use apl::{AplType, APL};
use config::Config; use config::Config;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View file

@ -1,5 +1,4 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
pub mod extension;
use crate::{config::Config, webhooks::WebhookManifest}; use crate::{config::Config, webhooks::WebhookManifest};
@ -48,11 +47,6 @@ pub enum AppExtensionMount {
OrderOverviewCreate, OrderOverviewCreate,
OrderOverviewMoreActions, OrderOverviewMoreActions,
} }
impl Default for AppExtensionMount {
fn default() -> Self {
Self::ProductOverviewMoreActions
}
}
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")] #[serde(rename_all = "SCREAMING_SNAKE_CASE")]
@ -60,13 +54,8 @@ pub enum AppExtensionTarget {
Popup, Popup,
AppPage, AppPage,
} }
impl Default for AppExtensionTarget {
fn default() -> Self {
Self::Popup
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct AppExtension { pub struct AppExtension {
/** Name which will be displayed in the dashboard */ /** Name which will be displayed in the dashboard */
@ -199,20 +188,6 @@ impl AppManifestBuilder {
self.manifest.permissions.append(&mut permissions); self.manifest.permissions.append(&mut permissions);
self self
} }
pub fn add_extension(mut self, extension: AppExtension) -> Self {
match &mut self.manifest.extensions {
Some(e) => e.push(extension),
None => self.manifest.extensions = Some(vec![extension]),
}
self
}
pub fn add_extensions(mut self, mut extensions: Vec<AppExtension>) -> Self {
match &mut self.manifest.extensions {
Some(e) => e.append(&mut extensions),
None => self.manifest.extensions = Some(extensions),
}
self
}
pub fn build(self) -> AppManifest { pub fn build(self) -> AppManifest {
self.manifest self.manifest
} }

View file

@ -1,58 +0,0 @@
use super::{AppExtension, AppExtensionMount, AppExtensionTarget, AppPermission};
pub struct AppExtensionBuilder {
pub extension: AppExtension,
}
impl AppExtensionBuilder {
pub fn new() -> Self {
Self {
extension: AppExtension::default(),
}
}
/** Name which will be displayed in the dashboard */
pub fn set_label(mut self, label: &str) -> Self {
label.clone_into(&mut self.extension.label);
self
}
/** the place where the extension will be mounted */
pub fn set_mount(mut self, mount: AppExtensionMount) -> Self {
self.extension.mount = mount;
self
}
/** Method of presenting the interface
`POPUP` will present the interface in a modal overlay
`APP_PAGE` will navigate to the application page
@default `POPUP`
*/
pub fn set_target(mut self, target: AppExtensionTarget) -> Self {
self.extension.target = target;
self
}
pub fn add_permission(mut self, permission: AppPermission) -> Self {
self.extension.permissions.push(permission);
self
}
pub fn add_permissions(mut self, mut permission: Vec<AppPermission>) -> Self {
self.extension.permissions.append(&mut permission);
self
}
/** URL of the view to display,
you can skip the domain and protocol when target is set to `APP_PAGE`, or when your manifest defines an `appUrl`.
When target is set to `POPUP`, the url will be used to render an `<iframe>`.
*/
pub fn set_url(mut self, url: &str) -> Self {
url.clone_into(&mut self.extension.url);
self
}
pub fn build(self) -> AppExtension {
self.extension
}
}

1
sdk/src/tests/mod.rs Normal file
View file

@ -0,0 +1 @@

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -4,6 +4,7 @@ use std::{
fs::{self}, fs::{self},
io::ErrorKind, io::ErrorKind,
}; };
use tinytemplate::TinyTemplate;
use crate::{ use crate::{
app::{AppState, SitemapConfig}, app::{AppState, SitemapConfig},
@ -315,8 +316,12 @@ async fn update_or_create<T: Serialize + Clone>(
for affected in affected_urls.iter_mut() { for affected in affected_urls.iter_mut() {
match affected { match affected {
AffectedType::Data(url) => { AffectedType::Data(url) => {
match Url::new(data.clone(), sitemap_config, item.clone(), rel_item.clone()) match Url::new(
{ data.clone(),
&sitemap_config,
item.clone(),
rel_item.clone(),
) {
Ok(new_url) => { Ok(new_url) => {
url.url = new_url.url; url.url = new_url.url;
url.data = new_url.data; url.data = new_url.data;
@ -333,7 +338,7 @@ async fn update_or_create<T: Serialize + Clone>(
let new_data: ProductCreated = url.clone().into(); let new_data: ProductCreated = url.clone().into();
match Url::new( match Url::new(
new_data, new_data,
sitemap_config, &sitemap_config,
url.clone().data, url.clone().data,
Some(item.clone()), Some(item.clone()),
) { ) {
@ -349,7 +354,7 @@ async fn update_or_create<T: Serialize + Clone>(
let new_data: CollectionCreated = url.clone().into(); let new_data: CollectionCreated = url.clone().into();
match Url::new( match Url::new(
new_data, new_data,
sitemap_config, &sitemap_config,
url.clone().data, url.clone().data,
Some(item.clone()), Some(item.clone()),
) { ) {
@ -365,7 +370,7 @@ async fn update_or_create<T: Serialize + Clone>(
let new_data: PageCreated = url.clone().into(); let new_data: PageCreated = url.clone().into();
match Url::new( match Url::new(
new_data, new_data,
sitemap_config, &sitemap_config,
url.clone().data, url.clone().data,
Some(item.clone()), Some(item.clone()),
) { ) {
@ -381,7 +386,7 @@ async fn update_or_create<T: Serialize + Clone>(
let new_data: CollectionCreated = url.clone().into(); let new_data: CollectionCreated = url.clone().into();
match Url::new( match Url::new(
new_data, new_data,
sitemap_config, &sitemap_config,
url.clone().data, url.clone().data,
Some(item.clone()), Some(item.clone()),
) { ) {

View file

@ -155,11 +155,7 @@ pub async fn regenerate(state: AppState, saleor_api_url: String) -> anyhow::Resu
slug: p.slug.clone(), slug: p.slug.clone(),
typ: ItemType::Product, typ: ItemType::Product,
}, },
p.category.clone().map(|c| ItemData { None,
id: c.id.inner().to_owned(),
slug: c.slug,
typ: ItemType::Category,
}),
) { ) {
Ok(u) => Some(u), Ok(u) => Some(u),
Err(e) => { Err(e) => {

View file

@ -4,7 +4,8 @@ use std::time::Duration;
use crate::{ use crate::{
create_app, create_app,
sitemap::{ItemType, UrlSet}, queries::event_subjects_updated::{Category, Product, ProductUpdated},
sitemap::{ItemType, Url, UrlSet},
}; };
use async_std::task::sleep; use async_std::task::sleep;
use axum::{ use axum::{
@ -60,12 +61,11 @@ pub async fn app_runs_and_responses() {
#[tokio::test] #[tokio::test]
#[traced_test] #[traced_test]
#[serial] #[serial]
//TODO: This test is busted or smt
async fn update_event_updates_correctly() { async fn update_event_updates_correctly() {
let mut app = init_test_app().await; let mut app = init_test_app().await;
let (_, sitemap_config) = testing_configs(); let (_, sitemap_config) = testing_configs();
let mut evn = gen_random_url_set(500, &sitemap_config); let mut evn = gen_random_url_set(50, &sitemap_config);
for (body, _, webhook_type) in evn.clone() { for (body, _, webhook_type) in evn.clone() {
app = create_query(app, body, webhook_type).await; app = create_query(app, body, webhook_type).await;
} }
@ -272,22 +272,7 @@ fn urlset_serialisation_isnt_lossy() {
let deserialized_url_set: UrlSet = serde_cbor::de::from_slice(&file_str).unwrap(); let deserialized_url_set: UrlSet = serde_cbor::de::from_slice(&file_str).unwrap();
assert_eq!(url_set, deserialized_url_set); assert_eq!(url_set, deserialized_url_set);
} }
//TODO: TEST UPDATES AND DELETES, UPDATING URL CREATES A NEW ENTRY INSTEAD OF EDITING PREVIOUS ONE
// #[rstest]
// #[traced_test]
// #[parallel]
// fn desereialize_cbor() {
// std::fs::write(
// "db.json",
// serde_json::to_string_pretty(
// &serde_cbor::de::from_slice::<UrlSet>(&std::fs::read("db.cbor").unwrap()).unwrap(),
// )
// .unwrap(),
// )
// .unwrap();
//
// // assert_eq!(url_set, deserialized_url_set);
// }
// #[rstest] // #[rstest]
// #[traced_test] // #[traced_test]

View file

@ -1,6 +1,6 @@
use axum::{ use axum::{
body::Body, body::Body,
http::{Request, StatusCode}, http::{Request, Response, StatusCode},
routing::RouterIntoService, routing::RouterIntoService,
}; };
use rand::{ use rand::{
@ -261,35 +261,11 @@ pub fn gen_random_url_set(
) -> Vec<(String, Url, EitherWebhookType)> { ) -> Vec<(String, Url, EitherWebhookType)> {
let mut res: Vec<(String, Url, EitherWebhookType)> = vec![]; let mut res: Vec<(String, Url, EitherWebhookType)> = vec![];
for _ in 0..len { for _ in 0..len {
let slug = random_word::gen(random_word::Lang::En).to_owned() let slug = random_word::gen(random_word::Lang::En).to_owned();
+ "_" let id = cynic::Id::new(slug.to_owned() + "_ID");
+ random_word::gen(random_word::Lang::En)
+ "_"
+ random_word::gen(random_word::Lang::En)
+ "_"
+ random_word::gen(random_word::Lang::En)
+ "_"
+ random_word::gen(random_word::Lang::En)
+ "_"
+ random_word::gen(random_word::Lang::En)
+ "_"
+ random_word::gen(random_word::Lang::En);
let id = cynic::Id::new("ID_".to_owned() + &slug.clone());
let mut rel_slug = random_word::gen(random_word::Lang::En).to_owned() let mut rel_slug = random_word::gen(random_word::Lang::En).to_owned();
+ "_" let mut rel_id = cynic::Id::new(rel_slug.to_owned() + "_ID");
+ random_word::gen(random_word::Lang::En)
+ "_"
+ random_word::gen(random_word::Lang::En)
+ "_"
+ random_word::gen(random_word::Lang::En)
+ "_"
+ random_word::gen(random_word::Lang::En)
+ "_"
+ random_word::gen(random_word::Lang::En)
+ "_"
+ random_word::gen(random_word::Lang::En);
let mut rel_id = cynic::Id::new("ID_".to_owned() + &rel_slug.clone());
match rand::random::<ItemType>() { match rand::random::<ItemType>() {
ItemType::Product => { ItemType::Product => {