1use std::fs;
2
3use color_eyre::eyre::{Report, Result};
4use schemaui::SchemaUI;
5use schemaui::precompile::web::{
6 build_session_snapshot, write_session_snapshot_json, write_session_snapshot_ts_module,
7};
8use schemaui::web::session::ServeOptions as WebServeOptions;
9
10use crate::cli::{WebCommand, WebSnapshotCommand};
11use crate::session::diagnostics::DiagnosticCollector;
12use crate::session::format::resolve_format_hint;
13use crate::session::schema_source::{load_optional_document, resolve_session_inputs};
14use crate::session::{SessionBundle, prepare_session};
15
16pub fn run_cli(cmd: WebCommand) -> Result<()> {
17 let session = prepare_session(&cmd.common)?;
18 execute_web_session(session, cmd)
19}
20
21fn execute_web_session(session: SessionBundle, cmd: WebCommand) -> Result<()> {
22 let SessionBundle {
23 schema,
24 defaults,
25 title,
26 description,
27 output,
28 } = session;
29
30 let mut ui = if let Some(defaults) = defaults {
31 SchemaUI::new(defaults).with_schema(schema)
32 } else {
33 SchemaUI::from_schema(schema)
34 };
35 if let Some(title) = title {
36 ui = ui.with_title(title);
37 }
38 if let Some(description) = description {
39 ui = ui.with_description(description);
40 }
41
42 let serve = WebServeOptions {
43 host: cmd.host,
44 port: cmd.port,
45 };
46
47 let value = ui.run_web(serve).map_err(Report::msg)?;
48 if let Some(options) = output {
49 options.write(&value).map_err(Report::msg)?;
50 }
51 Ok(())
52}
53
54pub fn run_snapshot_cli(cmd: WebSnapshotCommand) -> Result<()> {
55 let schema_spec = cmd.common.schema.as_deref();
56 let config_spec = cmd.common.config.as_deref();
57 let mut diagnostics = DiagnosticCollector::default();
58 let schema_stdin = schema_spec == Some("-");
59 let config_stdin = config_spec == Some("-");
60 if schema_stdin && config_stdin {
61 diagnostics.push_input(
62 "schema/config",
63 "cannot read schema and config from stdin simultaneously; provide inline content, files, or a remote schema",
64 );
65 }
66 let schema_hint = resolve_format_hint(schema_spec, "schema", &mut diagnostics);
67 let config_hint = resolve_format_hint(config_spec, "config", &mut diagnostics);
68 let schema_document = load_optional_document(
69 schema_spec,
70 schema_hint.hint.format,
71 "schema",
72 schema_hint.blocked || (schema_stdin && config_stdin),
73 &mut diagnostics,
74 );
75 let config_document = load_optional_document(
76 config_spec,
77 config_hint.hint.format,
78 "config",
79 config_hint.blocked || (schema_stdin && config_stdin),
80 &mut diagnostics,
81 );
82 diagnostics.into_result()?;
83 let resolved = resolve_session_inputs(schema_document, config_document).map_err(Report::msg)?;
84 let mut snapshot = build_session_snapshot(&resolved.schema, resolved.defaults.as_ref())
85 .map_err(Report::msg)?;
86 if let Some(title) = cmd.common.title {
87 snapshot.title = Some(title);
88 }
89 if let Some(description) = cmd.common.description {
90 snapshot.description = Some(description);
91 }
92
93 fs::create_dir_all(&cmd.out_dir)?;
94 let json_out = cmd.out_dir.join("session_snapshot.json");
95 let ts_out = cmd.out_dir.join("session_snapshot.ts");
96
97 write_session_snapshot_json(&snapshot, &json_out).map_err(Report::msg)?;
98 write_session_snapshot_ts_module(&snapshot, &ts_out, &cmd.ts_export).map_err(Report::msg)?;
99
100 eprintln!("Generated Web precompile snapshots:");
101 eprintln!(" JSON: {:?}", json_out);
102 eprintln!(" TypeScript: {:?}", ts_out);
103
104 Ok(())
105}