Skip to content

Commit cd85cae

Browse files
chris-tophersclaude
andcommitted
fix: add streaming DMMF binary command to bypass V8 and WASM limits
Add a `get-dmmf` subcommand to the prisma-fmt CLI that streams DMMF JSON directly to stdout via serde_json::to_writer(). This approach has no memory ceiling — unlike WASM (limited to ~4GB linear memory), the native binary can stream arbitrarily large DMMF with only 1x peak memory (the in-memory DMMF struct, no serialized buffer). Changes: - dmmf crate: add dmmf_json_to_writer() using serde_json::to_writer() - prisma-fmt: add get_dmmf_to_writer() that validates + streams - prisma-fmt: export get_dmmf_to_writer() from lib.rs - prisma-fmt: add GetDmmf CLI variant, reads stdin params, streams to stdout Alternative approach to the buffered WASM API in prisma#5757. Fixes: prisma/prisma#29111 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9a53aad commit cd85cae

File tree

4 files changed

+47
-0
lines changed

4 files changed

+47
-0
lines changed

prisma-fmt/src/get_dmmf.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ pub(crate) fn get_dmmf(params: &str) -> Result<String, String> {
2121
validate::run(params.prisma_schema, params.no_color).map(dmmf::dmmf_json_from_validated_schema)
2222
}
2323

24+
/// Stream DMMF JSON directly to a writer. No intermediate String/Vec allocation.
25+
/// This enables the CLI binary to pipe DMMF to stdout without hitting any memory limit.
26+
/// See: https://github.com/prisma/prisma/issues/29111
27+
pub(crate) fn get_dmmf_to_writer<W: std::io::Write>(params: &str, writer: W) -> Result<(), String> {
28+
let params: GetDmmfParams = match serde_json::from_str(params) {
29+
Ok(params) => params,
30+
Err(serde_err) => {
31+
panic!("Failed to deserialize GetDmmfParams: {serde_err}");
32+
}
33+
};
34+
35+
validate::run(params.prisma_schema, params.no_color)
36+
.and_then(|schema| dmmf::dmmf_json_to_writer(schema, writer).map_err(|e| e.to_string()))
37+
}
38+
2439
#[cfg(test)]
2540
mod tests {
2641
use super::*;

prisma-fmt/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,12 @@ pub fn get_dmmf(get_dmmf_params: String) -> Result<String, String> {
303303
get_dmmf::get_dmmf(&get_dmmf_params)
304304
}
305305

306+
/// Stream DMMF JSON directly to a writer. No intermediate allocation.
307+
/// See: https://github.com/prisma/prisma/issues/29111
308+
pub fn get_dmmf_to_writer<W: std::io::Write>(get_dmmf_params: &str, writer: W) -> Result<(), String> {
309+
get_dmmf::get_dmmf_to_writer(get_dmmf_params, writer)
310+
}
311+
306312
pub fn get_datamodel(get_datamodel_params: String) -> Result<String, String> {
307313
get_datamodel::get_datamodel(&get_datamodel_params)
308314
}

prisma-fmt/src/main.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ pub enum FmtOpts {
4141
PreviewFeatures,
4242
/// Artificially panic (for testing the CLI)
4343
DebugPanic,
44+
/// Generate DMMF JSON from schema, streaming to stdout.
45+
/// Reads JSON params from stdin, streams DMMF to stdout via serde_json::to_writer().
46+
/// This has no memory ceiling — unlike WASM, the binary can stream arbitrarily large DMMF.
47+
/// See: https://github.com/prisma/prisma/issues/29111
48+
GetDmmf,
4449
}
4550

4651
fn main() {
@@ -51,6 +56,18 @@ fn main() {
5156
FmtOpts::NativeTypes => plug(native::run),
5257
FmtOpts::ReferentialActions => plug(actions::run),
5358
FmtOpts::PreviewFeatures => plug(|_s| preview::run()),
59+
FmtOpts::GetDmmf => {
60+
let mut input = String::new();
61+
io::stdin()
62+
.read_to_string(&mut input)
63+
.expect("Unable to read from stdin.");
64+
let stdout = io::stdout();
65+
let writer = io::BufWriter::new(stdout.lock());
66+
if let Err(e) = prisma_fmt::get_dmmf_to_writer(&input, writer) {
67+
eprintln!("{e}");
68+
std::process::exit(1);
69+
}
70+
}
5471
}
5572
}
5673

query-compiler/dmmf/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ pub fn dmmf_json_from_validated_schema(schema: ValidatedSchema) -> String {
2121
serde_json::to_string(&dmmf).unwrap()
2222
}
2323

24+
/// Serialize DMMF JSON directly to a writer without building an intermediate String or Vec.
25+
/// Uses serde_json::to_writer() which streams JSON tokens incrementally.
26+
/// This avoids both V8's string limit and WASM memory limits.
27+
/// See: https://github.com/prisma/prisma/issues/29111
28+
pub fn dmmf_json_to_writer<W: std::io::Write>(schema: ValidatedSchema, writer: W) -> serde_json::Result<()> {
29+
let dmmf = from_precomputed_parts(&schema::build(Arc::new(schema), true));
30+
serde_json::to_writer(writer, &dmmf)
31+
}
32+
2433
pub fn dmmf_from_schema(schema: &str) -> DataModelMetaFormat {
2534
let schema = Arc::new(psl::parse_schema_without_extensions(schema).unwrap());
2635
from_precomputed_parts(&schema::build(schema, true))

0 commit comments

Comments
 (0)