Skip to content
Draft
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
13 changes: 12 additions & 1 deletion scripts/generate_network_component_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
import argparse
import html
import json
import os
import re
import subprocess
import sys
from datetime import datetime, timezone
from pathlib import Path
from urllib.parse import urlparse
from urllib.request import Request, urlopen


Expand Down Expand Up @@ -119,8 +121,17 @@ def parse_args() -> argparse.Namespace:
return parser.parse_args()


def request_headers(url: str) -> dict[str, str]:
headers = {"User-Agent": USER_AGENT}
token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
if token and urlparse(url).netloc == "api.github.com":
headers["Authorization"] = f"Bearer {token}"
headers["X-GitHub-Api-Version"] = "2022-11-28"
return headers


def request_url(url: str, timeout: float):
request = Request(url, headers={"User-Agent": USER_AGENT})
request = Request(url, headers=request_headers(url))
return urlopen(request, timeout=timeout)


Expand Down
19 changes: 10 additions & 9 deletions scripts/generate_wallet_gateway_openrpc_reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,15 +268,16 @@ def update_docs_navigation(
navigation = docs.get("navigation")
if not isinstance(navigation, dict):
raise ValueError(f"docs.json navigation must be an object: {docs_json_path}")
dropdowns = navigation.get("dropdowns")
if not isinstance(dropdowns, list):
raise ValueError(f"docs.json navigation.dropdowns must be a list: {docs_json_path}")
dropdown = next((item for item in dropdowns if isinstance(item, dict) and item.get("dropdown") == dropdown_label), None)
if dropdown is None:
raise ValueError(f"Dropdown not found in docs.json: {dropdown_label}")
pages = dropdown.get("pages")
products = navigation.get("products")
if not isinstance(products, list):
raise ValueError(f"docs.json navigation.products must be a list: {docs_json_path}")
nav_root = next((item for item in products if isinstance(item, dict) and item.get("product") == dropdown_label), None)
if nav_root is None:
raise ValueError(f"Product not found in docs.json: {dropdown_label}")

pages = nav_root.get("pages")
if not isinstance(pages, list):
raise ValueError(f"Dropdown does not expose a pages list: {dropdown_label}")
raise ValueError(f"Product does not expose a pages list: {dropdown_label}")

refs = {overview_page_ref(output_dir, docs_json_path), docs_json_page_ref(output_dir / "operations" / "details.mdx", docs_json_path)}
refs.update(spec_page_ref(output_dir, docs_json_path, spec["spec_id"]) for spec in spec_entries)
Expand Down Expand Up @@ -310,7 +311,7 @@ def update_docs_navigation(
break
for offset, wallet_group in enumerate(wallet_groups):
pruned_pages.insert(min(insert_at + offset, len(pruned_pages)), wallet_group)
dropdown["pages"] = pruned_pages
nav_root["pages"] = pruned_pages
docs_json_path.write_text(json.dumps(docs, indent=2) + "\n", encoding="utf-8")
print(f"Updated docs navigation: {docs_json_path}")

Expand Down
1 change: 1 addition & 0 deletions scripts/generated_reference_sources/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Generated-reference source update helpers."""
25 changes: 25 additions & 0 deletions scripts/generated_reference_sources/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from __future__ import annotations

import json
from dataclasses import dataclass
from pathlib import Path


@dataclass(frozen=True)
class SourceUpdate:
source: str
path: Path
field: str
previous: str
current: str


def load_json(path: Path) -> dict[str, object]:
payload = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(payload, dict):
raise ValueError(f"Expected JSON object in {path}")
return payload


def write_json(path: Path, payload: dict[str, object]) -> None:
path.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
93 changes: 93 additions & 0 deletions scripts/generated_reference_sources/splice_openapi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Required, TypedDict

import generate_splice_mintlify_openapi as splice_openapi_generator

from generated_reference_sources.common import SourceUpdate, load_json, write_json


REPO_ROOT = Path(__file__).resolve().parents[2]
SOURCE_KEY = "splice-openapi"
SOURCE_LABEL = "Splice OpenAPI"
DEFAULT_SOURCE_CONFIG = (
REPO_ROOT / "config" / "mintlify-openapi" / "splice-openapi" / "source-artifacts.json"
)


class SpliceOpenApiSpecConfig(TypedDict, total=False):
filename: str
nav_label: str
source: str
directory: str


class SpliceOpenApiFamilyConfig(TypedDict, total=False):
group: str
specs: list[SpliceOpenApiSpecConfig]


class SpliceOpenApiSourceConfigPayload(TypedDict, total=False):
source: str
release_repo: str
tag_regex: str
min_version: str
publish_version: Required[str]
asset_template: str
nav_dropdown: str
top_level_group_label: str
insert_after_group: str
managed_openapi_root: str
enabled_nav_specs: list[str]
legacy_cleanup_paths: list[str]
families: list[SpliceOpenApiFamilyConfig]


@dataclass(frozen=True)
class SpliceOpenApiSourceConfig:
raw: SpliceOpenApiSourceConfigPayload
publish_version: str


def parse_source_config(path: Path) -> SpliceOpenApiSourceConfig:
raw_json = load_json(path)
publish_version = raw_json.get("publish_version")
if not isinstance(publish_version, str) or not publish_version:
raise ValueError(f"{path} must define non-empty publish_version")
raw: SpliceOpenApiSourceConfigPayload = {}
raw.update(raw_json)
return SpliceOpenApiSourceConfig(raw=raw, publish_version=publish_version)


def latest_version(source_config: SpliceOpenApiSourceConfig) -> str:
releases = splice_openapi_generator.selected_releases(
source_config=source_config.raw,
include_versions=None,
)
return releases[-1]["version"]


def update_source(
*,
source_config_path: Path,
dry_run: bool,
) -> SourceUpdate | None:
source_config = parse_source_config(source_config_path)
current_version = latest_version(source_config)
if source_config.publish_version == current_version:
return None

update = SourceUpdate(
source=SOURCE_LABEL,
path=source_config_path,
field="publish_version",
previous=source_config.publish_version,
current=current_version,
)
if not dry_run:
updated_config = dict(source_config.raw)
updated_config["publish_version"] = current_version
write_json(source_config_path, updated_config)
return update
104 changes: 104 additions & 0 deletions scripts/generated_reference_sources/wallet_gateway_openrpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Required, TypedDict

import generate_wallet_gateway_openrpc_reference as wallet_gateway_openrpc_generator

from generated_reference_sources.common import SourceUpdate, load_json, write_json


REPO_ROOT = Path(__file__).resolve().parents[2]
SOURCE_KEY = "wallet-gateway-openrpc"
SOURCE_LABEL = "Wallet Gateway OpenRPC"
DEFAULT_SOURCE_CONFIG = (
REPO_ROOT / "config" / "x2mdx" / "wallet-gateway-openrpc" / "source-artifacts.json"
)


class WalletGatewayOpenRpcSpecConfig(TypedDict, total=False):
spec_id: str
display_name: str
source_path: str


class WalletGatewayOpenRpcSourceConfigPayload(TypedDict, total=False):
source: str
release_repo: Required[str]
remote: str
tag_prefix: Required[str]
min_version: str
publish_version: Required[str]
specs: list[WalletGatewayOpenRpcSpecConfig]


@dataclass(frozen=True)
class WalletGatewayOpenRpcSourceConfig:
raw: WalletGatewayOpenRpcSourceConfigPayload
release_repo: str
tag_prefix: str
min_version: str
publish_version: str


def parse_source_config(path: Path) -> WalletGatewayOpenRpcSourceConfig:
raw_json = load_json(path)
release_repo = raw_json.get("release_repo")
tag_prefix = raw_json.get("tag_prefix")
min_version = raw_json.get("min_version") or "0.0.0"
publish_version = raw_json.get("publish_version")
if not isinstance(release_repo, str) or not release_repo:
raise ValueError("Wallet Gateway OpenRPC source config must define release_repo")
if not isinstance(tag_prefix, str) or not tag_prefix:
raise ValueError("Wallet Gateway OpenRPC source config must define tag_prefix")
if not isinstance(min_version, str):
raise ValueError("Wallet Gateway OpenRPC min_version must be a string")
if not isinstance(publish_version, str) or not publish_version:
raise ValueError(f"{path} must define non-empty publish_version")
raw: WalletGatewayOpenRpcSourceConfigPayload = {}
raw.update(raw_json)
return WalletGatewayOpenRpcSourceConfig(
raw=raw,
release_repo=release_repo,
tag_prefix=tag_prefix,
min_version=min_version,
publish_version=publish_version,
)


def latest_version(source_config: WalletGatewayOpenRpcSourceConfig) -> str:
versions = wallet_gateway_openrpc_generator.stable_release_versions(
release_repo=source_config.release_repo,
tag_prefix=source_config.tag_prefix,
min_version=source_config.min_version,
max_version=None,
include_versions=None,
)
if not versions:
raise ValueError("No Wallet Gateway OpenRPC releases selected")
return versions[-1]


def update_source(
*,
source_config_path: Path,
dry_run: bool,
) -> SourceUpdate | None:
source_config = parse_source_config(source_config_path)
current_version = latest_version(source_config)
if source_config.publish_version == current_version:
return None

update = SourceUpdate(
source=SOURCE_LABEL,
path=source_config_path,
field="publish_version",
previous=source_config.publish_version,
current=current_version,
)
if not dry_run:
updated_config = dict(source_config.raw)
updated_config["publish_version"] = current_version
write_json(source_config_path, updated_config)
return update
Loading