Skip to content

Commit

Permalink
Use import type in typescript for all imports (#4029)
Browse files Browse the repository at this point in the history
Summary:
This makes the following change to typescript artifacts:

```diff
-import { ConcreteRequest, Query } from "relay-runtime";
+import type { ConcreteRequest, Query } from "relay-runtime";
 import type { FragmentRefs } from "relay-runtime";
```

Using the existing `useImportTypeSyntax` config.

As stated in the config, the `import type` syntax introduced in Typescript version 3.8 and prevents warnings from `importsNotUsedAsValues`. This setting also assists naive bundlers from taking a dependency on `relay-runtime`, when only the types are needed.

I kept this simple. Other paths for implementation would be
 - There's a mix of distinct typegen printers e.g. compiler/crates/relay-typegen/src/typescript.rs, and the inline use of conditionals on the language directly in compiler/crates/relay-compiler/src/artifact_content/content.rs. Consolidating these would allow sharing the existing `write_import_type` function
 - The imports could instead be consolidated and printed together, rather than potentially having multiple imports from the same file as it is now

Pull Request resolved: #4029

Test Plan:
Imported from GitHub, without a `Test Plan:` line.

Static Docs Site previews have moved into the custom phabricator field "Static Docs", and will no longer modify test plans after 5th October 2022.

Reviewed By: alunyov

Differential Revision: D38279030

Pulled By: alunyov

fbshipit-source-id: 1e252d2fe9041963a33d6dedecb4ac4b512628dd
  • Loading branch information
tomgasson authored and facebook-github-bot committed Sep 30, 2022
1 parent 1667b19 commit bcf7d6f
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 6 deletions.
23 changes: 17 additions & 6 deletions compiler/crates/relay-compiler/src/artifact_content/content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub fn generate_updatable_query(
}

write_import_type_from(
&project_config.typegen_config.language,
project_config,
&mut section,
generated_types.imported_types,
"relay-runtime",
Expand Down Expand Up @@ -260,7 +260,7 @@ pub fn generate_operation(
}

write_import_type_from(
&project_config.typegen_config.language,
project_config,
&mut section,
generated_types.imported_types,
"relay-runtime",
Expand Down Expand Up @@ -426,7 +426,7 @@ pub fn generate_split_operation(
writeln!(section, "/*::")?;
}
write_import_type_from(
&project_config.typegen_config.language,
project_config,
&mut section,
"NormalizationSplitOperation",
"relay-runtime",
Expand Down Expand Up @@ -600,7 +600,7 @@ fn generate_read_only_fragment(
}

write_import_type_from(
&project_config.typegen_config.language,
project_config,
&mut section,
generated_types.imported_types,
"relay-runtime",
Expand Down Expand Up @@ -790,15 +790,26 @@ fn generate_use_strict_section(language: &TypegenLanguage) -> Result<GenericSect
}

fn write_import_type_from(
language: &TypegenLanguage,
project_config: &ProjectConfig,
section: &mut dyn Write,
type_: &str,
from: &str,
) -> FmtResult {
let language = &project_config.typegen_config.language;
match language {
TypegenLanguage::JavaScript => Ok(()),
TypegenLanguage::Flow => writeln!(section, "import type {{ {} }} from '{}';", type_, from),
TypegenLanguage::TypeScript => writeln!(section, "import {{ {} }} from '{}';", type_, from),
TypegenLanguage::TypeScript => writeln!(
section,
"import {}{{ {} }} from '{}';",
if project_config.typegen_config.use_import_type_syntax {
"type "
} else {
""
},
type_,
from
),
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
==================================== INPUT ====================================
fragment LinkedField on User {
name
profilePicture {
uri
width
height
}
}
==================================== OUTPUT ===================================
import type { FragmentRefs } from "relay-runtime";
export type LinkedField$data = {
readonly name: string | null;
readonly profilePicture: {
readonly height: number | null;
readonly uri: string | null;
readonly width: number | null;
} | null;
readonly " $fragmentType": "LinkedField";
};
export type LinkedField$key = {
readonly " $data"?: LinkedField$data;
readonly " $fragmentSpreads": FragmentRefs<"LinkedField">;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fragment LinkedField on User {
name
profilePicture {
uri
width
height
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

use std::sync::Arc;

use common::ConsoleLogger;
use common::FeatureFlag;
use common::FeatureFlags;
use common::SourceLocationKey;
use fixture_tests::Fixture;
use fnv::FnvBuildHasher;
use fnv::FnvHashMap;
use graphql_ir::build;
use graphql_ir::Program;
use graphql_syntax::parse_executable;
use indexmap::IndexMap;
use intern::string_key::Intern;
use relay_codegen::JsModuleFormat;
use relay_config::CustomScalarType;
use relay_config::CustomScalarTypeImport;
use relay_config::ProjectConfig;
use relay_test_schema::get_test_schema;
use relay_test_schema::get_test_schema_with_extensions;
use relay_transforms::apply_transforms;
use relay_typegen::FragmentLocations;
use relay_typegen::TypegenConfig;
use relay_typegen::TypegenLanguage;
use relay_typegen::{self};

type FnvIndexMap<K, V> = IndexMap<K, V, FnvBuildHasher>;

pub fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String> {
let parts = fixture.content.split("%extensions%").collect::<Vec<_>>();
let (source, schema) = match parts.as_slice() {
[source, extensions] => (source, get_test_schema_with_extensions(extensions)),
[source] => (source, get_test_schema()),
_ => panic!(),
};

let source_location = SourceLocationKey::standalone(fixture.file_name);

let mut sources = FnvHashMap::default();
sources.insert(source_location, source);
let ast = parse_executable(source, source_location).unwrap_or_else(|e| {
panic!("Encountered error building AST: {:?}", e);
});
let ir = build(&schema, &ast.definitions).unwrap_or_else(|e| {
panic!("Encountered error building IR {:?}", e);
});
let program = Program::from_definitions(Arc::clone(&schema), ir);
let mut custom_scalar_types = FnvIndexMap::default();
custom_scalar_types.insert(
"JSON".intern(),
CustomScalarType::Path(CustomScalarTypeImport {
name: "JSON".intern(),
path: "TypeDefsFile".into(),
}),
);
let project_config = ProjectConfig {
name: "test".intern(),
js_module_format: JsModuleFormat::Haste,
typegen_config: TypegenConfig {
language: TypegenLanguage::TypeScript,
use_import_type_syntax: true,
custom_scalar_types,
..Default::default()
},
feature_flags: Arc::new(FeatureFlags {
enable_fragment_aliases: FeatureFlag::Enabled,
..Default::default()
}),
..Default::default()
};
let programs = apply_transforms(
&project_config,
Arc::new(program),
Default::default(),
Arc::new(ConsoleLogger),
None,
None,
)
.unwrap();

let fragment_locations = FragmentLocations::new(programs.typegen.fragments());
let mut operations: Vec<_> = programs.typegen.operations().collect();
operations.sort_by_key(|op| op.name.item);
let operation_strings = operations.into_iter().map(|typegen_operation| {
let normalization_operation = programs
.normalization
.operation(typegen_operation.name.item)
.unwrap();
relay_typegen::generate_operation_type_exports_section(
typegen_operation,
normalization_operation,
&schema,
&project_config,
&fragment_locations,
)
});

let mut fragments: Vec<_> = programs.typegen.fragments().collect();
fragments.sort_by_key(|frag| frag.name.item);
let fragment_strings = fragments.into_iter().map(|frag| {
relay_typegen::generate_fragment_type_exports_section(
frag,
&schema,
&project_config,
&fragment_locations,
)
});

let mut result: Vec<String> = operation_strings.collect();
result.extend(fragment_strings);
Ok(result
.join("-------------------------------------------------------------------------------\n"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<fbb84200234cfe7d4293dd0c63574aab>>
*/

mod generate_typescript_import_syntax;

use generate_typescript_import_syntax::transform_fixture;
use fixture_tests::test_fixture;

#[test]
fn simple() {
let input = include_str!("generate_typescript_import_syntax/fixtures/simple.graphql");
let expected = include_str!("generate_typescript_import_syntax/fixtures/simple.expected");
test_fixture(transform_fixture, "simple.graphql", "generate_typescript_import_syntax/fixtures/simple.expected", input, expected);
}

0 comments on commit bcf7d6f

Please sign in to comment.