Skip to main content

workload_spec/
export_ts.rs

1//! In-memory TS-binding rendering, shared by `bin/export-ts.rs` (which writes
2//! it to `packages/yah/workload-spec/index.ts`) and `tests/ts_drift.rs`
3//! (which compares [`render`]'s output against that committed file without
4//! writing anything or touching git — R605-B28).
5//!
6//! [`render`] used to be inlined in `bin/export-ts.rs`'s `main`, which made
7//! "is the committed file what the Rust types imply" undecidable except by a
8//! `git diff` against HEAD — a question the drift guard actually needed to
9//! answer without going through git at all (R605-B28's fix on the sibling
10//! `.yah/schema/*.toml.schema.json` guard, `xtask::schemas::render_all`, is
11//! the pattern this mirrors).
12
13use ts_rs::{Config, TS};
14
15use crate::*;
16
17pub const HEADER: &str = "\
18// AUTO-GENERATED by `cargo run -p yah-workload-spec --bin export-ts`.
19// Source of truth: crates/yah/workload-spec/src/lib.rs.
20// Do not edit by hand. Regenerate after changing the Rust types and commit
21// the result; CI fails if this file drifts from the Rust schema.
22
23";
24
25/// Render the full single-file TS binding for `WorkloadSpec` and every type
26/// it references, in the same fixed leaves-first order `bin/export-ts.rs`
27/// always wrote. Pure — no filesystem access.
28pub fn render() -> String {
29    let cfg = Config::default();
30    let mut out = String::from(HEADER);
31
32    macro_rules! emit {
33        ($t:ty) => {
34            out.push_str("export ");
35            out.push_str(&<$t as TS>::decl(&cfg));
36            out.push_str("\n\n");
37        };
38    }
39
40    // Order: leaves first, then composites that reference them.
41    emit!(SchemaVersion);
42    emit!(Millis);
43    emit!(MachineId);
44    emit!(MeshIdent);
45    emit!(TierTag);
46    emit!(TenantId);
47    emit!(NamespaceId);
48
49    emit!(MeshLookup);
50    emit!(EnvValue);
51    emit!(EnvVar);
52
53    emit!(SecretRef);
54    emit!(SecretTarget);
55    emit!(SecretMount);
56
57    emit!(VolumeSource);
58    emit!(VolumeMount);
59
60    emit!(ImageRef);
61    emit!(ResourceLimits);
62
63    emit!(HealthProbe);
64    emit!(Healthcheck);
65
66    emit!(BackoffPolicy);
67    emit!(RestartPolicy);
68    emit!(StopPolicy);
69
70    emit!(MeshPeer);
71    emit!(MeshExpose);
72    emit!(PublicTls);
73    emit!(PublicExpose);
74    emit!(OperatorExpose);
75    emit!(ExposeSpec);
76
77    // R860-T1: the requirement vocabulary. Requirement.provides makes this
78    // mutually recursive with WorkloadSpec, so the order is arbitrary — the
79    // declarations reference each other by name either way.
80    emit!(Locality);
81    emit!(Supply);
82    emit!(Requirement);
83
84    emit!(WorkloadSpec);
85
86    // The two on-disk forms of `kind = "container"` (R783-F1 / W324). Leaves
87    // first: ContainerManifest is a union over WorkloadSpec and ContainerBuild.
88    emit!(ContainerMount);
89    emit!(ContainerRunConfig);
90    emit!(ContainerBuildStep);
91    emit!(ContainerBuild);
92    emit!(ContainerManifest);
93
94    emit!(BuildConfig);
95    emit!(BuildMode);
96    emit!(MesofactStaticWorkload);
97    emit!(MesofactServeBundle);
98    emit!(BundleLifecycle);
99    // Referenced by MesofactStaticWorkload.revalidate_receiver — omitting it
100    // emitted a binding that names a type this file never declares.
101    emit!(AlmanacFeed);
102    emit!(MesofactRevalidateReceiver);
103
104    emit!(AlmanacTarget);
105    emit!(NotReadyPolicy);
106    emit!(Cadence);
107    emit!(AlmanacManifest);
108
109    emit!(BlakeHash);
110    emit!(License);
111    emit!(FetchSource);
112    emit!(TransformSpec);
113    emit!(AssetDerive);
114    emit!(AssetEntry);
115    emit!(StaticAssetWorkload);
116
117    // R852-F1 — the per-tenant passway. Leaf first: TenantPasswayWorkload
118    // names TenantPasswayTls.
119    emit!(TenantPasswayTls);
120    emit!(TenantPasswayWorkload);
121
122    emit!(Workload);
123
124    out
125}