#!/usr/bin/env nu # Decide whether the workspace needs a wasm32 build for the Leptos hydration profile. # # Used by the `build-auto` justfile recipe (and any CI driver) to choose between: # cargo leptos build --release (any route declares leptos-hydration) # cargo build --release --no-default-features --features ssr,htmx-ssr # (all routes are htmx-ssr) # # Decision sources, in precedence order: # 1. A `rendering_profile = "leptos-hydration"` override on any per-route TOML. # 2. `[rendering] default_profile = "leptos-hydration"` in the workspace config. # 3. Absence of a workspace `[rendering]` table (Rustelo default is hydration). # # Exit codes (suited for shell `if`): # 0 — wasm build needed (run cargo leptos) # 1 — wasm build NOT needed (run cargo build with htmx-ssr features) # 2 — argument or filesystem error # # Usage: # nu scripts/check-wasm-needed.nu --routes-dir site/config/routes \ # --workspace-config site/config/rendering.toml # # nu scripts/check-wasm-needed.nu --verbose ... # also print the reason def main [ --routes-dir: string # directory containing per-language route TOMLs; scanned recursively --workspace-config: string # path to the workspace config TOML carrying the [rendering] table --verbose # print one-line reason to stderr ] { let routes_dir = if $routes_dir == null { null } else { $routes_dir } let workspace_config = if $workspace_config == null { null } else { $workspace_config } # 1. Any route-level override forces the decision. if $routes_dir != null and ($routes_dir | path exists) { let hits = (try { route_overrides $routes_dir } catch { |e| print --stderr $"check-wasm-needed: failed to scan routes dir: ($e)" exit 2 }) if ($hits | length) > 0 { if $verbose { let first = ($hits | first) print --stderr $"wasm needed: route override (($first.file)) declares leptos-hydration" } exit 0 } } # 2. Workspace default. let workspace_says_hydrate = if $workspace_config != null and ($workspace_config | path exists) { workspace_default_is_hydration $workspace_config } else { true # 3. Absent table → Rustelo default is hydration. } if $workspace_says_hydrate { if $verbose { print --stderr "wasm needed: workspace default is leptos-hydration (explicit or implicit)" } exit 0 } else { if $verbose { print --stderr "wasm skipped: workspace default is htmx-ssr and no route opts back into leptos-hydration" } exit 1 } } # Returns rows {file, line} for every route TOML under `dir` whose # `rendering_profile` field is `"leptos-hydration"`. def route_overrides [dir: string] { glob $"($dir)/**/*.toml" | each {|file| let content = (open --raw $file) $content | lines | enumerate | each {|row| let line = $row.item if ($line | str replace --all ' ' '' | str contains 'rendering_profile="leptos-hydration"') { { file: $file, line: ($row.index + 1) } } else { null } } | where { |it| $it != null } } | flatten } # Parses the workspace config (TOML or NCL) and returns true when the # rendering.default_profile field is missing or set to "leptos-hydration". # # NCL workspaces are read as text and the field is grepped (avoids requiring # the nickel CLI in PATH for this dispatch decision). The grep is intentionally # strict — only single-line `default_profile = ""` syntax is recognised. def workspace_default_is_hydration [config_path: string] { let extension = ($config_path | path parse | get extension) if $extension == "ncl" { let content = (try { open --raw $config_path } catch { return true }) # Look for a single-line `default_profile = "..."` assignment. let htmx_line = ( $content | lines | each { |l| $l | str replace --all ' ' '' } | where { |l| $l | str contains 'default_profile="htmx-ssr"' } ) ($htmx_line | length) == 0 } else { let parsed = (try { open $config_path } catch { return true }) let table = ($parsed.rendering? | default null) if $table == null { true } else { let value = ($table.default_profile? | default "leptos-hydration") $value == "leptos-hydration" } } }