Skip to content

Commit

Permalink
Enhance schemaExtensions to Support Both Files and Directories (#4859)
Browse files Browse the repository at this point in the history
Summary:
**Summary**

This update enhances the behavior of the `"schemaExtensions"` configuration key, allowing it to specify either:
- A folder containing GraphQL schema extension files (as originally documented).
- A specific .graphql schema extension file (new functionality).

This change unifies behavior between the Watchman query and the walkdir implementation, ensuring consistent handling of schema extensions regardless of configuration.

**Details**

Previously, the Relay documentation instructed users to configure "schemaExtensions" with a folder path containing the GraphQL schema extensions. However:
	•	Relay did not enforce that the target was a folder.
	•	Users could already specify a single .graphql schema extension file directly and it would work when not using Watchman.

This update ensures both approaches work seamlessly with Watchman and enhancing flexibility. The documentation has also been updated to reflect this new functionality.

**Why This Change?**

This improvement resolves an inconsistency between Watchman and non-Watchman setups, offering better support for varying project configurations without breaking existing workflows.

Pull Request resolved: #4859

Reviewed By: evanyeung

Differential Revision: D68106213

Pulled By: captbaritone

fbshipit-source-id: ca2f2f401429face4b60c88b033099450e6a3e05
  • Loading branch information
sverrejoh authored and facebook-github-bot committed Jan 14, 2025
1 parent 99cbea8 commit be8f5f7
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 13 deletions.
8 changes: 4 additions & 4 deletions compiler/crates/relay-compiler/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -994,12 +994,12 @@ impl SingleProjectConfigFile {
}
})?,
);
for extension_dir in self.schema_extensions.iter() {
for extension_path in self.schema_extensions.iter() {
paths.push(
canonicalize(root_dir.join(extension_dir.clone())).map_err(|_| {
ConfigValidationError::ExtensionDirNotExistent {
canonicalize(root_dir.join(extension_path.clone())).map_err(|_| {
ConfigValidationError::ExtensionPathNotExistent {
project_name: self.project_name,
extension_dir: extension_dir.clone(),
extension_path: extension_path.clone(),
}
})?,
);
Expand Down
6 changes: 3 additions & 3 deletions compiler/crates/relay-compiler/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,11 @@ pub enum ConfigValidationError {
},

#[error(
"The `schemaExtensions` configured for project `{project_name}` does not exist at `{extension_dir}`."
"The `schemaExtensions` configured for project `{project_name}` does not exist at `{extension_path}`."
)]
ExtensionDirNotExistent {
ExtensionPathNotExistent {
project_name: ProjectName,
extension_dir: PathBuf,
extension_path: PathBuf,
},

#[error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub fn get_watchman_expr(config: &Config) -> Expr {

let extension_roots = config.get_extension_roots();
if !extension_roots.is_empty() {
let extensions_expr = expr_graphql_files_in_dirs(extension_roots);
let extensions_expr = expr_graphql_file_or_dir_contents(extension_roots);
expressions.push(extensions_expr);
}

Expand Down Expand Up @@ -132,13 +132,27 @@ fn expr_files_in_dirs(roots: Vec<PathBuf>) -> Expr {

fn expr_graphql_files_in_dirs(roots: Vec<PathBuf>) -> Expr {
Expr::All(vec![
// ending in *.graphql
// ending in *.graphql or *.gql
Expr::Suffix(vec!["graphql".into(), "gql".into()]),
// in one of the extension directories
expr_files_in_dirs(roots),
])
}

// Expression to get all graphql items by path or path of containing folder.
fn expr_graphql_file_or_dir_contents(paths: Vec<PathBuf>) -> Expr {
Expr::All(vec![
Expr::Suffix(vec!["graphql".into(), "gql".into()]),
Expr::Any(vec![
Expr::Name(NameTerm {
paths: paths.clone(),
wholename: true,
}),
expr_files_in_dirs(paths),
]),
])
}

/// Helper to create an `anyof` expression if multiple items are passed or just
/// return the expression for a single item input `Vec`.
/// Panics for empty expressions. These are not valid in Watchman. We could
Expand Down
2 changes: 1 addition & 1 deletion packages/relay-compiler/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ file sources, and "listen" to the file changes in the "watch" mode. If
[string]
- `excludes` Directories to ignore under `src`. [array] [default:
["\*\*/node_modules/\*\*", "\*\*/__mocks__/\*\*", "\*\*/__generated__/\*\*"]]
- `schemaExtensions` List of directories with schema extensions. [array]
- `schemaExtensions` List of files or directories with schema extensions. [array]
- `schemaConfig`
- `nodeInterfaceIdField` Configure the name of the globally unique ID field on
the Node interface. Useful if you can't use the default `id` field name.
Expand Down
7 changes: 4 additions & 3 deletions website/docs/guides/client-schema-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ The Relay Compiler fully supports client-side extensions of the schema, which al

## Extending the server schema

To extend the server schema, create a new `.graphql` file inside your `--src` directory.
Let's call it `./src/clientSchema.graphql`.
This file needs to be in a folder referenced in the `"schemaExtensions"` of your Relay config.
To extend the server schema, create a new `.graphql` file inside your `--src`
directory. Let's call it `./src/clientSchema.graphql`. This file needs to be
referenced in the `"schemaExtensions"` of your Relay config, either directly or
via its folder.

This schema describes what local data can be queried on the client.
It can even be used to extend an existing server schema.
Expand Down

0 comments on commit be8f5f7

Please sign in to comment.