Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7be7420c4f | ||
|
|
34c4e87d14 | ||
|
|
e61c757633 | ||
|
|
cc1f8fba72 |
@@ -132,6 +132,16 @@ fun WebViewScreen(
|
||||
AndroidView(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
factory = { context ->
|
||||
fun openExternalUrl(url: String) {
|
||||
try {
|
||||
val intent = android.content.Intent(
|
||||
android.content.Intent.ACTION_VIEW,
|
||||
android.net.Uri.parse(url),
|
||||
)
|
||||
context.startActivity(intent)
|
||||
} catch (_: Exception) {}
|
||||
}
|
||||
|
||||
WebView(context).apply {
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
@@ -220,13 +230,7 @@ fun WebViewScreen(
|
||||
// Keep navigation within the Archipelago server
|
||||
if (url.startsWith(serverUrl)) return false
|
||||
// Open external URLs in the system browser
|
||||
try {
|
||||
val intent = android.content.Intent(
|
||||
android.content.Intent.ACTION_VIEW,
|
||||
android.net.Uri.parse(url),
|
||||
)
|
||||
context.startActivity(intent)
|
||||
} catch (_: Exception) {}
|
||||
openExternalUrl(url)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -243,18 +247,30 @@ fun WebViewScreen(
|
||||
isUserGesture: Boolean,
|
||||
resultMsg: android.os.Message?,
|
||||
): Boolean {
|
||||
// Extract the URL from the hit test
|
||||
val data = view?.hitTestResult?.extra
|
||||
if (data != null) {
|
||||
try {
|
||||
val intent = android.content.Intent(
|
||||
android.content.Intent.ACTION_VIEW,
|
||||
android.net.Uri.parse(data),
|
||||
)
|
||||
context.startActivity(intent)
|
||||
} catch (_: Exception) {}
|
||||
val transport = resultMsg?.obj as? WebView.WebViewTransport
|
||||
?: return false
|
||||
|
||||
val popup = WebView(context).apply {
|
||||
settings.javaScriptEnabled = true
|
||||
webViewClient = object : WebViewClient() {
|
||||
override fun shouldOverrideUrlLoading(
|
||||
view: WebView?,
|
||||
request: WebResourceRequest?,
|
||||
): Boolean {
|
||||
val url = request?.url?.toString() ?: return true
|
||||
openExternalUrl(url)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
|
||||
if (url != null) openExternalUrl(url)
|
||||
view?.stopLoading()
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
transport.webView = popup
|
||||
resultMsg.sendToTarget()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# Changelog
|
||||
|
||||
## v1.7.79-alpha (2026-05-20)
|
||||
|
||||
- Saleor now installs the official Saleor Storefront as part of the stack, built from the pinned `saleor/storefront` source and served as the customer-facing shop on port `9011`.
|
||||
- Saleor app launches now open the storefront while the admin dashboard remains available on port `9010` with the generated `admin@example.com` credentials shown in Archipelago.
|
||||
- Public Nginx Proxy Manager hosts forwarding to the Saleor storefront also expose same-origin `/graphql/`, so public storefront domains can talk to the local Saleor API without mixed-content or private-LAN reachability failures.
|
||||
- Saleor stack metadata, marketplace descriptions, catalog ports, scanner exclusions, and app-session routing now describe the storefront/dashboard/API split explicitly.
|
||||
|
||||
## v1.7.78-alpha (2026-05-20)
|
||||
|
||||
- Public Nginx Proxy Manager hosts for Saleor now keep browser GraphQL calls same-origin at `/graphql/` and proxy them to the local API on `8000`, fixing `Failed to fetch` when a public domain such as `noderunner.shop` was loaded from devices that cannot reach the node's private LAN/tailnet API address.
|
||||
- Saleor's validated stack changes are now release-ready: dashboard origins on port `9010` are explicitly allowed for dashboard/API calls, preserving the working test-node install path for production nodes.
|
||||
- NetBird launches now stay pinned to the unified dashboard/proxy origin on port `8087` instead of following stale runtime-discovered server URLs on `8086`.
|
||||
- NetBird's local nginx proxy now routes browser API, OAuth, relay, and WebSocket traffic through `host.containers.internal:8086` instead of a hard-coded rootless Podman gateway IP, and includes the upstream `management.ProxyService` gRPC path.
|
||||
- The mobile credentials interstitial now keeps credential lists scrollable and action buttons reachable in both My Apps and the mobile app icon grid.
|
||||
- Android WebView popup windows now hand external popup URLs to the system browser, covering app login/signup flows that open secondary windows.
|
||||
- Validation passed with `git diff --check`, `cargo check -p archipelago`, and the focused `npm test -- src/views/appSession/__tests__/appSessionConfig.test.ts` suite.
|
||||
|
||||
## v1.7.77-alpha (2026-05-20)
|
||||
|
||||
- Saleor first-use now exposes generated credentials through Archipelago instead of leaving users at an unexplained dashboard login: App Details shows copyable `admin@example.com` credentials, and My Apps/mobile icon launches show a pre-launch credentials modal.
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
"id": "saleor",
|
||||
"title": "Saleor",
|
||||
"version": "3.23",
|
||||
"description": "Composable commerce platform with GraphQL API, dashboard, worker, mail testing, and tracing.",
|
||||
"description": "Composable commerce platform with customer storefront, GraphQL API, dashboard, worker, mail testing, and tracing.",
|
||||
"icon": "/assets/img/app-icons/saleor.svg",
|
||||
"author": "Saleor",
|
||||
"category": "commerce",
|
||||
@@ -76,9 +76,9 @@
|
||||
"dockerImage": "ghcr.io/saleor/saleor:3.23",
|
||||
"repoUrl": "https://github.com/saleor/saleor",
|
||||
"containerConfig": {
|
||||
"ports": ["9010:80", "8000:8000", "8025:8025", "16686:16686"],
|
||||
"ports": ["9011:80", "9010:80", "8000:8000", "8025:8025", "16686:16686"],
|
||||
"volumes": ["/var/lib/archipelago/saleor:/app/media", "/var/lib/archipelago/saleor-db:/var/lib/postgresql/data"],
|
||||
"notes": "Installed as a Saleor stack: dashboard on 9010, API on 8000, Mailpit on 8025, and Jaeger on 16686. Supporting containers include PostgreSQL, Valkey, Celery worker, and services required by Saleor."
|
||||
"notes": "Installed as a Saleor stack: customer storefront on 9011, admin dashboard on 9010, API on 8000, Mailpit on 8025, and Jaeger on 16686. Supporting containers include PostgreSQL, Valkey, Celery worker, and services required by Saleor."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
Generated
+1
-1
@@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "archipelago"
|
||||
version = "1.7.77-alpha"
|
||||
version = "1.7.78-alpha"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"archipelago-container",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "archipelago"
|
||||
version = "1.7.77-alpha"
|
||||
version = "1.7.79-alpha"
|
||||
edition = "2021"
|
||||
description = "Archipelago Bitcoin Node OS - Native backend"
|
||||
authors = ["Archipelago Team"]
|
||||
|
||||
@@ -244,6 +244,8 @@ async fn repair_saleor_network_aliases() {
|
||||
("saleor-api", "api"),
|
||||
("saleor-worker", "worker"),
|
||||
("saleor", "saleor"),
|
||||
("saleor-storefront", "storefront"),
|
||||
("saleor-storefront-app", "storefront-app"),
|
||||
] {
|
||||
let exists = tokio::process::Command::new("podman")
|
||||
.args(["container", "exists", container])
|
||||
@@ -271,6 +273,7 @@ async fn repair_saleor_network_aliases() {
|
||||
.output()
|
||||
.await;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async fn run_required_stack_command(
|
||||
@@ -445,6 +448,9 @@ const NETBIRD_SERVER_IMAGE: &str = "docker.io/netbirdio/netbird-server:0.71.2";
|
||||
const NETBIRD_PROXY_IMAGE: &str = "docker.io/library/nginx:1.27-alpine";
|
||||
const SALEOR_API_IMAGE: &str = "ghcr.io/saleor/saleor:3.23";
|
||||
const SALEOR_DASHBOARD_IMAGE: &str = "ghcr.io/saleor/saleor-dashboard:3.23";
|
||||
const SALEOR_STOREFRONT_IMAGE: &str = "localhost/archipelago/saleor-storefront:6eb0b97";
|
||||
const SALEOR_STOREFRONT_CONTEXT: &str =
|
||||
"https://github.com/saleor/storefront.git#6eb0b97b25bd4344d8139515a1cabf763d703b39";
|
||||
const SALEOR_POSTGRES_IMAGE: &str = "docker.io/library/postgres:15-alpine";
|
||||
const SALEOR_VALKEY_IMAGE: &str = "docker.io/valkey/valkey:8.1-alpine";
|
||||
const SALEOR_JAEGER_IMAGE: &str = "docker.io/jaegertracing/jaeger:latest";
|
||||
@@ -1655,6 +1661,8 @@ impl RpcHandler {
|
||||
"saleor-api",
|
||||
"saleor-worker",
|
||||
"saleor",
|
||||
"saleor-storefront",
|
||||
"saleor-storefront-app",
|
||||
],
|
||||
)
|
||||
.await?
|
||||
@@ -1662,7 +1670,7 @@ impl RpcHandler {
|
||||
return Ok(adopted);
|
||||
}
|
||||
|
||||
install_log("INSTALL START: saleor stack (postgres + valkey + api + worker + dashboard)")
|
||||
install_log("INSTALL START: saleor stack (postgres + valkey + api + worker + dashboard + storefront)")
|
||||
.await;
|
||||
info!("Installing Saleor stack");
|
||||
|
||||
@@ -1691,6 +1699,8 @@ impl RpcHandler {
|
||||
"saleor",
|
||||
"saleor-api",
|
||||
"saleor-worker",
|
||||
"saleor-storefront",
|
||||
"saleor-storefront-app",
|
||||
"saleor-db",
|
||||
"saleor-cache",
|
||||
"saleor-jaeger",
|
||||
@@ -1716,6 +1726,7 @@ impl RpcHandler {
|
||||
"/var/lib/archipelago/saleor",
|
||||
"/var/lib/archipelago/saleor-db",
|
||||
"/var/lib/archipelago/saleor-cache",
|
||||
"/var/lib/archipelago/saleor-storefront",
|
||||
])
|
||||
.output()
|
||||
.await;
|
||||
@@ -1724,6 +1735,7 @@ impl RpcHandler {
|
||||
"/var/lib/archipelago/saleor",
|
||||
"/var/lib/archipelago/saleor-db",
|
||||
"/var/lib/archipelago/saleor-cache",
|
||||
"/var/lib/archipelago/saleor-storefront",
|
||||
] {
|
||||
let _ = tokio::process::Command::new("sudo")
|
||||
.args(["chown", "-R", &format!("{}:{}", user, user), dir])
|
||||
@@ -1740,9 +1752,16 @@ impl RpcHandler {
|
||||
let secret_key = super::config::read_or_generate_secret("saleor-secret-key").await;
|
||||
let admin_pass = super::config::read_or_generate_secret("saleor-admin-password").await;
|
||||
let host_ip = &self.config.host_ip;
|
||||
let dashboard_url = format!("http://{}:9010/", host_ip);
|
||||
let dashboard_origin = format!("http://{}:9010", host_ip);
|
||||
let dashboard_url = format!("{}/", dashboard_origin);
|
||||
let api_url = format!("http://{}:8000/graphql/", host_ip);
|
||||
let internal_api_url = "http://api:8000/graphql/";
|
||||
let storefront_origin = format!("http://{}:9011", host_ip);
|
||||
let allowed_hosts = format!("localhost,127.0.0.1,api,saleor-api,{}", host_ip);
|
||||
let allowed_client_hosts = format!(
|
||||
"{},{},http://localhost:9010,http://127.0.0.1:9010,http://localhost:9011,http://127.0.0.1:9011",
|
||||
dashboard_origin, storefront_origin
|
||||
);
|
||||
let database_url = format!("postgres://saleor:{}@db/saleor", db_pass);
|
||||
|
||||
let mut db_cmd = tokio::process::Command::new("podman");
|
||||
@@ -1884,6 +1903,10 @@ impl RpcHandler {
|
||||
"-e".to_string(),
|
||||
format!("DASHBOARD_URL={}", dashboard_url),
|
||||
"-e".to_string(),
|
||||
format!("ALLOWED_CLIENT_HOSTS={}", allowed_client_hosts),
|
||||
"-e".to_string(),
|
||||
format!("ALLOWED_GRAPHQL_ORIGINS={}", allowed_client_hosts),
|
||||
"-e".to_string(),
|
||||
format!("ALLOWED_HOSTS={}", allowed_hosts),
|
||||
];
|
||||
|
||||
@@ -2057,6 +2080,90 @@ user.save()
|
||||
]);
|
||||
run_required_stack_command("saleor", "create dashboard", &mut dashboard_cmd).await?;
|
||||
|
||||
let mut storefront_build_cmd = tokio::process::Command::new("podman");
|
||||
storefront_build_cmd.args([
|
||||
"build",
|
||||
"--network",
|
||||
"saleor-net",
|
||||
"--pull=always",
|
||||
"-t",
|
||||
SALEOR_STOREFRONT_IMAGE,
|
||||
"--build-arg",
|
||||
&format!("NEXT_PUBLIC_SALEOR_API_URL={}", internal_api_url),
|
||||
"--build-arg",
|
||||
&format!("NEXT_PUBLIC_STOREFRONT_URL={}", storefront_origin),
|
||||
"--build-arg",
|
||||
"NEXT_PUBLIC_DEFAULT_CHANNEL=default-channel",
|
||||
SALEOR_STOREFRONT_CONTEXT,
|
||||
]);
|
||||
run_required_stack_command("saleor", "build storefront", &mut storefront_build_cmd)
|
||||
.await?;
|
||||
|
||||
let mut storefront_cmd = tokio::process::Command::new("podman");
|
||||
storefront_cmd.args([
|
||||
"run",
|
||||
"-d",
|
||||
"--name",
|
||||
"saleor-storefront-app",
|
||||
"--network",
|
||||
"saleor-net",
|
||||
"--network-alias",
|
||||
"storefront-app",
|
||||
"--restart=unless-stopped",
|
||||
"--cap-drop=ALL",
|
||||
"--cap-add=CHOWN",
|
||||
"--cap-add=DAC_OVERRIDE",
|
||||
"--cap-add=FOWNER",
|
||||
"--cap-add=SETGID",
|
||||
"--cap-add=SETUID",
|
||||
"--security-opt=no-new-privileges:true",
|
||||
"--memory=512m",
|
||||
"--pids-limit=2048",
|
||||
"-e",
|
||||
&format!("NEXT_PUBLIC_SALEOR_API_URL={}", internal_api_url),
|
||||
"-e",
|
||||
&format!("NEXT_PUBLIC_STOREFRONT_URL={}", storefront_origin),
|
||||
"-e",
|
||||
"NEXT_PUBLIC_DEFAULT_CHANNEL=default-channel",
|
||||
SALEOR_STOREFRONT_IMAGE,
|
||||
]);
|
||||
run_required_stack_command("saleor", "create storefront app", &mut storefront_cmd).await?;
|
||||
|
||||
write_saleor_storefront_proxy_config().await?;
|
||||
let mut storefront_proxy_cmd = tokio::process::Command::new("podman");
|
||||
storefront_proxy_cmd.args([
|
||||
"run",
|
||||
"-d",
|
||||
"--name",
|
||||
"saleor-storefront",
|
||||
"--network",
|
||||
"saleor-net",
|
||||
"--network-alias",
|
||||
"storefront",
|
||||
"--restart=unless-stopped",
|
||||
"--cap-drop=ALL",
|
||||
"--cap-add=CHOWN",
|
||||
"--cap-add=DAC_OVERRIDE",
|
||||
"--cap-add=FOWNER",
|
||||
"--cap-add=NET_BIND_SERVICE",
|
||||
"--cap-add=SETGID",
|
||||
"--cap-add=SETUID",
|
||||
"--security-opt=no-new-privileges:true",
|
||||
"--memory=128m",
|
||||
"--pids-limit=1024",
|
||||
"-p",
|
||||
"9011:80",
|
||||
"-v",
|
||||
"/var/lib/archipelago/saleor-storefront/nginx.conf:/etc/nginx/conf.d/default.conf:ro",
|
||||
NETBIRD_PROXY_IMAGE,
|
||||
]);
|
||||
run_required_stack_command(
|
||||
"saleor",
|
||||
"create storefront proxy",
|
||||
&mut storefront_proxy_cmd,
|
||||
)
|
||||
.await?;
|
||||
|
||||
wait_for_stack_containers(
|
||||
"saleor",
|
||||
&[
|
||||
@@ -2067,6 +2174,8 @@ user.save()
|
||||
"saleor-api",
|
||||
"saleor-worker",
|
||||
"saleor",
|
||||
"saleor-storefront",
|
||||
"saleor-storefront-app",
|
||||
],
|
||||
120,
|
||||
)
|
||||
@@ -2082,6 +2191,8 @@ user.save()
|
||||
"saleor-api",
|
||||
"saleor-worker",
|
||||
"saleor",
|
||||
"saleor-storefront",
|
||||
"saleor-storefront-app",
|
||||
],
|
||||
30,
|
||||
)
|
||||
@@ -2099,7 +2210,7 @@ user.save()
|
||||
Ok(serde_json::json!({
|
||||
"success": true,
|
||||
"package_id": "saleor",
|
||||
"message": "Saleor stack installed (7 containers)",
|
||||
"message": "Saleor stack installed (9 containers)",
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -2120,6 +2231,48 @@ async fn read_or_generate_b64_secret(name: &str) -> String {
|
||||
secret
|
||||
}
|
||||
|
||||
async fn write_saleor_storefront_proxy_config() -> Result<()> {
|
||||
tokio::fs::create_dir_all("/var/lib/archipelago/saleor-storefront")
|
||||
.await
|
||||
.context("Failed to create Saleor storefront config directory")?;
|
||||
|
||||
let nginx_conf = r#"server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
location ^~ /graphql/ {
|
||||
proxy_pass http://api:8000/graphql/;
|
||||
proxy_set_header Host api;
|
||||
proxy_set_header Origin "";
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://storefront-app:3000;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Accept-Encoding "";
|
||||
sub_filter_once off;
|
||||
sub_filter_types text/html application/javascript text/javascript;
|
||||
sub_filter 'http://api:8000/graphql/' '$http_x_forwarded_proto://$host/graphql/';
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
tokio::fs::write(
|
||||
"/var/lib/archipelago/saleor-storefront/nginx.conf",
|
||||
nginx_conf,
|
||||
)
|
||||
.await
|
||||
.context("Failed to write Saleor storefront nginx.conf")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn write_netbird_config_files(host_ip: &str) -> Result<()> {
|
||||
let public_origin = format!("http://{}:8087", host_ip);
|
||||
let server_origin = format!("http://{}:8086", host_ip);
|
||||
@@ -2182,10 +2335,9 @@ LETSENCRYPT_DOMAIN=none
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
# Route API/auth through the host-published server port. Rootless Podman
|
||||
# can give netbird-server a new container IP on restart while nginx keeps
|
||||
# an old resolved address, which breaks login with 502s.
|
||||
set $netbird_server http://169.254.1.2:8086;
|
||||
# Route browser API/auth through the host-published server port. Rootless
|
||||
# Podman can give netbird-server a new container IP on restart while nginx
|
||||
# keeps an old resolved address, which breaks login with 502s.
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
@@ -2194,17 +2346,17 @@ LETSENCRYPT_DOMAIN=none
|
||||
proxy_http_version 1.1;
|
||||
|
||||
location ~ ^/(relay|ws-proxy/) {{
|
||||
proxy_pass $netbird_server;
|
||||
proxy_pass http://host.containers.internal:8086;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_read_timeout 1d;
|
||||
}}
|
||||
|
||||
location ~ ^/(api|oauth2)(/|$) {{
|
||||
proxy_pass $netbird_server;
|
||||
proxy_pass http://host.containers.internal:8086;
|
||||
}}
|
||||
|
||||
location ~ ^/(signalexchange\.SignalExchange|management\.ManagementService)/ {{
|
||||
location ~ ^/(signalexchange\.SignalExchange|management\.ManagementService|management\.ProxyService)/ {{
|
||||
grpc_pass grpc://netbird-server:80;
|
||||
grpc_read_timeout 1d;
|
||||
grpc_send_timeout 1d;
|
||||
|
||||
@@ -69,6 +69,8 @@ impl DockerPackageScanner {
|
||||
"saleor-cache",
|
||||
"saleor-jaeger",
|
||||
"saleor-mailpit",
|
||||
"saleor-storefront",
|
||||
"saleor-storefront-app",
|
||||
"buildx_buildkit_default",
|
||||
];
|
||||
|
||||
@@ -519,7 +521,7 @@ fn get_app_metadata(app_id: &str) -> AppMetadata {
|
||||
},
|
||||
"saleor" => AppMetadata {
|
||||
title: "Saleor".to_string(),
|
||||
description: "Composable commerce platform with GraphQL API and dashboard. Log in with admin@example.com; the password is stored on the node at /var/lib/archipelago/secrets/saleor-admin-password".to_string(),
|
||||
description: "Composable commerce platform with storefront, dashboard, and GraphQL API. The customer storefront opens on port 9011; admin dashboard is on 9010 with admin@example.com credentials stored on the node.".to_string(),
|
||||
icon: "/assets/img/app-icons/saleor.svg".to_string(),
|
||||
repo: "https://github.com/saleor/saleor".to_string(),
|
||||
tier: "",
|
||||
|
||||
@@ -129,7 +129,7 @@ impl PodmanClient {
|
||||
"filebrowser" => "http://localhost:8083",
|
||||
"nginx-proxy-manager" => "http://localhost:8081",
|
||||
"portainer" => "http://localhost:9000",
|
||||
"saleor" => "http://localhost:9010",
|
||||
"saleor" => "http://localhost:9011",
|
||||
"uptime-kuma" => "http://localhost:3002",
|
||||
"fedimint" | "fedimintd" => "http://localhost:8175",
|
||||
"fedimint-gateway" => "http://localhost:8176",
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "neode-ui",
|
||||
"version": "1.7.77-alpha",
|
||||
"version": "1.7.79-alpha",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "neode-ui",
|
||||
"version": "1.7.77-alpha",
|
||||
"version": "1.7.79-alpha",
|
||||
"dependencies": {
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@vue-leaflet/vue-leaflet": "^0.10.1",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "neode-ui",
|
||||
"private": true,
|
||||
"version": "1.7.77-alpha",
|
||||
"version": "1.7.79-alpha",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "./start-dev.sh",
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
"id": "saleor",
|
||||
"title": "Saleor",
|
||||
"version": "3.23",
|
||||
"description": "Composable commerce platform with GraphQL API, dashboard, worker, mail testing, and tracing.",
|
||||
"description": "Composable commerce platform with customer storefront, GraphQL API, dashboard, worker, mail testing, and tracing.",
|
||||
"icon": "/assets/img/app-icons/saleor.svg",
|
||||
"author": "Saleor",
|
||||
"category": "commerce",
|
||||
@@ -76,9 +76,9 @@
|
||||
"dockerImage": "ghcr.io/saleor/saleor:3.23",
|
||||
"repoUrl": "https://github.com/saleor/saleor",
|
||||
"containerConfig": {
|
||||
"ports": ["9010:80", "8000:8000", "8025:8025", "16686:16686"],
|
||||
"ports": ["9011:80", "9010:80", "8000:8000", "8025:8025", "16686:16686"],
|
||||
"volumes": ["/var/lib/archipelago/saleor:/app/media", "/var/lib/archipelago/saleor-db:/var/lib/postgresql/data"],
|
||||
"notes": "Installed as a Saleor stack: dashboard on 9010, API on 8000, Mailpit on 8025, and Jaeger on 16686. Supporting containers include PostgreSQL, Valkey, Celery worker, and services required by Saleor."
|
||||
"notes": "Installed as a Saleor stack: customer storefront on 9011, admin dashboard on 9010, API on 8000, Mailpit on 8025, and Jaeger on 16686. Supporting containers include PostgreSQL, Valkey, Celery worker, and services required by Saleor."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -103,6 +103,7 @@ const PORT_TO_APP_ID: Record<string, string> = {
|
||||
'8888': 'searxng',
|
||||
'9000': 'portainer',
|
||||
'9010': 'saleor',
|
||||
'9011': 'saleor',
|
||||
'8087': 'netbird',
|
||||
'8086': 'netbird',
|
||||
'9980': 'onlyoffice',
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
class="fixed inset-0 z-[2700] flex items-end justify-center bg-black/60 backdrop-blur-md p-0 md:items-center md:p-6"
|
||||
@click.self="closeCredentialModal"
|
||||
>
|
||||
<div class="sideload-modal">
|
||||
<div class="sideload-modal credential-modal">
|
||||
<div class="flex items-start justify-between gap-4 mb-5">
|
||||
<div>
|
||||
<h2 class="text-lg font-semibold text-white">{{ credentialModal.title }}</h2>
|
||||
@@ -187,7 +187,7 @@
|
||||
</div>
|
||||
<button type="button" class="sideload-close-btn" aria-label="Close" @click="closeCredentialModal">×</button>
|
||||
</div>
|
||||
<div class="space-y-3">
|
||||
<div class="credential-modal-body space-y-3">
|
||||
<div v-for="cred in credentialModal.credentials" :key="cred.label" class="rounded-lg border border-white/10 bg-white/[0.04] p-3">
|
||||
<div class="flex items-center justify-between gap-3 mb-1">
|
||||
<span class="text-white/60 text-xs uppercase tracking-wide">{{ cred.label }}</span>
|
||||
@@ -196,9 +196,9 @@
|
||||
<p class="font-mono text-sm text-white break-all">{{ cred.value }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 flex gap-3">
|
||||
<button type="button" class="flex-1 glass-button px-4 py-3 rounded-lg" @click="closeCredentialModal">Cancel</button>
|
||||
<button type="button" class="flex-1 glass-button px-4 py-3 rounded-lg font-semibold" @click="continueCredentialLaunch">Continue to app</button>
|
||||
<div class="credential-modal-actions mt-5 flex flex-col sm:flex-row gap-3">
|
||||
<button type="button" class="w-full sm:flex-1 glass-button px-4 py-3 rounded-lg" @click="closeCredentialModal">Cancel</button>
|
||||
<button type="button" class="w-full sm:flex-1 glass-button px-4 py-3 rounded-lg font-semibold" @click="continueCredentialLaunch">Continue to app</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -690,6 +690,18 @@ async function submitSideload() {
|
||||
}
|
||||
.sideload-input::placeholder { color: rgba(255, 255, 255, 0.38); }
|
||||
.sideload-input:focus { border-color: rgba(255, 255, 255, 0.38); }
|
||||
.credential-modal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.credential-modal-body {
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.credential-modal-actions {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.sideload-modal {
|
||||
border-radius: 1.25rem;
|
||||
|
||||
@@ -17,5 +17,16 @@ describe('appSessionConfig', () => {
|
||||
|
||||
expect(resolveAppUrl('mempool')).toBe('http://192.168.1.228:4080')
|
||||
expect(resolveAppUrl('indeedhub')).toBe('http://192.168.1.228:7778')
|
||||
expect(resolveAppUrl('saleor')).toBe('http://192.168.1.228:9011')
|
||||
})
|
||||
|
||||
it('keeps NetBird on the unified dashboard proxy port', () => {
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: { hostname: '192.168.1.228' },
|
||||
writable: true,
|
||||
configurable: true,
|
||||
})
|
||||
|
||||
expect(resolveAppUrl('netbird', undefined, 'http://localhost:8086')).toBe('http://192.168.1.228:8087')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -14,7 +14,7 @@ export const APP_PORTS: Record<string, number> = {
|
||||
'archy-electrs-ui': 50002,
|
||||
'mempool-electrs': 50002,
|
||||
'btcpay-server': 23000,
|
||||
'saleor': 9010,
|
||||
'saleor': 9011,
|
||||
'lnd': 18083,
|
||||
'archy-lnd-ui': 18083,
|
||||
'mempool': 4080,
|
||||
@@ -100,9 +100,7 @@ export const NEW_TAB_APPS = new Set([
|
||||
export const IFRAME_BLOCKED_APPS = new Set<string>([])
|
||||
|
||||
/** Resolve app URL using direct port mapping (source of truth) */
|
||||
export function resolveAppUrl(id: string, routeQueryPath?: string, runtimeUrl?: string): string {
|
||||
if (id === 'netbird' && runtimeUrl) return runtimeUrl
|
||||
|
||||
export function resolveAppUrl(id: string, routeQueryPath?: string, _runtimeUrl?: string): string {
|
||||
// External HTTPS apps
|
||||
const ext = EXTERNAL_URLS[id]
|
||||
if (ext) return ext
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
|
||||
<Transition name="fade">
|
||||
<div v-if="credentialModal.show" class="fixed inset-0 z-[2700] flex items-end justify-center bg-black/60 backdrop-blur-md p-0 md:items-center md:p-6" @click.self="closeCredentialModal">
|
||||
<div class="sideload-modal">
|
||||
<div class="sideload-modal credential-modal">
|
||||
<div class="flex items-start justify-between gap-4 mb-5">
|
||||
<div>
|
||||
<h2 class="text-lg font-semibold text-white">{{ credentialModal.title }}</h2>
|
||||
@@ -81,7 +81,7 @@
|
||||
</div>
|
||||
<button type="button" class="sideload-close-btn" aria-label="Close" @click="closeCredentialModal">×</button>
|
||||
</div>
|
||||
<div class="space-y-3">
|
||||
<div class="credential-modal-body space-y-3">
|
||||
<div v-for="cred in credentialModal.credentials" :key="cred.label" class="rounded-lg border border-white/10 bg-white/[0.04] p-3">
|
||||
<div class="flex items-center justify-between gap-3 mb-1">
|
||||
<span class="text-white/60 text-xs uppercase tracking-wide">{{ cred.label }}</span>
|
||||
@@ -90,9 +90,9 @@
|
||||
<p class="font-mono text-sm text-white break-all">{{ cred.value }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 flex gap-3">
|
||||
<button type="button" class="flex-1 glass-button px-4 py-3 rounded-lg" @click="closeCredentialModal">Cancel</button>
|
||||
<button type="button" class="flex-1 glass-button px-4 py-3 rounded-lg font-semibold" @click="continueCredentialLaunch">Continue to app</button>
|
||||
<div class="credential-modal-actions mt-5 flex flex-col sm:flex-row gap-3">
|
||||
<button type="button" class="w-full sm:flex-1 glass-button px-4 py-3 rounded-lg" @click="closeCredentialModal">Cancel</button>
|
||||
<button type="button" class="w-full sm:flex-1 glass-button px-4 py-3 rounded-lg font-semibold" @click="continueCredentialLaunch">Continue to app</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -241,3 +241,43 @@ function scrollToPage(index: number) {
|
||||
el.scrollTo({ left: index * el.clientWidth, behavior: 'smooth' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sideload-modal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
max-width: 34rem;
|
||||
max-height: calc(100dvh - var(--safe-area-top, env(safe-area-inset-top, 0px)) - 12px);
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(255, 255, 255, 0.14);
|
||||
border-radius: 1.5rem 1.5rem 0 0;
|
||||
background: rgba(8, 10, 18, 0.94);
|
||||
padding: 1.25rem;
|
||||
padding-bottom: calc(1.25rem + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px)));
|
||||
box-shadow: 0 -24px 70px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
.sideload-close-btn {
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
flex-shrink: 0;
|
||||
border-radius: 0.75rem;
|
||||
color: rgba(255, 255, 255, 0.55);
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
.credential-modal-body {
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.credential-modal-actions {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.sideload-modal {
|
||||
border-radius: 1.25rem;
|
||||
padding: 1.5rem;
|
||||
box-shadow: 0 25px 80px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -79,7 +79,7 @@ export function getCuratedAppList(): MarketplaceApp[] {
|
||||
{ id: 'bitcoin-knots', title: 'Bitcoin Knots', version: '28.1.0', description: 'Run a full Bitcoin node. Validate and relay blocks and transactions on the Bitcoin network.', icon: '/assets/img/app-icons/bitcoin-knots.webp', author: 'Bitcoin Knots', dockerImage: `${R}/bitcoin-knots:latest`, repoUrl: 'https://github.com/bitcoinknots/bitcoin' },
|
||||
{ id: 'bitcoin-core', title: 'Bitcoin Core', version: '28.4', description: 'Reference implementation of the Bitcoin protocol. Run a full node validating and relaying blocks on the Bitcoin network.', icon: '/assets/img/app-icons/bitcoin-core.svg', author: 'Bitcoin Core contributors', dockerImage: 'docker.io/bitcoin/bitcoin:28.4', repoUrl: 'https://github.com/bitcoin/bitcoin' },
|
||||
{ id: 'btcpay-server', title: 'BTCPay Server', version: '2.3.9', description: 'Self-hosted Bitcoin payment processor. Accept Bitcoin payments without intermediaries or fees.', icon: '/assets/img/app-icons/btcpay-server.png', author: 'BTCPay Server Foundation', dockerImage: 'docker.io/btcpayserver/btcpayserver:2.3.9', repoUrl: 'https://github.com/btcpayserver/btcpayserver' },
|
||||
{ id: 'saleor', title: 'Saleor', version: '3.23', category: 'commerce', description: 'Composable commerce platform with GraphQL API, dashboard, worker, mail testing, and tracing. Log in with admin@example.com; the password is stored on the node.', icon: '/assets/img/app-icons/saleor.svg', author: 'Saleor', dockerImage: 'ghcr.io/saleor/saleor:3.23', repoUrl: 'https://github.com/saleor/saleor' },
|
||||
{ id: 'saleor', title: 'Saleor', version: '3.23', category: 'commerce', description: 'Composable commerce platform with customer storefront, GraphQL API, dashboard, worker, mail testing, and tracing. Storefront opens on port 9011; admin dashboard remains on 9010.', icon: '/assets/img/app-icons/saleor.svg', author: 'Saleor', dockerImage: 'ghcr.io/saleor/saleor:3.23', repoUrl: 'https://github.com/saleor/saleor' },
|
||||
{ id: 'lnd', title: 'LND', version: '0.18.4', description: 'Lightning Network Daemon. Fast and cheap Bitcoin payments through the Lightning Network.', icon: '/assets/img/app-icons/lnd.svg', author: 'Lightning Labs', dockerImage: `${R}/lnd:v0.18.4-beta`, repoUrl: 'https://github.com/lightningnetwork/lnd' },
|
||||
{ id: 'mempool', title: 'Mempool Explorer', version: '3.0.0', description: 'Self-hosted Bitcoin blockchain and mempool visualizer. Monitor transactions without revealing your addresses to third parties.', icon: '/assets/img/app-icons/mempool.webp', author: 'Mempool', dockerImage: `${R}/mempool-frontend:v3.0.0`, repoUrl: 'https://github.com/mempool/mempool' },
|
||||
{ id: 'homeassistant', title: 'Home Assistant', version: '2024.1', description: 'Open-source home automation. Control smart home devices privately, on your own hardware.', icon: '/assets/img/app-icons/homeassistant.png', author: 'Home Assistant', dockerImage: `${R}/home-assistant:2024.1`, repoUrl: 'https://github.com/home-assistant/core' },
|
||||
|
||||
@@ -163,7 +163,7 @@ export function getCuratedAppList(): MarketplaceApp[] {
|
||||
title: 'Saleor',
|
||||
version: '3.23',
|
||||
category: 'commerce',
|
||||
description: 'Composable commerce platform with GraphQL API, dashboard, worker, mail testing, and tracing.',
|
||||
description: 'Composable commerce platform with customer storefront, GraphQL API, dashboard, worker, mail testing, and tracing.',
|
||||
icon: '/assets/img/app-icons/saleor.svg',
|
||||
author: 'Saleor',
|
||||
dockerImage: 'ghcr.io/saleor/saleor:3.23',
|
||||
|
||||
@@ -180,6 +180,33 @@ init()
|
||||
</button>
|
||||
</div>
|
||||
<div class="overflow-y-auto flex-1 min-h-0 space-y-6 pr-1">
|
||||
<!-- v1.7.79-alpha -->
|
||||
<div>
|
||||
<div class="flex items-center gap-2 mb-3">
|
||||
<span class="text-xs font-mono px-2 py-0.5 rounded bg-orange-500/20 text-orange-300">v1.7.79-alpha</span>
|
||||
<span class="text-xs text-white/40">May 20, 2026</span>
|
||||
</div>
|
||||
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
||||
<p>Saleor now includes the official Saleor Storefront as the customer-facing shop on port 9011.</p>
|
||||
<p>Launching Saleor opens the storefront, while the admin dashboard remains on port 9010 with generated admin@example.com credentials shown in Archipelago.</p>
|
||||
<p>Public storefront domains also get same-origin /graphql/ proxying so phones and laptops can reach the local Saleor API through the domain instead of a private node address.</p>
|
||||
<p>Saleor catalog, marketplace, scanner, and app-session metadata now describe the storefront/dashboard/API split explicitly.</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- v1.7.78-alpha -->
|
||||
<div>
|
||||
<div class="flex items-center gap-2 mb-3">
|
||||
<span class="text-xs font-mono px-2 py-0.5 rounded bg-orange-500/20 text-orange-300">v1.7.78-alpha</span>
|
||||
<span class="text-xs text-white/40">May 20, 2026</span>
|
||||
</div>
|
||||
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
||||
<p>Saleor's validated port 9010 dashboard/API origin settings are now ready for production release, preserving the working test-node install path.</p>
|
||||
<p>NetBird launches now stay on the unified dashboard/proxy origin at port 8087 instead of following stale server URLs on 8086.</p>
|
||||
<p>NetBird proxy routing no longer depends on a hard-coded rootless Podman gateway IP and now includes the upstream management proxy gRPC path.</p>
|
||||
<p>Mobile credential prompts keep long credential lists scrollable and the Cancel/Continue buttons reachable in both My Apps and the mobile icon grid.</p>
|
||||
<p>Android app-session popups hand external login/signup windows to the system browser instead of dropping them inside the WebView.</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- v1.7.76-alpha -->
|
||||
<div>
|
||||
<div class="flex items-center gap-2 mb-3">
|
||||
|
||||
+16
-17
@@ -1,29 +1,28 @@
|
||||
{
|
||||
"version": "1.7.77-alpha",
|
||||
"version": "1.7.79-alpha",
|
||||
"release_date": "2026-05-20",
|
||||
"changelog": [
|
||||
"Saleor first-use now exposes generated credentials through Archipelago instead of leaving users at an unexplained dashboard login: App Details shows copyable `admin@example.com` credentials, and My Apps/mobile icon launches show a pre-launch credentials modal.",
|
||||
"Saleor installs now create or repair the `admin@example.com` staff account idempotently after sample data loads, use the correct dashboard mount path, and re-check stack containers after startup so stopped containers are caught.",
|
||||
"NetBird embedded login now uses the upstream-compatible IdP signing-key behavior and sends ID tokens from the dashboard to the management API, fixing the post-signup `Unauthenticated` state while preserving the unified local proxy/logout routes.",
|
||||
"Transient unnamed Podman helper containers created during app install tasks are hidden from My Apps, so generated names like `eager_keldysh` no longer appear as user applications.",
|
||||
"Validation passed with catalog/release JSON checks, `npm run type-check`, and `cargo fmt --all --check --manifest-path core/Cargo.toml`; live checks on `100.114.134.21` confirmed Saleor dashboard/API availability, generated Saleor admin login, NetBird OAuth availability, and NetBird logout redirects."
|
||||
"Saleor now installs the official Saleor Storefront as part of the stack, built from the pinned `saleor/storefront` source and served as the customer-facing shop on port `9011`.",
|
||||
"Saleor app launches now open the storefront while the admin dashboard remains available on port `9010` with the generated `admin@example.com` credentials shown in Archipelago.",
|
||||
"Public Nginx Proxy Manager hosts forwarding to the Saleor storefront also expose same-origin `/graphql/`, so public storefront domains can talk to the local Saleor API without mixed-content or private-LAN reachability failures.",
|
||||
"Saleor stack metadata, marketplace descriptions, catalog ports, scanner exclusions, and app-session routing now describe the storefront/dashboard/API split explicitly."
|
||||
],
|
||||
"components": [
|
||||
{
|
||||
"name": "archipelago",
|
||||
"current_version": "1.7.77-alpha",
|
||||
"new_version": "1.7.77-alpha",
|
||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.77-alpha/archipelago",
|
||||
"sha256": "53679077182044f0601bab41e7239d293089f30725c1bedd883f30c40bd7807b",
|
||||
"size_bytes": 43068640
|
||||
"current_version": "1.7.79-alpha",
|
||||
"new_version": "1.7.79-alpha",
|
||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.79-alpha/archipelago",
|
||||
"sha256": "266918442fc25478646c253581dd7b475716bcb716156420bbf7dd8c793ebaed",
|
||||
"size_bytes": 43070912
|
||||
},
|
||||
{
|
||||
"name": "archipelago-frontend-1.7.77-alpha.tar.gz",
|
||||
"current_version": "1.7.77-alpha",
|
||||
"new_version": "1.7.77-alpha",
|
||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.77-alpha/archipelago-frontend-1.7.77-alpha.tar.gz",
|
||||
"sha256": "a083abfcbdbb03a2ba5a02e622d7d496fa5e6b39f2ee5afd41c9f4df0d31b9d6",
|
||||
"size_bytes": 166486722
|
||||
"name": "archipelago-frontend-1.7.79-alpha.tar.gz",
|
||||
"current_version": "1.7.79-alpha",
|
||||
"new_version": "1.7.79-alpha",
|
||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.79-alpha/archipelago-frontend-1.7.79-alpha.tar.gz",
|
||||
"sha256": "ed1eff4f7013e9c5fafe80e8e92168aff774b4477c542badb3441ccd512fdd1a",
|
||||
"size_bytes": 166485301
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+16
-17
@@ -1,29 +1,28 @@
|
||||
{
|
||||
"version": "1.7.77-alpha",
|
||||
"version": "1.7.79-alpha",
|
||||
"release_date": "2026-05-20",
|
||||
"changelog": [
|
||||
"Saleor first-use now exposes generated credentials through Archipelago instead of leaving users at an unexplained dashboard login: App Details shows copyable `admin@example.com` credentials, and My Apps/mobile icon launches show a pre-launch credentials modal.",
|
||||
"Saleor installs now create or repair the `admin@example.com` staff account idempotently after sample data loads, use the correct dashboard mount path, and re-check stack containers after startup so stopped containers are caught.",
|
||||
"NetBird embedded login now uses the upstream-compatible IdP signing-key behavior and sends ID tokens from the dashboard to the management API, fixing the post-signup `Unauthenticated` state while preserving the unified local proxy/logout routes.",
|
||||
"Transient unnamed Podman helper containers created during app install tasks are hidden from My Apps, so generated names like `eager_keldysh` no longer appear as user applications.",
|
||||
"Validation passed with catalog/release JSON checks, `npm run type-check`, and `cargo fmt --all --check --manifest-path core/Cargo.toml`; live checks on `100.114.134.21` confirmed Saleor dashboard/API availability, generated Saleor admin login, NetBird OAuth availability, and NetBird logout redirects."
|
||||
"Saleor now installs the official Saleor Storefront as part of the stack, built from the pinned `saleor/storefront` source and served as the customer-facing shop on port `9011`.",
|
||||
"Saleor app launches now open the storefront while the admin dashboard remains available on port `9010` with the generated `admin@example.com` credentials shown in Archipelago.",
|
||||
"Public Nginx Proxy Manager hosts forwarding to the Saleor storefront also expose same-origin `/graphql/`, so public storefront domains can talk to the local Saleor API without mixed-content or private-LAN reachability failures.",
|
||||
"Saleor stack metadata, marketplace descriptions, catalog ports, scanner exclusions, and app-session routing now describe the storefront/dashboard/API split explicitly."
|
||||
],
|
||||
"components": [
|
||||
{
|
||||
"name": "archipelago",
|
||||
"current_version": "1.7.77-alpha",
|
||||
"new_version": "1.7.77-alpha",
|
||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.77-alpha/archipelago",
|
||||
"sha256": "53679077182044f0601bab41e7239d293089f30725c1bedd883f30c40bd7807b",
|
||||
"size_bytes": 43068640
|
||||
"current_version": "1.7.79-alpha",
|
||||
"new_version": "1.7.79-alpha",
|
||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.79-alpha/archipelago",
|
||||
"sha256": "266918442fc25478646c253581dd7b475716bcb716156420bbf7dd8c793ebaed",
|
||||
"size_bytes": 43070912
|
||||
},
|
||||
{
|
||||
"name": "archipelago-frontend-1.7.77-alpha.tar.gz",
|
||||
"current_version": "1.7.77-alpha",
|
||||
"new_version": "1.7.77-alpha",
|
||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.77-alpha/archipelago-frontend-1.7.77-alpha.tar.gz",
|
||||
"sha256": "a083abfcbdbb03a2ba5a02e622d7d496fa5e6b39f2ee5afd41c9f4df0d31b9d6",
|
||||
"size_bytes": 166486722
|
||||
"name": "archipelago-frontend-1.7.79-alpha.tar.gz",
|
||||
"current_version": "1.7.79-alpha",
|
||||
"new_version": "1.7.79-alpha",
|
||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.79-alpha/archipelago-frontend-1.7.79-alpha.tar.gz",
|
||||
"sha256": "ed1eff4f7013e9c5fafe80e8e92168aff774b4477c542badb3441ccd512fdd1a",
|
||||
"size_bytes": 166485301
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -58,6 +58,42 @@ for row in rows:
|
||||
# NPM containers use this name to reach host-published services; host nginx
|
||||
# itself should use loopback for the same services.
|
||||
nginx_host = "127.0.0.1" if host == "host.containers.internal" else host
|
||||
try:
|
||||
forward_port = int(port)
|
||||
except (TypeError, ValueError):
|
||||
forward_port = None
|
||||
is_saleor_dashboard = forward_port == 9010
|
||||
is_saleor_storefront = forward_port == 9011
|
||||
is_saleor = is_saleor_dashboard or is_saleor_storefront
|
||||
graphql_location = ""
|
||||
saleor_proxy_headers = ""
|
||||
if is_saleor:
|
||||
graphql_location = """
|
||||
location ^~ /graphql/ {
|
||||
proxy_pass http://127.0.0.1:8000/graphql/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host 127.0.0.1;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header X-Forwarded-Scheme https;
|
||||
proxy_set_header Origin "";
|
||||
}
|
||||
"""
|
||||
if is_saleor_storefront:
|
||||
saleor_proxy_headers = """
|
||||
proxy_set_header Accept-Encoding "";
|
||||
sub_filter_once off;
|
||||
sub_filter_types text/html application/javascript text/javascript;
|
||||
sub_filter 'http://api:8000/graphql/' 'https://$host/graphql/';
|
||||
"""
|
||||
if is_saleor_dashboard:
|
||||
saleor_proxy_headers = """
|
||||
proxy_set_header Accept-Encoding "";
|
||||
sub_filter_once off;
|
||||
sub_filter_types text/html;
|
||||
sub_filter '</head>' '<script>if(window.__SALEOR_CONFIG__){window.__SALEOR_CONFIG__.API_URL=location.origin+"/graphql/";window.__SALEOR_CONFIG__.EXTENSIONS_API_URL=location.origin+"/graphql/";}</script></head>';
|
||||
"""
|
||||
|
||||
print(f"""
|
||||
server {{
|
||||
@@ -81,6 +117,8 @@ server {{
|
||||
ssl_certificate {cert};
|
||||
ssl_certificate_key {key};
|
||||
|
||||
{graphql_location}
|
||||
|
||||
location / {{
|
||||
proxy_pass {scheme}://{nginx_host}:{port};
|
||||
proxy_http_version 1.1;
|
||||
@@ -91,6 +129,7 @@ server {{
|
||||
proxy_set_header X-Forwarded-Scheme https;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
{saleor_proxy_headers}
|
||||
}}
|
||||
}}
|
||||
""")
|
||||
|
||||
Reference in New Issue
Block a user