diff --git a/compiler/crates/common/src/feature_flags.rs b/compiler/crates/common/src/feature_flags.rs index ac67d37726e84..4cb6a57aee7f4 100644 --- a/compiler/crates/common/src/feature_flags.rs +++ b/compiler/crates/common/src/feature_flags.rs @@ -17,6 +17,7 @@ use serde::Serialize; use crate::Rollout; +/// **NOTE**: Every change on this struct should be reflected into the `relay-compiler/index.d.ts` file. #[derive(Default, Debug, Serialize, Deserialize, Clone)] #[serde(deny_unknown_fields)] pub struct FeatureFlags { @@ -86,6 +87,7 @@ pub struct FeatureFlags { pub enable_strict_custom_scalars: bool, } +/// **NOTE**: Every change on this struct should be reflected into the `relay-compiler/index.d.ts` file. #[derive(Debug, Deserialize, Clone, Serialize)] #[serde(tag = "kind", rename_all = "lowercase")] pub enum FeatureFlag { diff --git a/compiler/crates/relay-compiler/src/config.rs b/compiler/crates/relay-compiler/src/config.rs index 46582a5aa336d..faaa2091d0711 100644 --- a/compiler/crates/relay-compiler/src/config.rs +++ b/compiler/crates/relay-compiler/src/config.rs @@ -620,6 +620,8 @@ fn get_default_excludes() -> Vec { } /// Schema of the compiler configuration JSON file. +/// +/// **NOTE**: Every change on this struct should be reflected into the `relay-compiler/index.d.ts` file. #[derive(Debug, Serialize, Deserialize, Default)] #[serde(deny_unknown_fields, rename_all = "camelCase")] struct MultiProjectConfigFile { @@ -662,6 +664,7 @@ struct MultiProjectConfigFile { is_dev_variable_name: Option, } +/// **NOTE**: Every change on this struct should be reflected into the `relay-compiler/index.d.ts` file. #[derive(Debug, Serialize, Deserialize)] #[serde(deny_unknown_fields, rename_all = "camelCase", default)] pub struct SingleProjectConfigFile { diff --git a/compiler/crates/relay-config/src/js_module_format.rs b/compiler/crates/relay-config/src/js_module_format.rs index 1ceac0327d638..3abce621fbddc 100644 --- a/compiler/crates/relay-config/src/js_module_format.rs +++ b/compiler/crates/relay-config/src/js_module_format.rs @@ -9,6 +9,8 @@ use serde::Deserialize; use serde::Serialize; /// Formatting style for generated files. +/// +/// **NOTE**: Every change on this struct should be reflected into the `relay-compiler/index.d.ts` file. #[derive(Copy, Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] pub enum JsModuleFormat { diff --git a/compiler/crates/relay-config/src/module_import_config.rs b/compiler/crates/relay-config/src/module_import_config.rs index b1ed8dfbaf9fb..5c46d8622e629 100644 --- a/compiler/crates/relay-config/src/module_import_config.rs +++ b/compiler/crates/relay-config/src/module_import_config.rs @@ -10,6 +10,8 @@ use serde::Deserialize; use serde::Serialize; /// Configuration for @module. +/// +/// **NOTE**: Every change on this struct should be reflected into the `relay-compiler/index.d.ts` file. #[derive(Debug, Deserialize, Serialize, Default, Copy, Clone)] #[serde(deny_unknown_fields, rename_all = "camelCase")] pub struct ModuleImportConfig { diff --git a/compiler/crates/relay-config/src/project_config.rs b/compiler/crates/relay-config/src/project_config.rs index d1293ed63b40c..716e00ea90cdd 100644 --- a/compiler/crates/relay-config/src/project_config.rs +++ b/compiler/crates/relay-config/src/project_config.rs @@ -106,6 +106,7 @@ pub struct LocalPersistConfig { pub include_query_text: bool, } +/// **NOTE**: Every change on this struct should be reflected into the `relay-compiler/index.d.ts` file. #[derive(Debug, Serialize, Clone)] #[serde(untagged)] pub enum PersistConfig { @@ -175,6 +176,7 @@ impl Debug for ExtraArtifactsConfig { } } +/// **NOTE**: Every change on this struct should be reflected into the `relay-compiler/index.d.ts` file. #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SchemaConfig { diff --git a/compiler/crates/relay-config/src/resolvers_schema_module_config.rs b/compiler/crates/relay-config/src/resolvers_schema_module_config.rs index 46ebf2fc77bbe..faa5816858a9f 100644 --- a/compiler/crates/relay-config/src/resolvers_schema_module_config.rs +++ b/compiler/crates/relay-config/src/resolvers_schema_module_config.rs @@ -11,6 +11,8 @@ use serde::Deserialize; use serde::Serialize; /// Configuration for resolvers_schema_module generation +/// +/// **NOTE**: Every change on this struct should be reflected into the `relay-compiler/index.d.ts` file. #[derive(Default, Serialize, Deserialize, Debug)] #[serde(deny_unknown_fields, rename_all = "camelCase")] pub struct ResolversSchemaModuleConfig { diff --git a/compiler/crates/relay-config/src/typegen_config.rs b/compiler/crates/relay-config/src/typegen_config.rs index faa229bfd60ef..32753bf1dcfa4 100644 --- a/compiler/crates/relay-config/src/typegen_config.rs +++ b/compiler/crates/relay-config/src/typegen_config.rs @@ -17,6 +17,7 @@ use strum::EnumIter; use strum::IntoEnumIterator; type FnvIndexMap = IndexMap; +/// **NOTE**: Every change on this struct should be reflected into the `relay-compiler/index.d.ts` file. #[derive( EnumIter, strum::Display, @@ -50,6 +51,7 @@ impl TypegenLanguage { } } +/// **NOTE**: Every change on this struct should be reflected into the `relay-compiler/index.d.ts` file. #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(untagged)] pub enum CustomScalarType { diff --git a/gulpfile.js b/gulpfile.js index 86e4aef8152ad..7129e8bae702e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -355,7 +355,7 @@ const relayCompiler = gulp.parallel( }, function copyPackageFiles() { return gulp - .src(['README.md', 'package.json', 'cli.js', 'index.js'], { + .src(['README.md', 'package.json', 'cli.js', 'index.js', 'index.d.ts'], { cwd: path.join(PACKAGES, 'relay-compiler'), }) .pipe(gulp.dest(path.join(DIST, 'relay-compiler'))); diff --git a/packages/relay-compiler/README.md b/packages/relay-compiler/README.md index 979620e129ab8..5c282f5755f7a 100644 --- a/packages/relay-compiler/README.md +++ b/packages/relay-compiler/README.md @@ -113,6 +113,9 @@ file sources, and "listen" to the file changes in the "watch" mode. If - `criticalLevel` The severity level of diagnostics that will cause the compiler to error out on. ["error" | "warning" | "info"] +> [!TIP] +> For more details, and configuration options see: [Relay Compiler Configuration](https://github.com/facebook/relay/tree/main/packages/relay-compiler/index.d.ts) + ### CLI Arguments - `--repersist` Run the persister even if the query has not changed. diff --git a/packages/relay-compiler/index.d.ts b/packages/relay-compiler/index.d.ts new file mode 100644 index 0000000000000..e6b0f75fc64fb --- /dev/null +++ b/packages/relay-compiler/index.d.ts @@ -0,0 +1,367 @@ +/** + * This is the object containing the configuration of your Relay project. + * + * @see https://github.com/facebook/relay/tree/main/packages/relay-compiler + */ +export type RelayConfig = RelayConfigSingleProject | RelayConfigMultiProject; + +/** + * This is the configuration containing the object for single project configuration. + */ +export type RelayConfigSingleProject = { + /** Root directory of application code. */ + src: string; + /** Relative path to the file with GraphQL SDL file. */ + schema: string; + /** The name of the language used for input files and generated artifacts. */ + language: RelayConfigLanguage; + /** A specific directory to output all artifacts to. When enabling this the babel plugin needs `artifactDirectory` to be set as well. */ + artifactDirectory?: string; + /** + * Directories to ignore under `src`. + * + * @default ["/node_modules/", "/mocks/", "/generated/"] + */ + excludes?: string[]; + /** Extra config for the schema itself. */ + schemaConfig?: RelayConfigSchemaConfig; + /** + * This option controls whether or not a catch-all entry is added to enum type definitions values that may be added + * in the future. Enabling this means you will have to update your application whenever the GraphQL server schema adds + * new enum values to prevent it from breaking. + * + * @default false + */ + noFutureProofEnums?: boolean; + /** Mappings from custom scalars in your schema to built-in GraphQL types, for type emission purposes. */ + customScalars?: RelayConfigCustomScalars; + /** + * This option enables emitting ES modules artifacts. + * + * @default false + */ + eagerEsModules?: boolean; + /** Relay supports two versions of the config. */ + persistConfig?: RelayConfigPersist; + /** Name of the command that runs the relay compiler */ + codegenCommand?: string; + /** + * Name of the global variable for dev mode + * + * @default "__DEV__" + */ + isDevVariableName?: string; + /** + * Formatting style for generated files. + * + * @default "commonjs" + */ + jsModuleFormat?: 'commonjs' | 'haste'; + /** + * Options for configuring the output of compiler diagnostics. + * + * @default + * ```js + * { + * criticalLevel: "error", + * } + * ``` + */ + diagnosticReportConfig?: RelayConfigDiagnosticReportConfig; + /** The experimental features related to Relay. */ + featureFlags?: RelayConfigFeatureFlags; + /** + * Keep the previous compiler behavior by outputting an union of the raw type and null, + * and not the **correct** behavior of an union with the raw type, null and undefined. + * + * @default false + */ + typescript_exclude_undefined_from_nullable_union?: boolean; +} + +/** + * This is the configuration containing the object for multiproject configuration. + */ +export type RelayConfigMultiProject = { + /** Name of this configuration. */ + name?: string; + /** Root directory relative of this configuration. */ + root?: string; + /** A header to be prepend to each generated artifact. */ + header?: string[]; + /** + * A mapping directory from directory paths (relative to the root) to a project. + * If a path is a subdirectory of another path, the more specific path wins. + */ + sources: Record; + /** Name of the command that runs the relay compiler */ + codegenCommand?: string; + /** + * Directory to be excluded under each project. + * + * @default ["/node_modules/", "/mocks/", "/generated/"] + */ + excludes?: string[]; + /** Configuration of each project that will be reached by the compiler. */ + projects: Record; + savedStateConfig?: { + mergebase?: string; + "mergebase-with"?: string; + "saved-state"?: { + storage?: string; + "commit-id"?: string; + config?: any; + }; + }; + /** + * Name of the global variable for dev mode + * + * @default "__DEV__" + */ + isDevVariableName?: string; +} + +type RelayConfigMultiProjectItemSchemaConfig = + | { + /** The path of your schema file. */ + schema: string + } + | { + /** + * A directory containing a schema broken up in multiple `*.graphql` files. + */ + schemaDir: string; + } + +type RelayConfigMultiProjectItemDynamicModuleProvider = + | { mode: "JSResource" } + | { mode: "Custom", statement?: string; }; + +type RelayConfigMultiProjectItemTypegenConfig = { + /** + * The name of the language used for input files and generated artifacts. + * + * @default "javascript" + */ + language: RelayConfigLanguage; + /** + * (Flow only) When set, enum values are imported from a module with this suffix. For example, an enum Foo and this property set to `.test` would be imported from `Foo.test` + */ + enumModuleSuffix?: string; + /** + * (Flow only) When set, generated input types will have the listed fields optional even if the schema defines them as required. + */ + optionalInputFields?: string[]; + /** + * (TypeScript only) Whether to use the `import type` syntax introduced in Typescript version 3.8. This will prevent warnings from `importsNotUsedAsValues`. + */ + useImportTypeSyntax?: boolean; + customScalarTypes?: RelayConfigCustomScalars; + /** + * Require all GraphQL scalar types mapping to be defined, will throw if a GraphQL scalar type doesn't have a JS type. + */ + requireCustomScalarTypes?: boolean; + /** + * Work in progress new Flow type definitions + */ + flowTypegen?: { + /** + * This option controls whether or not a catch-all entry is added to enum type definitions values that may be added + * in the future. Enabling this means you will have to update your application whenever the GraphQL server schema adds + * new enum values to prevent it from breaking. + * + * @default false + */ + noFutureProofEnums?: boolean; + }; + /** + * This option enables emitting ES modules artifacts. + * + * @default false + */ + eagerEsModules?: boolean; +} + +export type RelayConfigMultiProjectItem = + RelayConfigMultiProjectItemSchemaConfig & RelayConfigMultiProjectItemTypegenConfig & { + /** + * The name of the base project. If a base project is set, the documents of that project can be referenced, + * but won't produce output artifacts. Extensions from the base project will be added as well and the schema + * of the base project should be a subset of the schema of this project. + */ + base?: string; + /** + * The output directory for all our generated artifactories from the compiler. A project without an output directory will put + * the generated files in a `__generated__` directory next to the input file. All files in these directories should be generated + * by the Relay compiler, so that the compiler can cleanup extra files. + */ + output?: string; + /** + * Some projects may need to generate extra artifacts. For those, we may need to provide an additional directory to put them. + * By default they will use `output`. + */ + extraArtifactsOutput?: string; + /** + * If `output` is provided and `shard_output` is `true`, shard the files by putting them under `{output_dir}/{source_relative_path}` + * + * @default false + */ + shardOutput?: boolean; + /** + * Regex to match and strip parts of the `source_relative_path` + */ + shardStripRegex?: string; + /** + * Array of directories containing *.graphql files with schema extensions. + * + * @default [] + */ + schemaExtensions?: string[]; + /** If this option is set, the compiler will persist queries using this config. */ + persist?: RelayConfigPersitConfigLocal; + /** + * Restrict @relay_test_operation to directories matching this regex + */ + testPathRegex?: string; + /** Generates a `// @relayVariables name1 name2` header in generated operation files. */ + variableNamesComment?: boolean; + featureFlags?: RelayConfigFeatureFlags; + /** A placeholder for allowing extra information in the config file */ + extra?: unknown; + /** + * A generic rollout state for larger codegen changes. The default is to + * pass, otherwise it should be a number between 0 and 100 as a percentage. + */ + rollout?: number; + /** + * Formatting style for generated files. + * + * @default "commonjs" + */ + jsModuleFormat?: 'commonjs' | 'haste'; + /** Extra config for the schema itself. */ + schemaConfig?: RelayConfigSchemaConfig; + /** Configuration for `@module`. */ + moduleImportConfig?: { + /** + * Defines the custom import statement to be generated on the + * `ModuleImport` node in ASTs, used for dynamically loading + * components at runtime. + */ + dynamicModuleProvider: RelayConfigMultiProjectItemDynamicModuleProvider; + }; + /** + * Options for configuring the output of compiler diagnostics. + * + * @default + * ```js + * { + * criticalLevel: "error", + * } + * ``` + */ + diagnosticReportConfig?: RelayConfigDiagnosticReportConfig; +} + +export type RelayConfigSchemaConfig = { + /** Configure the name of the globally unique ID field on the Node interface. Useful if you can't use the default id field name. */ + nodeInterfaceIdField?: string; + /** + * Specifies the name of the variable expected by the node query to pass the Node id. + * + * @default "id" + */ + nodeInterfaceIdVariableName?: string; + /** + * Restricts the type of all fields named `id` to `ID`. + * + * `allowedIdTypes` - Mappings from types in your schema to allowed types for their fields named `id`. + */ + nonNodeIdFields?: Record; +} + +export type RelayConfigPersist = RelayConfigPersitConfigRemote | RelayConfigPersitConfigLocal; + +export type RelayConfigPersitConfigRemote = { + /** String, URL to send a `POST` request to to persist. This field is required in `persistConfig`. */ + url: string; + /** The document will be in a `POST` parameter text. This map can contain additional parameters to send. */ + param: Record; + /** The maximum number concurrent requests that will be made to url. Use a value greater than 0. */ + concurrency: number; +} + +export type RelayConfigPersitConfigLocal = { + /** Path for the JSON file that will contain operations map. Compiler will write queries in the format: { "md5(queryText) => "queryText", ...}. */ + file: string; +} + +export type RelayConfigLanguage = 'javascript' | 'typescript' | 'flow'; + +export type RelayConfigCustomScalars = Record; + +export type RelayConfigDiagnosticReportConfig = { + /** + * The severity level of diagnostics that will cause the compiler to error out on. + * + * @default "error" + */ + criticalLevel: 'error' | 'warning' | 'info'; +}; + +type RelayConfigFeatureFlag = + | { kind: "disabled"; } + | { kind: "enabled"; } + | { + kind: "limited"; + allowlist: string[]; + } + | { + kind: "rollout"; + /** @minimum 0 + * @maximum 100 + */ + rollout: number; + }; + +export type RelayConfigFeatureFlags = { + /** + * Let users enable the Relay Resolvers. + * + * @see https://relay.dev/docs/guides/relay-resolvers/ + */ + enable_relay_resolver_transform?: boolean; + /** Enable deprecated `@outputType` on Relay Resolvers. */ + relay_resolver_enable_output_type?: RelayConfigFeatureFlag; + /** Enable returning interfaces from Relay Resolvers without `@outputType` */ + relay_resolver_enable_interface_output_type?: RelayConfigFeatureFlag; + /** + * For now, this also disallows fragments with variable definitions. + * This also makes `@module` to opt in using `@no_inline` internally + * + * **NOTE** that the presence of a fragment in this list only controls + * whether a fragment is *allowed* to use `@no_inline`: whether the fragment is + * inlined or not depends on whether it actually uses that directive. + */ + no_inline?: RelayConfigFeatureFlag; + enable_3d_branch_arg_generation?: boolean; + actor_change_support?: RelayConfigFeatureFlag; + text_artifacts?: RelayConfigFeatureFlag; + skip_printing_nulls?: RelayConfigFeatureFlag; + /** Enable support for the experimental `@alias` directive on fragment spreads. */ + enable_fragment_aliases?: RelayConfigFeatureFlag; + /** Print queries in compact form. */ + compact_query_text?: RelayConfigFeatureFlag; + /** Create normalization nodes for client edges to client objects. */ + emit_normalization_nodes_for_client_edges?: boolean; + /** Fully build the normalization AST for Resolvers. */ + enable_resolver_normalization_ast?: boolean; + /** Enforce strict flavors for relay resolvers and disallow mixing flavors. */ + relay_resolvers_enable_strict_resolver_flavors?: RelayConfigFeatureFlag; + /** Allow legacy verbose resolver syntax */ + relay_resolvers_allow_legacy_verbose_syntax?: RelayConfigFeatureFlag; + /** Allow relay resolvers to extend the Mutation type. */ + enable_relay_resolver_mutations?: boolean; + /** Perform strict validations when custom scalar types are used. */ + enable_strict_custom_scalars?: boolean; +} diff --git a/packages/relay-compiler/package.json b/packages/relay-compiler/package.json index b037e6234d47c..b854791efc1c2 100644 --- a/packages/relay-compiler/package.json +++ b/packages/relay-compiler/package.json @@ -15,5 +15,6 @@ "directory": "packages/relay-compiler" }, "main": "index.js", + "types": "./index.d.ts", "bin": "cli.js" } diff --git a/website/docs/getting-started/installation-and-setup.md b/website/docs/getting-started/installation-and-setup.md index 57a685e534981..93dc3afeca721 100644 --- a/website/docs/getting-started/installation-and-setup.md +++ b/website/docs/getting-started/installation-and-setup.md @@ -63,6 +63,7 @@ Create the configuration file: ```javascript // relay.config.js +/** @type {import('relay-compiler').RelayConfig} */ module.exports = { // ... // Configuration options accepted by the `relay-compiler` command-line tool and `babel-plugin-relay`. @@ -74,7 +75,7 @@ module.exports = { ``` This configuration also can be specified in `"relay"` section of the `package.json` file. -For more details, and configuration options see: [Relay Compiler Configuration](https://github.com/facebook/relay/tree/main/packages/relay-compiler) +For more details, and configuration options see: [Relay Compiler Configuration](https://github.com/facebook/relay/tree/main/packages/relay-compiler/index.d.ts) ## Set up babel-plugin-relay