Rustelo/scripts/check-wasm-needed.nu
Jesús Pérez c0281e759c
chore: update
2026-07-18 20:14:32 +01:00

113 lines
4.5 KiB
Text
Executable file

#!/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 = "<value>"` 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"
}
}
}