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!(Millis);
42    emit!(MachineId);
43    emit!(MeshIdent);
44    emit!(TierTag);
45    emit!(TenantId);
46    emit!(NamespaceId);
47
48    emit!(MeshLookup);
49    emit!(EnvValue);
50    emit!(EnvVar);
51
52    emit!(SecretRef);
53    emit!(SecretTarget);
54    emit!(SecretMount);
55
56    emit!(VolumeSource);
57    emit!(VolumeMount);
58
59    emit!(ImageRef);
60    emit!(ResourceLimits);
61
62    emit!(HealthProbe);
63    emit!(Healthcheck);
64
65    emit!(BackoffPolicy);
66    emit!(RestartPolicy);
67    emit!(StopPolicy);
68
69    emit!(MeshPeer);
70    emit!(MeshExpose);
71    emit!(PublicTls);
72    emit!(PublicExpose);
73    emit!(OperatorExpose);
74    emit!(ExposeSpec);
75
76    // R860-T1: the requirement vocabulary. Requirement.provides makes this
77    // mutually recursive with WorkloadSpec, so the order is arbitrary — the
78    // declarations reference each other by name either way.
79    emit!(Locality);
80    emit!(Supply);
81    emit!(Requirement);
82
83    emit!(WorkloadSpec);
84
85    // The two on-disk forms of `kind = "container"` (R783-F1 / W324). Leaves
86    // first: ContainerManifest is a union over WorkloadSpec and ContainerBuild.
87    emit!(ContainerMount);
88    emit!(ContainerRunConfig);
89    emit!(ContainerBuildStep);
90    emit!(ContainerBuild);
91    emit!(ContainerManifest);
92
93    emit!(BuildConfig);
94    emit!(BuildMode);
95    emit!(MesofactStaticWorkload);
96    emit!(MesofactServeBundle);
97    emit!(BundleLifecycle);
98    // Referenced by MesofactStaticWorkload.revalidate_receiver — omitting it
99    // emitted a binding that names a type this file never declares.
100    emit!(AlmanacFeed);
101    emit!(MesofactRevalidateReceiver);
102
103    emit!(AlmanacTarget);
104    emit!(NotReadyPolicy);
105    emit!(Cadence);
106    emit!(AlmanacManifest);
107
108    emit!(BlakeHash);
109    emit!(License);
110    emit!(FetchSource);
111    emit!(TransformSpec);
112    emit!(AssetDerive);
113    emit!(AssetEntry);
114    emit!(StaticAssetWorkload);
115
116    // R852-F1 — the per-tenant passway. Leaf first: TenantPasswayWorkload
117    // names TenantPasswayTls.
118    emit!(TenantPasswayTls);
119    emit!(TenantPasswayWorkload);
120
121    emit!(Workload);
122
123    out
124}