From 87bc6b811aafa9b7bcdb787a2b8c8b5728cbbfb0 Mon Sep 17 00:00:00 2001 From: Serhii Tatarintsev Date: Mon, 8 Apr 2024 14:20:22 +0200 Subject: [PATCH] WIP(schema-wasm): support schema split into multiple files (#4787) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implement multi-file schema handling in PSL This commit implements multi-file schema handling in the Prisma Schema Language. At a high level, instead of accepting a single string, `psl::validate_multi_file()` is an alternative to `psl::validate()` that accepts something morally equivalent to: ```json { "./prisma/schema/a.prisma": "datasource db { ... }", "./prisma/schema/nested/b.prisma": "model Test { ... }" } ``` There are tests for PSL validation with multiple schema files, but most of the rest of engines still consumes the single file version of `psl::validate()`. The implementation and the return type are shared between `psl::validate_multi_file()` and `psl::validate()`, so the change is completely transparent, other than the expectation of passing in a list of (file_name, file_contents) instead of a single string. The `psl::validate()` entry point should behave exactly the same as `psl::multi_schema()` with a single file named `schema.prisma`. In particular, it has the exact same return type. Implementation ============== This is achieved by extending `Span` to contain, in addition to a start and end offset, a `FileId`. The `FileId` is a unique identifier for a file and its parsed `SchemaAst` inside `ParserDatabase`. The identifier types for AST items in `ParserDatabase` are also extended to contain the `FileId`, so that they can be uniquely referred to in the context of the (multi-file) schema. After the analysis phase (the `parser_database` crate), consumers of the analyzed schema become multi-file aware completely transparently, no change is necessary in the other engines. The only changes that will be required at scattered points across the codebase are the `psl::validate()` call sites that will need to receive a `Vec, SourceFile>` instead of a single `SourceFile`. This PR does _not_ deal with that, but it makes where these call sites are obvious by what entry points they use: `psl::validate()`, `psl::parse_schema()` and the various `*_assert_single()` methods on `ParserDatabase`. The PR contains tests confirming that schema analysis, validation and displaying diagnostics across multiple files works as expected. Status of this PR ================= This is going to be directly mergeable after review, and it will not affect the current schema handling behaviour when dealing with a single schema file. Next steps ========== - Replace all calls to `psl::validate()` with calls to `psl::validate_multi_file()`. - The `*_assert_single()` calls should be progressively replaced with their multi-file counterparts across engines. - The language server should start sending multiple files to prisma-schema-wasm in all calls. This is not in the spirit of the language server spec, but that is the most immediate solution. We'll have to make `range_to_span()` in `prisma-fmt` multi-schema aware by taking a FileId param. Links ===== Relevant issue: https://github.com/prisma/prisma/issues/2377 Also see the [internal design doc](https://www.notion.so/prismaio/Multi-file-Schema-24d68fe8664048ad86252fe446caac24?d=68ef128f25974e619671a9855f65f44d#2889a038e68c4fe1ac9afe3cd34978bd). * WIP(schema-wasm): Support schema split into multiple files * Reformat support (psl crate) * Add multifile reformatting tests * Clippy * feat(prisma-fmt): addd support for mergeSchemas, expose functions to prisma-fmt-wasm * chore(prisma-fmt): removed unused function * chore: fix typo Co-authored-by: Serhii Tatarintsev * feat(prisma-fmt): apply validation to merge_schemas * chore(prisma-fmt): update unit test * chore: fix bad merge * chore: fix tests --------- Co-authored-by: Tom HoulĂ© Co-authored-by: Alberto Schiabel Co-authored-by: jkomyno --- prisma-fmt/src/code_actions/multi_schema.rs | 3 +- prisma-fmt/src/get_config.rs | 49 +++--- prisma-fmt/src/get_dmmf.rs | 47 +++++- prisma-fmt/src/lib.rs | 10 ++ prisma-fmt/src/merge_schemas.rs | 127 +++++++++++++++ prisma-fmt/src/schema_file_input.rs | 26 +++ prisma-fmt/src/validate.rs | 93 ++++++++++- prisma-schema-wasm/src/lib.rs | 6 + psl/parser-database/src/files.rs | 7 + psl/parser-database/src/lib.rs | 22 ++- psl/psl-core/src/lib.rs | 10 +- psl/psl-core/src/reformat.rs | 150 +++++++++++++----- psl/psl/build.rs | 37 ++++- psl/psl/src/lib.rs | 2 + psl/psl/tests/multi_file/basic.rs | 2 +- psl/psl/tests/panic_with_diff/mod.rs | 7 +- psl/psl/tests/reformat_tests.rs | 71 ++++++++- .../align_blocks.reformatted/User.prisma | 5 + .../align_blocks.reformatted/db.prisma | 9 ++ .../align_blocks/User.prisma | 5 + .../align_blocks/db.prisma | 9 ++ .../relation_1_to_1.reformatted/Post.prisma | 5 + .../relation_1_to_1.reformatted/User.prisma | 7 + .../relation_1_to_1.reformatted/db.prisma | 9 ++ .../relation_1_to_1/Post.prisma | 4 + .../relation_1_to_1/User.prisma | 7 + .../relation_1_to_1/db.prisma | 9 ++ .../relation_list.reformatted/Post.prisma | 6 + .../relation_list.reformatted/User.prisma | 6 + .../relation_list.reformatted/db.prisma | 9 ++ .../relation_list/Post.prisma | 4 + .../relation_list/User.prisma | 6 + .../relation_list/db.prisma | 9 ++ .../relation_single.reformatted/Post.prisma | 5 + .../relation_single.reformatted/User.prisma | 7 + .../relation_single.reformatted/db.prisma | 9 ++ .../relation_single/Post.prisma | 4 + .../relation_single/User.prisma | 6 + .../relation_single/db.prisma | 9 ++ psl/psl/tests/validation_tests.rs | 2 +- psl/schema-ast/src/reformat.rs | 2 + psl/schema-ast/src/source_file.rs | 8 + query-engine/dmmf/src/lib.rs | 6 + 43 files changed, 750 insertions(+), 86 deletions(-) create mode 100644 prisma-fmt/src/merge_schemas.rs create mode 100644 prisma-fmt/src/schema_file_input.rs create mode 100644 psl/psl/tests/reformatter_multi_file/align_blocks.reformatted/User.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/align_blocks.reformatted/db.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/align_blocks/User.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/align_blocks/db.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_1_to_1.reformatted/Post.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_1_to_1.reformatted/User.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_1_to_1.reformatted/db.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_1_to_1/Post.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_1_to_1/User.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_1_to_1/db.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_list.reformatted/Post.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_list.reformatted/User.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_list.reformatted/db.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_list/Post.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_list/User.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_list/db.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_single.reformatted/Post.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_single.reformatted/User.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_single.reformatted/db.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_single/Post.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_single/User.prisma create mode 100644 psl/psl/tests/reformatter_multi_file/relation_single/db.prisma diff --git a/prisma-fmt/src/code_actions/multi_schema.rs b/prisma-fmt/src/code_actions/multi_schema.rs index 7e6aa9ceaf80..aa5aaad05175 100644 --- a/prisma-fmt/src/code_actions/multi_schema.rs +++ b/prisma-fmt/src/code_actions/multi_schema.rs @@ -147,8 +147,7 @@ pub(super) fn add_schema_to_schemas( ) } None => { - let has_properties = datasource.provider_defined() - || datasource.url_defined() + let has_properties = datasource.provider_defined() | datasource.url_defined() || datasource.direct_url_defined() || datasource.shadow_url_defined() || datasource.relation_mode_defined() diff --git a/prisma-fmt/src/get_config.rs b/prisma-fmt/src/get_config.rs index d6de194e1e86..97f714dc456c 100644 --- a/prisma-fmt/src/get_config.rs +++ b/prisma-fmt/src/get_config.rs @@ -1,14 +1,14 @@ -use psl::Diagnostics; +use psl::{Diagnostics, ValidatedSchema}; use serde::Deserialize; use serde_json::json; use std::collections::HashMap; -use crate::validate::SCHEMA_PARSER_ERROR_CODE; +use crate::{schema_file_input::SchemaFileInput, validate::SCHEMA_PARSER_ERROR_CODE}; #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct GetConfigParams { - prisma_schema: String, + prisma_schema: SchemaFileInput, #[serde(default)] ignore_env_var_errors: bool, #[serde(default)] @@ -43,29 +43,38 @@ pub(crate) fn get_config(params: &str) -> Result { } fn get_config_impl(params: GetConfigParams) -> Result { - let wrap_get_config_err = |errors: Diagnostics| -> GetConfigError { - use std::fmt::Write as _; - - let mut full_error = errors.to_pretty_string("schema.prisma", ¶ms.prisma_schema); - write!(full_error, "\nValidation Error Count: {}", errors.errors().len()).unwrap(); - - GetConfigError { - // this mirrors user_facing_errors::common::SchemaParserError - error_code: Some(SCHEMA_PARSER_ERROR_CODE), - message: full_error, - } - }; - - let mut config = psl::parse_configuration(¶ms.prisma_schema).map_err(wrap_get_config_err)?; + let mut schema = psl::validate_multi_file(params.prisma_schema.into()); + if schema.diagnostics.has_errors() { + return Err(create_get_config_error(&schema, &schema.diagnostics)); + } if !params.ignore_env_var_errors { let overrides: Vec<(_, _)> = params.datasource_overrides.into_iter().collect(); - config + schema + .configuration .resolve_datasource_urls_prisma_fmt(&overrides, |key| params.env.get(key).map(String::from)) - .map_err(wrap_get_config_err)?; + .map_err(|diagnostics| create_get_config_error(&schema, &diagnostics))?; } - Ok(psl::get_config(&config)) + Ok(psl::get_config(&schema.configuration)) +} + +fn create_get_config_error(schema: &ValidatedSchema, diagnostics: &Diagnostics) -> GetConfigError { + use std::fmt::Write as _; + + let mut rendered_diagnostics = schema.render_diagnostics(diagnostics); + write!( + rendered_diagnostics, + "\nValidation Error Count: {}", + diagnostics.errors().len() + ) + .unwrap(); + + GetConfigError { + // this mirrors user_facing_errors::common::SchemaParserError + error_code: Some(SCHEMA_PARSER_ERROR_CODE), + message: rendered_diagnostics, + } } #[cfg(test)] diff --git a/prisma-fmt/src/get_dmmf.rs b/prisma-fmt/src/get_dmmf.rs index 02eec126d17d..151cb7691ee5 100644 --- a/prisma-fmt/src/get_dmmf.rs +++ b/prisma-fmt/src/get_dmmf.rs @@ -1,11 +1,11 @@ use serde::Deserialize; -use crate::validate; +use crate::{schema_file_input::SchemaFileInput, validate}; #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct GetDmmfParams { - prisma_schema: String, + prisma_schema: SchemaFileInput, #[serde(default)] no_color: bool, } @@ -18,7 +18,7 @@ pub(crate) fn get_dmmf(params: &str) -> Result { } }; - validate::run(¶ms.prisma_schema, params.no_color).map(|_| dmmf::dmmf_json_from_schema(¶ms.prisma_schema)) + validate::run(params.prisma_schema, params.no_color).map(dmmf::dmmf_json_from_validated_schema) } #[cfg(test)] @@ -90,6 +90,47 @@ mod tests { expected.assert_eq(&response); } + #[test] + fn get_dmmf_multiple_files() { + let schema = vec![ + ( + "a.prisma", + r#" + datasource thedb { + provider = "postgresql" + url = env("DBURL") + } + + model A { + id String @id + b_id String @unique + b B @relation(fields: [b_id], references: [id]) + } + "#, + ), + ( + "b.prisma", + r#" + model B { + id String @id + a A? + } + "#, + ), + ]; + + let request = json!({ + "prismaSchema": schema, + }); + + let expected = expect![[ + r#"{"datamodel":{"enums":[],"models":[{"name":"A","dbName":null,"fields":[{"name":"id","kind":"scalar","isList":false,"isRequired":true,"isUnique":false,"isId":true,"isReadOnly":false,"hasDefaultValue":false,"type":"String","isGenerated":false,"isUpdatedAt":false},{"name":"b_id","kind":"scalar","isList":false,"isRequired":true,"isUnique":true,"isId":false,"isReadOnly":true,"hasDefaultValue":false,"type":"String","isGenerated":false,"isUpdatedAt":false},{"name":"b","kind":"object","isList":false,"isRequired":true,"isUnique":false,"isId":false,"isReadOnly":false,"hasDefaultValue":false,"type":"B","relationName":"AToB","relationFromFields":["b_id"],"relationToFields":["id"],"isGenerated":false,"isUpdatedAt":false}],"primaryKey":null,"uniqueFields":[],"uniqueIndexes":[],"isGenerated":false},{"name":"B","dbName":null,"fields":[{"name":"id","kind":"scalar","isList":false,"isRequired":true,"isUnique":false,"isId":true,"isReadOnly":false,"hasDefaultValue":false,"type":"String","isGenerated":false,"isUpdatedAt":false},{"name":"a","kind":"object","isList":false,"isRequired":false,"isUnique":false,"isId":false,"isReadOnly":false,"hasDefaultValue":false,"type":"A","relationName":"AToB","relationFromFields":[],"relationToFields":[],"isGenerated":false,"isUpdatedAt":false}],"primaryKey":null,"uniqueFields":[],"uniqueIndexes":[],"isGenerated":false}],"types":[]},"schema":{"inputObjectTypes":{"prisma":[{"name":"AWhereInput","meta":{"source":"A"},"constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"AND","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"OR","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"NOT","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"StringFilter","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"String","location":"scalar","isList":false}]},{"name":"b_id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"StringFilter","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"String","location":"scalar","isList":false}]},{"name":"b","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BRelationFilter","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AOrderByWithRelationInput","constraints":{"maxNumFields":1,"minNumFields":0},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"b_id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"b","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AWhereUniqueInput","meta":{"source":"A"},"constraints":{"maxNumFields":null,"minNumFields":1,"fields":["id","b_id"]},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"b_id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"AND","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"OR","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"NOT","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"b","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BRelationFilter","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AOrderByWithAggregationInput","constraints":{"maxNumFields":1,"minNumFields":0},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"b_id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"_count","isRequired":false,"isNullable":false,"inputTypes":[{"type":"ACountOrderByAggregateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"_max","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AMaxOrderByAggregateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"_min","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AMinOrderByAggregateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AScalarWhereWithAggregatesInput","meta":{"source":"A"},"constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"AND","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AScalarWhereWithAggregatesInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AScalarWhereWithAggregatesInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"OR","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AScalarWhereWithAggregatesInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"NOT","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AScalarWhereWithAggregatesInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AScalarWhereWithAggregatesInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"StringWithAggregatesFilter","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"String","location":"scalar","isList":false}]},{"name":"b_id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"StringWithAggregatesFilter","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"String","location":"scalar","isList":false}]}]},{"name":"BWhereInput","meta":{"source":"B"},"constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"AND","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"OR","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"NOT","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"StringFilter","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"String","location":"scalar","isList":false}]},{"name":"a","isRequired":false,"isNullable":true,"inputTypes":[{"type":"ANullableRelationFilter","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"Null","location":"scalar","isList":false}]}]},{"name":"BOrderByWithRelationInput","constraints":{"maxNumFields":1,"minNumFields":0},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"a","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BWhereUniqueInput","meta":{"source":"B"},"constraints":{"maxNumFields":null,"minNumFields":1,"fields":["id"]},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"AND","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"OR","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"NOT","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"a","isRequired":false,"isNullable":true,"inputTypes":[{"type":"ANullableRelationFilter","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"Null","location":"scalar","isList":false}]}]},{"name":"BOrderByWithAggregationInput","constraints":{"maxNumFields":1,"minNumFields":0},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"_count","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BCountOrderByAggregateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"_max","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BMaxOrderByAggregateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"_min","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BMinOrderByAggregateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BScalarWhereWithAggregatesInput","meta":{"source":"B"},"constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"AND","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BScalarWhereWithAggregatesInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BScalarWhereWithAggregatesInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"OR","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BScalarWhereWithAggregatesInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"NOT","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BScalarWhereWithAggregatesInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BScalarWhereWithAggregatesInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"StringWithAggregatesFilter","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"String","location":"scalar","isList":false}]}]},{"name":"ACreateInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"b","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BCreateNestedOneWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AUncheckedCreateInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"b_id","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]}]},{"name":"AUpdateInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"b","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BUpdateOneRequiredWithoutANestedInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AUncheckedUpdateInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"b_id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"ACreateManyInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"b_id","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]}]},{"name":"AUpdateManyMutationInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AUncheckedUpdateManyInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"b_id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BCreateInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"a","isRequired":false,"isNullable":false,"inputTypes":[{"type":"ACreateNestedOneWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BUncheckedCreateInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"a","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AUncheckedCreateNestedOneWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BUpdateInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"a","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AUpdateOneWithoutBNestedInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BUncheckedUpdateInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"a","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AUncheckedUpdateOneWithoutBNestedInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BCreateManyInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]}]},{"name":"BUpdateManyMutationInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BUncheckedUpdateManyInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"StringFilter","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"equals","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"in","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":true},{"type":"ListStringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"notIn","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":true},{"type":"ListStringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"lt","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"lte","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"gt","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"gte","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"contains","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"startsWith","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"endsWith","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"mode","isRequired":false,"isNullable":false,"inputTypes":[{"type":"QueryMode","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"not","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"NestedStringFilter","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BRelationFilter","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"is","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"isNot","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"ACountOrderByAggregateInput","constraints":{"maxNumFields":1,"minNumFields":1},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"b_id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]}]},{"name":"AMaxOrderByAggregateInput","constraints":{"maxNumFields":1,"minNumFields":1},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"b_id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]}]},{"name":"AMinOrderByAggregateInput","constraints":{"maxNumFields":1,"minNumFields":1},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"b_id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]}]},{"name":"StringWithAggregatesFilter","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"equals","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"in","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":true},{"type":"ListStringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"notIn","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":true},{"type":"ListStringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"lt","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"lte","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"gt","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"gte","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"contains","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"startsWith","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"endsWith","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"mode","isRequired":false,"isNullable":false,"inputTypes":[{"type":"QueryMode","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"not","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"NestedStringWithAggregatesFilter","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"_count","isRequired":false,"isNullable":false,"inputTypes":[{"type":"NestedIntFilter","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"_min","isRequired":false,"isNullable":false,"inputTypes":[{"type":"NestedStringFilter","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"_max","isRequired":false,"isNullable":false,"inputTypes":[{"type":"NestedStringFilter","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"ANullableRelationFilter","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"is","isRequired":false,"isNullable":true,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"Null","location":"scalar","isList":false}]},{"name":"isNot","isRequired":false,"isNullable":true,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"Null","location":"scalar","isList":false}]}]},{"name":"BCountOrderByAggregateInput","constraints":{"maxNumFields":1,"minNumFields":1},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]}]},{"name":"BMaxOrderByAggregateInput","constraints":{"maxNumFields":1,"minNumFields":1},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]}]},{"name":"BMinOrderByAggregateInput","constraints":{"maxNumFields":1,"minNumFields":1},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"SortOrder","namespace":"prisma","location":"enumTypes","isList":false}]}]},{"name":"BCreateNestedOneWithoutAInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"create","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BCreateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUncheckedCreateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"connectOrCreate","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BCreateOrConnectWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"connect","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"StringFieldUpdateOperationsInput","constraints":{"maxNumFields":1,"minNumFields":1},"fields":[{"name":"set","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]}]},{"name":"BUpdateOneRequiredWithoutANestedInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"create","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BCreateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUncheckedCreateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"connectOrCreate","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BCreateOrConnectWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"upsert","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BUpsertWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"connect","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"update","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BUpdateToOneWithWhereWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUpdateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUncheckedUpdateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"ACreateNestedOneWithoutBInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"create","isRequired":false,"isNullable":false,"inputTypes":[{"type":"ACreateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedCreateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"connectOrCreate","isRequired":false,"isNullable":false,"inputTypes":[{"type":"ACreateOrConnectWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"connect","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AUncheckedCreateNestedOneWithoutBInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"create","isRequired":false,"isNullable":false,"inputTypes":[{"type":"ACreateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedCreateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"connectOrCreate","isRequired":false,"isNullable":false,"inputTypes":[{"type":"ACreateOrConnectWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"connect","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AUpdateOneWithoutBNestedInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"create","isRequired":false,"isNullable":false,"inputTypes":[{"type":"ACreateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedCreateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"connectOrCreate","isRequired":false,"isNullable":false,"inputTypes":[{"type":"ACreateOrConnectWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"upsert","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AUpsertWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"disconnect","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Boolean","location":"scalar","isList":false},{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"delete","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Boolean","location":"scalar","isList":false},{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"connect","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"update","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AUpdateToOneWithWhereWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUpdateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedUpdateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AUncheckedUpdateOneWithoutBNestedInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"create","isRequired":false,"isNullable":false,"inputTypes":[{"type":"ACreateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedCreateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"connectOrCreate","isRequired":false,"isNullable":false,"inputTypes":[{"type":"ACreateOrConnectWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"upsert","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AUpsertWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"disconnect","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Boolean","location":"scalar","isList":false},{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"delete","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Boolean","location":"scalar","isList":false},{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"connect","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"update","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AUpdateToOneWithWhereWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUpdateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedUpdateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"NestedStringFilter","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"equals","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"in","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":true},{"type":"ListStringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"notIn","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":true},{"type":"ListStringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"lt","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"lte","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"gt","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"gte","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"contains","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"startsWith","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"endsWith","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"not","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"NestedStringFilter","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"NestedStringWithAggregatesFilter","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"equals","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"in","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":true},{"type":"ListStringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"notIn","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":true},{"type":"ListStringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"lt","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"lte","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"gt","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"gte","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"contains","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"startsWith","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"endsWith","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"not","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"NestedStringWithAggregatesFilter","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"_count","isRequired":false,"isNullable":false,"inputTypes":[{"type":"NestedIntFilter","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"_min","isRequired":false,"isNullable":false,"inputTypes":[{"type":"NestedStringFilter","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"_max","isRequired":false,"isNullable":false,"inputTypes":[{"type":"NestedStringFilter","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"NestedIntFilter","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"equals","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false},{"type":"IntFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"in","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":true},{"type":"ListIntFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"notIn","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":true},{"type":"ListIntFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"lt","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false},{"type":"IntFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"lte","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false},{"type":"IntFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"gt","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false},{"type":"IntFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"gte","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false},{"type":"IntFieldRefInput","namespace":"prisma","location":"fieldRefTypes","isList":false}]},{"name":"not","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false},{"type":"NestedIntFilter","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BCreateWithoutAInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]}]},{"name":"BUncheckedCreateWithoutAInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]}]},{"name":"BCreateOrConnectWithoutAInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"where","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"create","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BCreateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUncheckedCreateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BUpsertWithoutAInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"update","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BUpdateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUncheckedUpdateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"create","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BCreateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUncheckedCreateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BUpdateToOneWithWhereWithoutAInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"data","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BUpdateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUncheckedUpdateWithoutAInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BUpdateWithoutAInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"BUncheckedUpdateWithoutAInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"ACreateWithoutBInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]}]},{"name":"AUncheckedCreateWithoutBInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]}]},{"name":"ACreateOrConnectWithoutBInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"where","isRequired":true,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"create","isRequired":true,"isNullable":false,"inputTypes":[{"type":"ACreateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedCreateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AUpsertWithoutBInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"update","isRequired":true,"isNullable":false,"inputTypes":[{"type":"AUpdateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedUpdateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"create","isRequired":true,"isNullable":false,"inputTypes":[{"type":"ACreateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedCreateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AUpdateToOneWithWhereWithoutBInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"data","isRequired":true,"isNullable":false,"inputTypes":[{"type":"AUpdateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedUpdateWithoutBInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AUpdateWithoutBInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]},{"name":"AUncheckedUpdateWithoutBInput","constraints":{"maxNumFields":null,"minNumFields":null},"fields":[{"name":"id","isRequired":false,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false},{"type":"StringFieldUpdateOperationsInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}]}]},"outputObjectTypes":{"prisma":[{"name":"Query","fields":[{"name":"findFirstA","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"orderBy","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":true},{"type":"AOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"cursor","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"take","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"skip","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"distinct","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":false},{"type":"AScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":true}]}],"isNullable":true,"outputType":{"type":"A","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"findFirstAOrThrow","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"orderBy","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":true},{"type":"AOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"cursor","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"take","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"skip","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"distinct","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":false},{"type":"AScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":true}]}],"isNullable":true,"outputType":{"type":"A","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"findManyA","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"orderBy","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":true},{"type":"AOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"cursor","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"take","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"skip","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"distinct","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":false},{"type":"AScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":true}]}],"isNullable":false,"outputType":{"type":"A","namespace":"model","location":"outputObjectTypes","isList":true}},{"name":"aggregateA","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"orderBy","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":true},{"type":"AOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"cursor","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"take","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"skip","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]}],"isNullable":false,"outputType":{"type":"AggregateA","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"groupByA","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"orderBy","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AOrderByWithAggregationInput","namespace":"prisma","location":"inputObjectTypes","isList":true},{"type":"AOrderByWithAggregationInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"by","isRequired":true,"isNullable":false,"inputTypes":[{"type":"AScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":true},{"type":"AScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"having","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AScalarWhereWithAggregatesInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"take","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"skip","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]}],"isNullable":false,"outputType":{"type":"AGroupByOutputType","namespace":"prisma","location":"outputObjectTypes","isList":true}},{"name":"findUniqueA","args":[{"name":"where","isRequired":true,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":true,"outputType":{"type":"A","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"findUniqueAOrThrow","args":[{"name":"where","isRequired":true,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":true,"outputType":{"type":"A","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"findFirstB","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"orderBy","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":true},{"type":"BOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"cursor","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"take","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"skip","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"distinct","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":false},{"type":"BScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":true}]}],"isNullable":true,"outputType":{"type":"B","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"findFirstBOrThrow","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"orderBy","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":true},{"type":"BOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"cursor","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"take","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"skip","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"distinct","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":false},{"type":"BScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":true}]}],"isNullable":true,"outputType":{"type":"B","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"findManyB","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"orderBy","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":true},{"type":"BOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"cursor","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"take","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"skip","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"distinct","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":false},{"type":"BScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":true}]}],"isNullable":false,"outputType":{"type":"B","namespace":"model","location":"outputObjectTypes","isList":true}},{"name":"aggregateB","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"orderBy","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":true},{"type":"BOrderByWithRelationInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"cursor","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"take","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"skip","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]}],"isNullable":false,"outputType":{"type":"AggregateB","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"groupByB","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"orderBy","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BOrderByWithAggregationInput","namespace":"prisma","location":"inputObjectTypes","isList":true},{"type":"BOrderByWithAggregationInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"by","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":true},{"type":"BScalarFieldEnum","namespace":"prisma","location":"enumTypes","isList":false}]},{"name":"having","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BScalarWhereWithAggregatesInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"take","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]},{"name":"skip","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Int","location":"scalar","isList":false}]}],"isNullable":false,"outputType":{"type":"BGroupByOutputType","namespace":"prisma","location":"outputObjectTypes","isList":true}},{"name":"findUniqueB","args":[{"name":"where","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":true,"outputType":{"type":"B","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"findUniqueBOrThrow","args":[{"name":"where","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":true,"outputType":{"type":"B","namespace":"model","location":"outputObjectTypes","isList":false}}]},{"name":"Mutation","fields":[{"name":"createOneA","args":[{"name":"data","isRequired":true,"isNullable":false,"inputTypes":[{"type":"ACreateInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedCreateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":false,"outputType":{"type":"A","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"upsertOneA","args":[{"name":"where","isRequired":true,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"create","isRequired":true,"isNullable":false,"inputTypes":[{"type":"ACreateInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedCreateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"update","isRequired":true,"isNullable":false,"inputTypes":[{"type":"AUpdateInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedUpdateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":false,"outputType":{"type":"A","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"createManyA","args":[{"name":"data","isRequired":true,"isNullable":false,"inputTypes":[{"type":"ACreateManyInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"ACreateManyInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"skipDuplicates","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Boolean","location":"scalar","isList":false}]}],"isNullable":false,"outputType":{"type":"AffectedRowsOutput","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"deleteOneA","args":[{"name":"where","isRequired":true,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":true,"outputType":{"type":"A","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"updateOneA","args":[{"name":"data","isRequired":true,"isNullable":false,"inputTypes":[{"type":"AUpdateInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedUpdateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"where","isRequired":true,"isNullable":false,"inputTypes":[{"type":"AWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":true,"outputType":{"type":"A","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"updateManyA","args":[{"name":"data","isRequired":true,"isNullable":false,"inputTypes":[{"type":"AUpdateManyMutationInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"AUncheckedUpdateManyInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":false,"outputType":{"type":"AffectedRowsOutput","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"deleteManyA","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":false,"outputType":{"type":"AffectedRowsOutput","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"createOneB","args":[{"name":"data","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BCreateInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUncheckedCreateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":false,"outputType":{"type":"B","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"upsertOneB","args":[{"name":"where","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"create","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BCreateInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUncheckedCreateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"update","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BUpdateInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUncheckedUpdateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":false,"outputType":{"type":"B","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"createManyB","args":[{"name":"data","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BCreateManyInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BCreateManyInput","namespace":"prisma","location":"inputObjectTypes","isList":true}]},{"name":"skipDuplicates","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Boolean","location":"scalar","isList":false}]}],"isNullable":false,"outputType":{"type":"AffectedRowsOutput","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"deleteOneB","args":[{"name":"where","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":true,"outputType":{"type":"B","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"updateOneB","args":[{"name":"data","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BUpdateInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUncheckedUpdateInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"where","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BWhereUniqueInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":true,"outputType":{"type":"B","namespace":"model","location":"outputObjectTypes","isList":false}},{"name":"updateManyB","args":[{"name":"data","isRequired":true,"isNullable":false,"inputTypes":[{"type":"BUpdateManyMutationInput","namespace":"prisma","location":"inputObjectTypes","isList":false},{"type":"BUncheckedUpdateManyInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]},{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":false,"outputType":{"type":"AffectedRowsOutput","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"deleteManyB","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"BWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":false,"outputType":{"type":"AffectedRowsOutput","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"executeRaw","args":[{"name":"query","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"parameters","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Json","location":"scalar","isList":false}]}],"isNullable":false,"outputType":{"type":"Json","location":"scalar","isList":false}},{"name":"queryRaw","args":[{"name":"query","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"parameters","isRequired":false,"isNullable":false,"inputTypes":[{"type":"Json","location":"scalar","isList":false}]}],"isNullable":false,"outputType":{"type":"Json","location":"scalar","isList":false}}]},{"name":"AggregateA","fields":[{"name":"_count","args":[],"isNullable":true,"outputType":{"type":"ACountAggregateOutputType","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"_min","args":[],"isNullable":true,"outputType":{"type":"AMinAggregateOutputType","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"_max","args":[],"isNullable":true,"outputType":{"type":"AMaxAggregateOutputType","namespace":"prisma","location":"outputObjectTypes","isList":false}}]},{"name":"AGroupByOutputType","fields":[{"name":"id","args":[],"isNullable":false,"outputType":{"type":"String","location":"scalar","isList":false}},{"name":"b_id","args":[],"isNullable":false,"outputType":{"type":"String","location":"scalar","isList":false}},{"name":"_count","args":[],"isNullable":true,"outputType":{"type":"ACountAggregateOutputType","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"_min","args":[],"isNullable":true,"outputType":{"type":"AMinAggregateOutputType","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"_max","args":[],"isNullable":true,"outputType":{"type":"AMaxAggregateOutputType","namespace":"prisma","location":"outputObjectTypes","isList":false}}]},{"name":"AggregateB","fields":[{"name":"_count","args":[],"isNullable":true,"outputType":{"type":"BCountAggregateOutputType","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"_min","args":[],"isNullable":true,"outputType":{"type":"BMinAggregateOutputType","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"_max","args":[],"isNullable":true,"outputType":{"type":"BMaxAggregateOutputType","namespace":"prisma","location":"outputObjectTypes","isList":false}}]},{"name":"BGroupByOutputType","fields":[{"name":"id","args":[],"isNullable":false,"outputType":{"type":"String","location":"scalar","isList":false}},{"name":"_count","args":[],"isNullable":true,"outputType":{"type":"BCountAggregateOutputType","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"_min","args":[],"isNullable":true,"outputType":{"type":"BMinAggregateOutputType","namespace":"prisma","location":"outputObjectTypes","isList":false}},{"name":"_max","args":[],"isNullable":true,"outputType":{"type":"BMaxAggregateOutputType","namespace":"prisma","location":"outputObjectTypes","isList":false}}]},{"name":"AffectedRowsOutput","fields":[{"name":"count","args":[],"isNullable":false,"outputType":{"type":"Int","location":"scalar","isList":false}}]},{"name":"ACountAggregateOutputType","fields":[{"name":"id","args":[],"isNullable":false,"outputType":{"type":"Int","location":"scalar","isList":false}},{"name":"b_id","args":[],"isNullable":false,"outputType":{"type":"Int","location":"scalar","isList":false}},{"name":"_all","args":[],"isNullable":false,"outputType":{"type":"Int","location":"scalar","isList":false}}]},{"name":"AMinAggregateOutputType","fields":[{"name":"id","args":[],"isNullable":true,"outputType":{"type":"String","location":"scalar","isList":false}},{"name":"b_id","args":[],"isNullable":true,"outputType":{"type":"String","location":"scalar","isList":false}}]},{"name":"AMaxAggregateOutputType","fields":[{"name":"id","args":[],"isNullable":true,"outputType":{"type":"String","location":"scalar","isList":false}},{"name":"b_id","args":[],"isNullable":true,"outputType":{"type":"String","location":"scalar","isList":false}}]},{"name":"BCountAggregateOutputType","fields":[{"name":"id","args":[],"isNullable":false,"outputType":{"type":"Int","location":"scalar","isList":false}},{"name":"_all","args":[],"isNullable":false,"outputType":{"type":"Int","location":"scalar","isList":false}}]},{"name":"BMinAggregateOutputType","fields":[{"name":"id","args":[],"isNullable":true,"outputType":{"type":"String","location":"scalar","isList":false}}]},{"name":"BMaxAggregateOutputType","fields":[{"name":"id","args":[],"isNullable":true,"outputType":{"type":"String","location":"scalar","isList":false}}]}],"model":[{"name":"A","fields":[{"name":"id","args":[],"isNullable":false,"outputType":{"type":"String","location":"scalar","isList":false}},{"name":"b_id","args":[],"isNullable":false,"outputType":{"type":"String","location":"scalar","isList":false}},{"name":"b","args":[],"isNullable":false,"outputType":{"type":"B","namespace":"model","location":"outputObjectTypes","isList":false}}]},{"name":"B","fields":[{"name":"id","args":[],"isNullable":false,"outputType":{"type":"String","location":"scalar","isList":false}},{"name":"a","args":[{"name":"where","isRequired":false,"isNullable":false,"inputTypes":[{"type":"AWhereInput","namespace":"prisma","location":"inputObjectTypes","isList":false}]}],"isNullable":true,"outputType":{"type":"A","namespace":"model","location":"outputObjectTypes","isList":false}}]}]},"enumTypes":{"prisma":[{"name":"TransactionIsolationLevel","values":["ReadUncommitted","ReadCommitted","RepeatableRead","Serializable"]},{"name":"AScalarFieldEnum","values":["id","b_id"]},{"name":"BScalarFieldEnum","values":["id"]},{"name":"SortOrder","values":["asc","desc"]},{"name":"QueryMode","values":["default","insensitive"]}]},"fieldRefTypes":{"prisma":[{"name":"StringFieldRefInput","allowTypes":[{"type":"String","location":"scalar","isList":false}],"fields":[{"name":"_ref","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"_container","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]}]},{"name":"ListStringFieldRefInput","allowTypes":[{"type":"String","location":"scalar","isList":true}],"fields":[{"name":"_ref","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"_container","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]}]},{"name":"IntFieldRefInput","allowTypes":[{"type":"Int","location":"scalar","isList":false}],"fields":[{"name":"_ref","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"_container","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]}]},{"name":"ListIntFieldRefInput","allowTypes":[{"type":"Int","location":"scalar","isList":true}],"fields":[{"name":"_ref","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]},{"name":"_container","isRequired":true,"isNullable":false,"inputTypes":[{"type":"String","location":"scalar","isList":false}]}]}]}},"mappings":{"modelOperations":[{"model":"A","aggregate":"aggregateA","createMany":"createManyA","createOne":"createOneA","deleteMany":"deleteManyA","deleteOne":"deleteOneA","findFirst":"findFirstA","findFirstOrThrow":"findFirstAOrThrow","findMany":"findManyA","findUnique":"findUniqueA","findUniqueOrThrow":"findUniqueAOrThrow","groupBy":"groupByA","updateMany":"updateManyA","updateOne":"updateOneA","upsertOne":"upsertOneA"},{"model":"B","aggregate":"aggregateB","createMany":"createManyB","createOne":"createOneB","deleteMany":"deleteManyB","deleteOne":"deleteOneB","findFirst":"findFirstB","findFirstOrThrow":"findFirstBOrThrow","findMany":"findManyB","findUnique":"findUniqueB","findUniqueOrThrow":"findUniqueBOrThrow","groupBy":"groupByB","updateMany":"updateManyB","updateOne":"updateOneB","upsertOne":"upsertOneB"}],"otherOperations":{"read":[],"write":["executeRaw","queryRaw"]}}}"# + ]]; + + let response = get_dmmf(&request.to_string()).unwrap(); + expected.assert_eq(&response); + } + #[test] fn get_dmmf_using_both_relation_mode_and_referential_integrity() { let schema = r#" diff --git a/prisma-fmt/src/lib.rs b/prisma-fmt/src/lib.rs index ada79cd7290b..c1449b3b2053 100644 --- a/prisma-fmt/src/lib.rs +++ b/prisma-fmt/src/lib.rs @@ -3,8 +3,10 @@ mod code_actions; mod get_config; mod get_dmmf; mod lint; +mod merge_schemas; mod native; mod preview; +mod schema_file_input; mod text_document_completion; mod validate; @@ -89,6 +91,14 @@ pub fn validate(validate_params: String) -> Result<(), String> { validate::validate(&validate_params) } +/// Given a list of Prisma schema files (and their locations), returns the merged schema. +/// This is useful for `@prisma/client` generation, where the client needs a single - potentially large - schema, +/// while still allowing the user to split their schema copies into multiple files. +/// Internally, it uses `[validate]`. +pub fn merge_schemas(params: String) -> Result { + merge_schemas::merge_schemas(¶ms) +} + pub fn native_types(schema: String) -> String { native::run(&schema) } diff --git a/prisma-fmt/src/merge_schemas.rs b/prisma-fmt/src/merge_schemas.rs new file mode 100644 index 000000000000..bcb37922b68d --- /dev/null +++ b/prisma-fmt/src/merge_schemas.rs @@ -0,0 +1,127 @@ +use psl::reformat_validated_schema_into_single; +use serde::Deserialize; + +use crate::schema_file_input::SchemaFileInput; + +#[derive(Debug, Deserialize)] +pub struct MergeSchemasParams { + schema: SchemaFileInput, +} + +pub(crate) fn merge_schemas(params: &str) -> Result { + let params: MergeSchemasParams = match serde_json::from_str(params) { + Ok(params) => params, + Err(serde_err) => { + panic!("Failed to deserialize MergeSchemasParams: {serde_err}"); + } + }; + + let validated_schema = crate::validate::run(params.schema, false)?; + + let indent_width = 2usize; + let merged_schema = reformat_validated_schema_into_single(validated_schema, indent_width).unwrap(); + + Ok(merged_schema) +} + +#[cfg(test)] +mod tests { + use super::*; + use expect_test::expect; + use serde_json::json; + + #[test] + fn merge_two_valid_schemas_succeeds() { + let schema = vec![ + ( + "b.prisma", + r#" + model B { + id String @id + a A? + } + "#, + ), + ( + "a.prisma", + r#" + datasource db { + provider = "postgresql" + url = env("DBURL") + } + + model A { + id String @id + b_id String @unique + b B @relation(fields: [b_id], references: [id]) + } + "#, + ), + ]; + + let request = json!({ + "schema": schema, + }); + + let expected = expect![[r#" + model B { + id String @id + a A? + } + + datasource db { + provider = "postgresql" + url = env("DBURL") + } + + model A { + id String @id + b_id String @unique + b B @relation(fields: [b_id], references: [id]) + } + "#]]; + + let response = merge_schemas(&request.to_string()).unwrap(); + expected.assert_eq(&response); + } + + #[test] + fn merge_two_invalid_schemas_panics() { + let schema = vec![ + ( + "b.prisma", + r#" + model B { + id String @id + a A? + } + "#, + ), + ( + "a.prisma", + r#" + datasource db { + provider = "postgresql" + url = env("DBURL") + } + + model A { + id String @id + b_id String @unique + } + "#, + ), + ]; + + let request = json!({ + "schema": schema, + }); + + let expected = expect![[ + r#"{"error_code":"P1012","message":"\u001b[1;91merror\u001b[0m: \u001b[1mError validating field `a` in model `B`: The relation field `a` on model `B` is missing an opposite relation field on the model `A`. Either run `prisma format` or add it manually.\u001b[0m\n \u001b[1;94m-->\u001b[0m \u001b[4mb.prisma:4\u001b[0m\n\u001b[1;94m | \u001b[0m\n\u001b[1;94m 3 | \u001b[0m id String @id\n\u001b[1;94m 4 | \u001b[0m \u001b[1;91ma A?\u001b[0m\n\u001b[1;94m 5 | \u001b[0m }\n\u001b[1;94m | \u001b[0m\n\nValidation Error Count: 1"}"# + ]]; + + let response = merge_schemas(&request.to_string()).unwrap_err(); + expected.assert_eq(&response); + } +} diff --git a/prisma-fmt/src/schema_file_input.rs b/prisma-fmt/src/schema_file_input.rs new file mode 100644 index 000000000000..a7204510ed8b --- /dev/null +++ b/prisma-fmt/src/schema_file_input.rs @@ -0,0 +1,26 @@ +use psl::SourceFile; +use serde::Deserialize; + +/// Struct for supporting multiple files +/// in a backward-compatible way: can either accept +/// a single file contents or vector of (filePath, content) tuples. +/// Can be converted to the input for `psl::validate_multi_file` from +/// any of the variants. +#[derive(Deserialize, Debug)] +#[serde(untagged)] +pub(crate) enum SchemaFileInput { + Single(String), + Multiple(Vec<(String, String)>), +} + +impl From for Vec<(String, SourceFile)> { + fn from(value: SchemaFileInput) -> Self { + match value { + SchemaFileInput::Single(content) => vec![("schema.prisma".to_owned(), content.into())], + SchemaFileInput::Multiple(file_list) => file_list + .into_iter() + .map(|(filename, content)| (filename, content.into())) + .collect(), + } + } +} diff --git a/prisma-fmt/src/validate.rs b/prisma-fmt/src/validate.rs index 4cc9f88bf8bd..7bbce19e425d 100644 --- a/prisma-fmt/src/validate.rs +++ b/prisma-fmt/src/validate.rs @@ -1,14 +1,17 @@ +use psl::ValidatedSchema; use serde::Deserialize; use serde_json::json; use std::fmt::Write as _; +use crate::schema_file_input::SchemaFileInput; + // this mirrors user_facing_errors::common::SchemaParserError pub(crate) static SCHEMA_PARSER_ERROR_CODE: &str = "P1012"; #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct ValidateParams { - prisma_schema: String, + prisma_schema: SchemaFileInput, #[serde(default)] no_color: bool, } @@ -21,21 +24,22 @@ pub(crate) fn validate(params: &str) -> Result<(), String> { } }; - run(¶ms.prisma_schema, params.no_color) + run(params.prisma_schema, params.no_color)?; + Ok(()) } -pub fn run(input_schema: &str, no_color: bool) -> Result<(), String> { - let validate_schema = psl::validate(input_schema.into()); +pub fn run(input_schema: SchemaFileInput, no_color: bool) -> Result { + let validate_schema = psl::validate_multi_file(input_schema.into()); let diagnostics = &validate_schema.diagnostics; if !diagnostics.has_errors() { - return Ok(()); + return Ok(validate_schema); } // always colorise output regardless of the environment, which is important for Wasm colored::control::set_override(!no_color); - let mut formatted_error = diagnostics.to_pretty_string("schema.prisma", input_schema); + let mut formatted_error = validate_schema.render_own_diagnostics(); write!( formatted_error, "\nValidation Error Count: {}", @@ -109,6 +113,83 @@ mod tests { validate(&request.to_string()).unwrap(); } + #[test] + fn validate_multiple_files() { + let schema = vec![ + ( + "a.prisma", + r#" + datasource thedb { + provider = "postgresql" + url = env("DBURL") + } + + model A { + id String @id + b_id String @unique + b B @relation(fields: [b_id], references: [id]) + } + "#, + ), + ( + "b.prisma", + r#" + model B { + id String @id + a A? + } + "#, + ), + ]; + + let request = json!({ + "prismaSchema": schema, + }); + + validate(&request.to_string()).unwrap(); + } + + #[test] + fn validate_multiple_files_error() { + let schema = vec![ + ( + "a.prisma", + r#" + datasource thedb { + provider = "postgresql" + url = env("DBURL") + } + + model A { + id String @id + b_id String @unique + b B @relation(fields: [b_id], references: [id]) + } + "#, + ), + ( + "b.prisma", + r#" + model B { + id String @id + a A + } + "#, + ), + ]; + + let request = json!({ + "prismaSchema": schema, + }); + + let expected = expect![[ + r#"{"error_code":"P1012","message":"\u001b[1;91merror\u001b[0m: \u001b[1mError parsing attribute \"@relation\": The relation field `a` on Model `B` is required. This is no longer valid because it's not possible to enforce this constraint on the database level. Please change the field type from `A` to `A?` to fix this.\u001b[0m\n \u001b[1;94m-->\u001b[0m \u001b[4mb.prisma:4\u001b[0m\n\u001b[1;94m | \u001b[0m\n\u001b[1;94m 3 | \u001b[0m id String @id\n\u001b[1;94m 4 | \u001b[0m \u001b[1;91ma A\u001b[0m\n\u001b[1;94m 5 | \u001b[0m }\n\u001b[1;94m | \u001b[0m\n\nValidation Error Count: 1"}"# + ]]; + + let response = validate(&request.to_string()).unwrap_err(); + expected.assert_eq(&response); + } + #[test] fn validate_using_both_relation_mode_and_referential_integrity() { let schema = r#" diff --git a/prisma-schema-wasm/src/lib.rs b/prisma-schema-wasm/src/lib.rs index cd373128d607..43288dd32f54 100644 --- a/prisma-schema-wasm/src/lib.rs +++ b/prisma-schema-wasm/src/lib.rs @@ -58,6 +58,12 @@ pub fn validate(params: String) -> Result<(), JsError> { prisma_fmt::validate(params).map_err(|e| JsError::new(&e)) } +#[wasm_bindgen] +pub fn merge_schemas(input: String) -> Result { + register_panic_hook(); + prisma_fmt::merge_schemas(input).map_err(|e| JsError::new(&e)) +} + #[wasm_bindgen] pub fn native_types(input: String) -> String { register_panic_hook(); diff --git a/psl/parser-database/src/files.rs b/psl/parser-database/src/files.rs index f201c839eea0..9aef27d3d70a 100644 --- a/psl/parser-database/src/files.rs +++ b/psl/parser-database/src/files.rs @@ -15,6 +15,13 @@ impl Files { .enumerate() .map(|(idx, (path, contents, ast))| (FileId(idx as u32), path, contents, ast)) } + + pub(crate) fn into_iter(self) -> impl Iterator { + self.0 + .into_iter() + .enumerate() + .map(|(idx, (path, contents, ast))| (FileId(idx as u32), path, contents, ast)) + } } impl Index for Files { diff --git a/psl/parser-database/src/lib.rs b/psl/parser-database/src/lib.rs index e1dd7b72b259..61dc685f93b3 100644 --- a/psl/parser-database/src/lib.rs +++ b/psl/parser-database/src/lib.rs @@ -175,6 +175,16 @@ impl ParserDatabase { self.asts.iter().map(|(_, _, _, ast)| ast) } + /// Iterate all parsed ASTs, consuming parser database + pub fn into_iter_asts(self) -> impl Iterator { + self.asts.into_iter().map(|(_, _, _, ast)| ast) + } + + /// Iterate all file ids + pub fn iter_file_ids(&self) -> impl Iterator + '_ { + self.asts.iter().map(|(file_id, _, _, _)| file_id) + } + /// A parsed AST. pub fn ast(&self, file_id: FileId) -> &ast::SchemaAst { &self.asts[file_id].2 @@ -199,9 +209,19 @@ impl ParserDatabase { } /// The source file contents. - pub(crate) fn source(&self, file_id: FileId) -> &str { + pub fn source(&self, file_id: FileId) -> &str { self.asts[file_id].1.as_str() } + + /// Iterate all source file contents. + pub fn iter_sources(&self) -> impl Iterator { + self.asts.iter().map(|ast| ast.2.as_str()) + } + + /// The name of the file. + pub fn file_name(&self, file_id: FileId) -> &str { + self.asts[file_id].0.as_str() + } } impl std::ops::Index for ParserDatabase { diff --git a/psl/psl-core/src/lib.rs b/psl/psl-core/src/lib.rs index 9d1877bd26da..03e1dca4356f 100644 --- a/psl/psl-core/src/lib.rs +++ b/psl/psl-core/src/lib.rs @@ -20,7 +20,7 @@ pub use crate::{ configuration::{ Configuration, Datasource, DatasourceConnectorData, Generator, GeneratorConfigValue, StringFromEnvVar, }, - reformat::reformat, + reformat::{reformat, reformat_multiple, reformat_validated_schema_into_single}, }; pub use diagnostics; pub use parser_database::{self, is_reserved_type_name}; @@ -53,10 +53,14 @@ impl ValidatedSchema { self.relation_mode } - pub fn render_diagnostics(&self) -> String { + pub fn render_own_diagnostics(&self) -> String { + self.render_diagnostics(&self.diagnostics) + } + + pub fn render_diagnostics(&self, diagnostics: &Diagnostics) -> String { let mut out = Vec::new(); - for error in self.diagnostics.errors() { + for error in diagnostics.errors() { let (file_name, source, _) = &self.db[error.span().file_id]; error.pretty_print(&mut out, file_name, source.as_str()).unwrap(); } diff --git a/psl/psl-core/src/reformat.rs b/psl/psl-core/src/reformat.rs index 09d21c731b38..a18b32e301b2 100644 --- a/psl/psl-core/src/reformat.rs +++ b/psl/psl-core/src/reformat.rs @@ -1,46 +1,95 @@ -use crate::ParserDatabase; +use crate::{ParserDatabase, ValidatedSchema}; +use diagnostics::FileId; use parser_database::{ast::WithSpan, walkers}; use schema_ast::{ast, SourceFile}; -use std::{borrow::Cow, sync::Arc}; +use std::{borrow::Cow, collections::HashMap}; /// Returns either the reformatted schema, or the original input if we can't reformat. This happens /// if and only if the source does not parse to a well formed AST. pub fn reformat(source: &str, indent_width: usize) -> Option { - let file = SourceFile::new_allocated(Arc::from(source.to_owned().into_boxed_str())); + let reformatted = reformat_multiple(vec![("schema.prisma".to_owned(), source.into())], indent_width); - let mut diagnostics = diagnostics::Diagnostics::new(); - let db = parser_database::ParserDatabase::new_single_file(file, &mut diagnostics); + reformatted.first().map(|(_, source)| source).cloned() +} + +pub fn reformat_validated_schema_into_single(schema: ValidatedSchema, indent_width: usize) -> Option { + let db = schema.db; + + let source = db + .iter_sources() + .map(|source| source.to_owned()) + .collect::>() + .join("\n"); - let source_to_reformat = if diagnostics.has_errors() { - Cow::Borrowed(source) + schema_ast::reformat(&source, indent_width) +} + +pub fn reformat_multiple(sources: Vec<(String, SourceFile)>, indent_width: usize) -> Vec<(String, String)> { + let mut diagnostics = diagnostics::Diagnostics::new(); + let db = parser_database::ParserDatabase::new(sources, &mut diagnostics); + + if diagnostics.has_errors() { + db.iter_file_ids() + .filter_map(|file_id| { + let formatted_source = schema_ast::reformat(db.source(file_id), indent_width)?; + Some((db.file_name(file_id).to_owned(), formatted_source)) + }) + .collect() } else { - let mut missing_bits = Vec::new(); + let mut missing_bits = HashMap::new(); + let mut ctx = MagicReformatCtx { - original_schema: source, - missing_bits: &mut missing_bits, + missing_bits_map: &mut missing_bits, db: &db, }; + push_missing_fields(&mut ctx); push_missing_attributes(&mut ctx); push_missing_relation_attribute_args(&mut ctx); - missing_bits.sort_by_key(|bit| bit.position); + ctx.sort_missing_bits(); - if missing_bits.is_empty() { - Cow::Borrowed(source) - } else { - Cow::Owned(enrich(source, &missing_bits)) - } - }; + db.iter_file_ids() + .filter_map(|file_id| { + let source = if let Some(missing_bits) = ctx.get_missing_bits(file_id) { + Cow::Owned(enrich(db.source(file_id), missing_bits)) + } else { + Cow::Borrowed(db.source(file_id)) + }; + + let formatted_source = schema_ast::reformat(&source, indent_width)?; - schema_ast::reformat(&source_to_reformat, indent_width) + Some((db.file_name(file_id).to_owned(), formatted_source)) + }) + .collect() + } } struct MagicReformatCtx<'a> { - original_schema: &'a str, - missing_bits: &'a mut Vec, + missing_bits_map: &'a mut HashMap>, db: &'a ParserDatabase, } +impl<'a> MagicReformatCtx<'a> { + fn add_missing_bit(&mut self, file_id: FileId, bit: MissingBit) { + self.missing_bits_map.entry(file_id).or_default().push(bit); + } + + fn get_missing_bits(&self, file_id: FileId) -> Option<&Vec> { + let bits_vec = self.missing_bits_map.get(&file_id)?; + if bits_vec.is_empty() { + None + } else { + Some(bits_vec) + } + } + + fn sort_missing_bits(&mut self) { + self.missing_bits_map + .iter_mut() + .for_each(|(_, bits)| bits.sort_by_key(|bit| bit.position)) + } +} + fn enrich(input: &str, missing_bits: &[MissingBit]) -> String { let bits = missing_bits.iter().scan(0usize, |last_insert_position, missing_bit| { let start: usize = *last_insert_position; @@ -109,10 +158,13 @@ fn push_inline_relation_missing_arguments( (", ", "", relation_attribute.span.end - 1) }; - ctx.missing_bits.push(MissingBit { - position, - content: format!("{prefix}{extra_args}{suffix}"), - }); + ctx.add_missing_bit( + relation_attribute.span.file_id, + MissingBit { + position, + content: format!("{prefix}{extra_args}{suffix}"), + }, + ); } } @@ -136,10 +188,14 @@ fn push_missing_relation_attribute(inline_relation: walkers::InlineRelationWalke content.push_str(&references_argument(inline_relation)); content.push(')'); - ctx.missing_bits.push(MissingBit { - position: after_type(forward.ast_field().field_type.span().end, ctx.original_schema), - content, - }) + let file_id = forward.ast_field().span().file_id; + ctx.add_missing_bit( + file_id, + MissingBit { + position: after_type(forward.ast_field().field_type.span().end, ctx.db.source(file_id)), + content, + }, + ); } } @@ -167,10 +223,14 @@ fn push_missing_relation_fields(inline: walkers::InlineRelationWalker<'_>, ctx: }; let arity = if inline.is_one_to_one() { "?" } else { "[]" }; - ctx.missing_bits.push(MissingBit { - position: inline.referenced_model().ast_model().span().end - 1, - content: format!("{referencing_model_name} {referencing_model_name}{arity} {ignore}\n"), - }); + let span = inline.referenced_model().ast_model().span(); + ctx.add_missing_bit( + span.file_id, + MissingBit { + position: span.end - 1, + content: format!("{referencing_model_name} {referencing_model_name}{arity} {ignore}\n"), + }, + ); } if inline.forward_relation_field().is_none() { @@ -179,10 +239,14 @@ fn push_missing_relation_fields(inline: walkers::InlineRelationWalker<'_>, ctx: let arity = render_arity(forward_relation_field_arity(inline)); let fields_arg = fields_argument(inline); let references_arg = references_argument(inline); - ctx.missing_bits.push(MissingBit { - position: inline.referencing_model().ast_model().span().end - 1, - content: format!("{field_name} {field_type}{arity} @relation({fields_arg}, {references_arg})\n"), - }) + let span = inline.referencing_model().ast_model().span(); + ctx.add_missing_bit( + span.file_id, + MissingBit { + position: span.end - 1, + content: format!("{field_name} {field_type}{arity} @relation({fields_arg}, {references_arg})\n"), + }, + ) } } @@ -211,13 +275,17 @@ fn push_missing_scalar_fields(inline: walkers::InlineRelationWalker<'_>, ctx: &m let mut attributes: String = String::new(); if let Some((_datasource_name, _type_name, _args, span)) = field.blueprint.raw_native_type() { - attributes.push_str(&ctx.original_schema[span.start..span.end]); + attributes.push_str(&ctx.db.source(span.file_id)[span.start..span.end]); } - ctx.missing_bits.push(MissingBit { - position: inline.referencing_model().ast_model().span().end - 1, - content: format!("{field_name} {field_type}{arity} {attributes}\n"), - }); + let span = inline.referencing_model().ast_model().span(); + ctx.add_missing_bit( + span.file_id, + MissingBit { + position: span.end - 1, + content: format!("{field_name} {field_type}{arity} {attributes}\n"), + }, + ); } } diff --git a/psl/psl/build.rs b/psl/psl/build.rs index 509b60875998..1b0d560da551 100644 --- a/psl/psl/build.rs +++ b/psl/psl/build.rs @@ -1,19 +1,46 @@ use std::{env, fs, io::Write as _, path}; const VALIDATIONS_ROOT_DIR: &str = "tests/validation"; -const REFORMAT_ROOT_DIR: &str = "tests/reformatter"; +const REFORMAT_SINGLE_FILE_ROOT_DIR: &str = "tests/reformatter"; +const REFORMAT_MULTI_FILE_ROOT_DIR: &str = "tests/reformatter_multi_file"; const CARGO_MANIFEST_DIR: &str = env!("CARGO_MANIFEST_DIR"); fn main() { build_validation_tests(); - build_reformat_tests(); + build_reformat_single_file_tests(); + build_reformat_multi_file_tests(); } -fn build_reformat_tests() { - println!("cargo:rerun-if-changed={REFORMAT_ROOT_DIR}"); +fn build_reformat_multi_file_tests() { + println!("cargo:rerun-if-changed={REFORMAT_MULTI_FILE_ROOT_DIR}"); + let schema_dirs_to_reformat = fs::read_dir(format!("{CARGO_MANIFEST_DIR}/{REFORMAT_MULTI_FILE_ROOT_DIR}")) + .unwrap() + .map(Result::unwrap) + .filter_map(|entry| { + let name = entry.file_name(); + let name = name.to_str().unwrap(); + if name == "." || name == ".." || name.ends_with(".reformatted") { + None + } else { + Some(name.trim_start_matches('/').to_owned()) + } + }); + let mut out_file = out_file("reformat_multi_file_tests.rs"); + for schema_dir in schema_dirs_to_reformat { + let test_name = test_name(&schema_dir); + writeln!( + out_file, + "#[test] fn {test_name}() {{ run_reformat_multi_file_test(\"{schema_dir}\"); }}" + ) + .unwrap(); + } +} + +fn build_reformat_single_file_tests() { + println!("cargo:rerun-if-changed={REFORMAT_SINGLE_FILE_ROOT_DIR}"); let mut all_schemas = Vec::new(); - find_all_schemas("", &mut all_schemas, REFORMAT_ROOT_DIR); + find_all_schemas("", &mut all_schemas, REFORMAT_SINGLE_FILE_ROOT_DIR); let mut out_file = out_file("reformat_tests.rs"); let schemas_to_reformat = all_schemas.iter().filter(|name| !name.ends_with(".reformatted.prisma")); diff --git a/psl/psl/src/lib.rs b/psl/psl/src/lib.rs index d1c38eaf4330..af78ef19b3b8 100644 --- a/psl/psl/src/lib.rs +++ b/psl/psl/src/lib.rs @@ -12,6 +12,8 @@ pub use psl_core::{ parser_database::{self, SourceFile}, reachable_only_with_capability, reformat, + reformat_multiple, + reformat_validated_schema_into_single, schema_ast, set_config_dir, Configuration, diff --git a/psl/psl/tests/multi_file/basic.rs b/psl/psl/tests/multi_file/basic.rs index fd1c2d0e4f95..d5eaf5b8b489 100644 --- a/psl/psl/tests/multi_file/basic.rs +++ b/psl/psl/tests/multi_file/basic.rs @@ -8,7 +8,7 @@ fn expect_errors(schemas: &[[&'static str; 2]], expectation: expect_test::Expect .collect(), ); - let actual = out.render_diagnostics(); + let actual = out.render_own_diagnostics(); expectation.assert_eq(&actual) } diff --git a/psl/psl/tests/panic_with_diff/mod.rs b/psl/psl/tests/panic_with_diff/mod.rs index a66b81643fdc..6360545e8515 100644 --- a/psl/psl/tests/panic_with_diff/mod.rs +++ b/psl/psl/tests/panic_with_diff/mod.rs @@ -1,9 +1,12 @@ -pub(crate) fn panic_with_diff(expected: &str, found: &str) { +pub(crate) fn panic_with_diff(expected: &str, found: &str, name: Option<&str>) { + let title = name + .map(|name| format!("Snapshot '{name}'")) + .unwrap_or("Snapshot".to_owned()); let chunks = dissimilar::diff(expected, found); let diff = format_chunks(chunks); panic!( r#" -Snapshot comparison failed. Run the test again with UPDATE_EXPECT=1 in the environment to update the snapshot. +${title} comparison failed. Run the test again with UPDATE_EXPECT=1 in the environment to update the snapshot. ===== EXPECTED ==== {expected} diff --git a/psl/psl/tests/reformat_tests.rs b/psl/psl/tests/reformat_tests.rs index c945ad53c077..c3c1748d8fed 100644 --- a/psl/psl/tests/reformat_tests.rs +++ b/psl/psl/tests/reformat_tests.rs @@ -24,7 +24,7 @@ fn run_reformat_test(test_file_path: &str) { let mut file = fs::File::create(&snapshot_file_name).unwrap(); // truncate file.write_all(reformatted_text.as_bytes()).unwrap(); } else { - panic_with_diff::panic_with_diff(&expected_text, &reformatted_text); + panic_with_diff::panic_with_diff(&expected_text, &reformatted_text, None); } if reformat(&reformatted_text) != reformatted_text { @@ -39,3 +39,72 @@ include!(concat!(env!("OUT_DIR"), "/reformat_tests.rs")); fn reformat(s: &str) -> String { psl::reformat(s, 2).unwrap() } + +mod reformat_multi_file { + use std::{collections::HashMap, fs, io::Write, path}; + + use psl::{reformat_multiple, SourceFile}; + + use crate::panic_with_diff; + + const MULTIFILE_TESTS_ROOT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/reformatter_multi_file"); + + #[inline(never)] + fn run_reformat_multi_file_test(test_dir_name: &str) { + let dir_path = path::Path::new(MULTIFILE_TESTS_ROOT).join(test_dir_name); + let snapshot_dir_path = path::Path::new(MULTIFILE_TESTS_ROOT).join(format!("{test_dir_name}.reformatted")); + + fs::create_dir_all(&snapshot_dir_path).unwrap(); + let schemas: Vec<_> = read_schemas_from_dir(dir_path).collect(); + + let result = reformat_multiple(schemas, 2); + + let should_update = std::env::var("UPDATE_EXPECT").is_ok(); + let mut snapshot_schemas: HashMap<_, _> = read_schemas_from_dir(&snapshot_dir_path).collect(); + for (path, content) in result { + let content = content.as_str(); + let snapshot_content = snapshot_schemas.remove(&path).unwrap_or_default(); + let snapshot_content = snapshot_content.as_str(); + if content == snapshot_content { + continue; + } + + if should_update { + let snapshot_file_path = path::Path::new(&snapshot_dir_path).join(path); + let mut file = fs::File::create(&snapshot_file_path).unwrap(); + file.write_all(content.as_bytes()).unwrap() + } else { + panic_with_diff::panic_with_diff(snapshot_content, content, Some(&path)); + } + } + + // cleanup removed files + for missing_file in snapshot_schemas.keys() { + if should_update { + fs::remove_file(path::Path::new(&snapshot_dir_path).join(missing_file)).unwrap() + } else { + panic!("{missing_file} is present in the snapshot directory, but missing from formatting results") + } + } + } + + fn read_schemas_from_dir(root_dir_path: impl AsRef) -> impl Iterator { + let root_dir_path = root_dir_path.as_ref().to_owned(); + fs::read_dir(&root_dir_path) + .unwrap() + .map(Result::unwrap) + .filter_map(move |entry| { + let file_name = entry.file_name(); + let file_name = file_name.to_str().unwrap(); + if !file_name.ends_with(".prisma") { + None + } else { + let full_path = root_dir_path.clone().join(file_name); + let content = fs::read_to_string(full_path).unwrap(); + Some((file_name.to_owned(), content.into())) + } + }) + } + + include!(concat!(env!("OUT_DIR"), "/reformat_multi_file_tests.rs")); +} diff --git a/psl/psl/tests/reformatter_multi_file/align_blocks.reformatted/User.prisma b/psl/psl/tests/reformatter_multi_file/align_blocks.reformatted/User.prisma new file mode 100644 index 000000000000..5a45cefe0114 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/align_blocks.reformatted/User.prisma @@ -0,0 +1,5 @@ +model User { + id Int @id @default(autoincrement()) + name String + age Float +} diff --git a/psl/psl/tests/reformatter_multi_file/align_blocks.reformatted/db.prisma b/psl/psl/tests/reformatter_multi_file/align_blocks.reformatted/db.prisma new file mode 100644 index 000000000000..e4acdefaaa68 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/align_blocks.reformatted/db.prisma @@ -0,0 +1,9 @@ +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" + previewFeatures = ["prismaSchemaFolder"] +} diff --git a/psl/psl/tests/reformatter_multi_file/align_blocks/User.prisma b/psl/psl/tests/reformatter_multi_file/align_blocks/User.prisma new file mode 100644 index 000000000000..f24cc66e4d25 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/align_blocks/User.prisma @@ -0,0 +1,5 @@ +model User { + id Int @id @default( autoincrement()) + name String + age Float +} \ No newline at end of file diff --git a/psl/psl/tests/reformatter_multi_file/align_blocks/db.prisma b/psl/psl/tests/reformatter_multi_file/align_blocks/db.prisma new file mode 100644 index 000000000000..34e89da163e4 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/align_blocks/db.prisma @@ -0,0 +1,9 @@ +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" + previewFeatures = ["prismaSchemaFolder"] +} \ No newline at end of file diff --git a/psl/psl/tests/reformatter_multi_file/relation_1_to_1.reformatted/Post.prisma b/psl/psl/tests/reformatter_multi_file/relation_1_to_1.reformatted/Post.prisma new file mode 100644 index 000000000000..84b3d54ea7f5 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_1_to_1.reformatted/Post.prisma @@ -0,0 +1,5 @@ +model Post { + id Int @id @default(autoincrement()) + title String + User User? +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_1_to_1.reformatted/User.prisma b/psl/psl/tests/reformatter_multi_file/relation_1_to_1.reformatted/User.prisma new file mode 100644 index 000000000000..fc08b7b116d6 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_1_to_1.reformatted/User.prisma @@ -0,0 +1,7 @@ +model User { + id Int @id @default(autoincrement()) + name String + age Float + postId Int @unique + post Post @relation(fields: [postId], references: [id]) +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_1_to_1.reformatted/db.prisma b/psl/psl/tests/reformatter_multi_file/relation_1_to_1.reformatted/db.prisma new file mode 100644 index 000000000000..e4acdefaaa68 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_1_to_1.reformatted/db.prisma @@ -0,0 +1,9 @@ +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" + previewFeatures = ["prismaSchemaFolder"] +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_1_to_1/Post.prisma b/psl/psl/tests/reformatter_multi_file/relation_1_to_1/Post.prisma new file mode 100644 index 000000000000..149498bbab37 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_1_to_1/Post.prisma @@ -0,0 +1,4 @@ +model Post { + id Int @id @default(autoincrement()) + title String +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_1_to_1/User.prisma b/psl/psl/tests/reformatter_multi_file/relation_1_to_1/User.prisma new file mode 100644 index 000000000000..51b16016f509 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_1_to_1/User.prisma @@ -0,0 +1,7 @@ +model User { + id Int @id @default(autoincrement()) + name String + age Float + postId Int @unique + post Post @relation(fields: [postId], references: [id]) +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_1_to_1/db.prisma b/psl/psl/tests/reformatter_multi_file/relation_1_to_1/db.prisma new file mode 100644 index 000000000000..e4acdefaaa68 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_1_to_1/db.prisma @@ -0,0 +1,9 @@ +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" + previewFeatures = ["prismaSchemaFolder"] +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_list.reformatted/Post.prisma b/psl/psl/tests/reformatter_multi_file/relation_list.reformatted/Post.prisma new file mode 100644 index 000000000000..93707cea33fd --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_list.reformatted/Post.prisma @@ -0,0 +1,6 @@ +model Post { + id Int @id @default(autoincrement()) + title String + User User? @relation(fields: [userId], references: [id]) + userId Int? +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_list.reformatted/User.prisma b/psl/psl/tests/reformatter_multi_file/relation_list.reformatted/User.prisma new file mode 100644 index 000000000000..0057debd6bd5 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_list.reformatted/User.prisma @@ -0,0 +1,6 @@ +model User { + id Int @id @default(autoincrement()) + name String + age Float + posts Post[] +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_list.reformatted/db.prisma b/psl/psl/tests/reformatter_multi_file/relation_list.reformatted/db.prisma new file mode 100644 index 000000000000..e4acdefaaa68 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_list.reformatted/db.prisma @@ -0,0 +1,9 @@ +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" + previewFeatures = ["prismaSchemaFolder"] +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_list/Post.prisma b/psl/psl/tests/reformatter_multi_file/relation_list/Post.prisma new file mode 100644 index 000000000000..149498bbab37 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_list/Post.prisma @@ -0,0 +1,4 @@ +model Post { + id Int @id @default(autoincrement()) + title String +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_list/User.prisma b/psl/psl/tests/reformatter_multi_file/relation_list/User.prisma new file mode 100644 index 000000000000..91bb36ac360b --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_list/User.prisma @@ -0,0 +1,6 @@ +model User { + id Int @id @default(autoincrement()) + name String + age Float + posts Post[] +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_list/db.prisma b/psl/psl/tests/reformatter_multi_file/relation_list/db.prisma new file mode 100644 index 000000000000..e4acdefaaa68 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_list/db.prisma @@ -0,0 +1,9 @@ +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" + previewFeatures = ["prismaSchemaFolder"] +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_single.reformatted/Post.prisma b/psl/psl/tests/reformatter_multi_file/relation_single.reformatted/Post.prisma new file mode 100644 index 000000000000..d5524c154ee7 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_single.reformatted/Post.prisma @@ -0,0 +1,5 @@ +model Post { + id Int @id @default(autoincrement()) + title String + User User[] +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_single.reformatted/User.prisma b/psl/psl/tests/reformatter_multi_file/relation_single.reformatted/User.prisma new file mode 100644 index 000000000000..a2690c937c76 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_single.reformatted/User.prisma @@ -0,0 +1,7 @@ +model User { + id Int @id @default(autoincrement()) + name String + age Float + post Post @relation(fields: [postId], references: [id]) + postId Int +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_single.reformatted/db.prisma b/psl/psl/tests/reformatter_multi_file/relation_single.reformatted/db.prisma new file mode 100644 index 000000000000..e4acdefaaa68 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_single.reformatted/db.prisma @@ -0,0 +1,9 @@ +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" + previewFeatures = ["prismaSchemaFolder"] +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_single/Post.prisma b/psl/psl/tests/reformatter_multi_file/relation_single/Post.prisma new file mode 100644 index 000000000000..149498bbab37 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_single/Post.prisma @@ -0,0 +1,4 @@ +model Post { + id Int @id @default(autoincrement()) + title String +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_single/User.prisma b/psl/psl/tests/reformatter_multi_file/relation_single/User.prisma new file mode 100644 index 000000000000..9d892ac43e6e --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_single/User.prisma @@ -0,0 +1,6 @@ +model User { + id Int @id @default(autoincrement()) + name String + age Float + post Post +} diff --git a/psl/psl/tests/reformatter_multi_file/relation_single/db.prisma b/psl/psl/tests/reformatter_multi_file/relation_single/db.prisma new file mode 100644 index 000000000000..e4acdefaaa68 --- /dev/null +++ b/psl/psl/tests/reformatter_multi_file/relation_single/db.prisma @@ -0,0 +1,9 @@ +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" + previewFeatures = ["prismaSchemaFolder"] +} diff --git a/psl/psl/tests/validation_tests.rs b/psl/psl/tests/validation_tests.rs index 6d0120cf933e..9859dbbc6bd3 100644 --- a/psl/psl/tests/validation_tests.rs +++ b/psl/psl/tests/validation_tests.rs @@ -91,7 +91,7 @@ fn run_validation_test(test_file_path: &str) { return; } - panic_with_diff::panic_with_diff(&last_comment_contents, &diagnostics) + panic_with_diff::panic_with_diff(&last_comment_contents, &diagnostics, None) } include!(concat!(env!("OUT_DIR"), "/validation_tests.rs")); diff --git a/psl/schema-ast/src/reformat.rs b/psl/schema-ast/src/reformat.rs index 853258226e2f..3492bb0524f0 100644 --- a/psl/schema-ast/src/reformat.rs +++ b/psl/schema-ast/src/reformat.rs @@ -19,6 +19,8 @@ pub fn reformat(input: &str, indent_width: usize) -> Option { renderer.stream.push('\n'); } + // TODO: why do we need to use a `Some` here? + // Also: if we really want to return an `Option`, why do unwrap in `ast.next()`? Some(renderer.stream) } diff --git a/psl/schema-ast/src/source_file.rs b/psl/schema-ast/src/source_file.rs index 3d7deafd3a24..63329ad93c39 100644 --- a/psl/schema-ast/src/source_file.rs +++ b/psl/schema-ast/src/source_file.rs @@ -6,6 +6,14 @@ pub struct SourceFile { contents: Contents, } +impl Default for SourceFile { + fn default() -> Self { + Self { + contents: Contents::Static(""), + } + } +} + impl SourceFile { pub fn new_static(content: &'static str) -> Self { Self { diff --git a/query-engine/dmmf/src/lib.rs b/query-engine/dmmf/src/lib.rs index 340566c83de1..42cfb2757ca4 100644 --- a/query-engine/dmmf/src/lib.rs +++ b/query-engine/dmmf/src/lib.rs @@ -4,6 +4,7 @@ mod serialization_ast; #[cfg(test)] mod tests; +use psl::ValidatedSchema; pub use serialization_ast::DataModelMetaFormat; use ast_builders::schema_to_dmmf; @@ -15,6 +16,11 @@ pub fn dmmf_json_from_schema(schema: &str) -> String { serde_json::to_string(&dmmf).unwrap() } +pub fn dmmf_json_from_validated_schema(schema: ValidatedSchema) -> String { + let dmmf = from_precomputed_parts(&schema::build(Arc::new(schema), true)); + serde_json::to_string(&dmmf).unwrap() +} + pub fn dmmf_from_schema(schema: &str) -> DataModelMetaFormat { let schema = Arc::new(psl::parse_schema(schema).unwrap()); from_precomputed_parts(&schema::build(schema, true))