Relay Support in Rust Compiler (#33702)
Reverts vercel/next.js#33699 This re-opens the support for relay in swc, although we need to narrow in the causes for the build failures in https://github.com/vercel/next.js/runs/4950448889?check_suite_focus=true Co-authored-by: Andrey Lunyov <102968+alunyov@users.noreply.github.com>
This commit is contained in:
parent
af0d082c49
commit
3e60c232a8
35 changed files with 1049 additions and 5 deletions
|
@ -94,6 +94,26 @@ const customJestConfig = {
|
|||
module.exports = createJestConfig(customJestConfig)
|
||||
```
|
||||
|
||||
### Relay
|
||||
|
||||
To enable [Relay](https://relay.dev/) support:
|
||||
|
||||
```js
|
||||
// next.config.js
|
||||
module.exports = {
|
||||
experimental: {
|
||||
relay: {
|
||||
// This should match relay.config.js
|
||||
src: './',
|
||||
artifactDirectory: './__generated__'
|
||||
language: 'typescript',
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
NOTE: In Next.js all JavaScripts files in `pages` directory are considered routes. So, for `relay-compiler` you'll need to specify `artifactDirectory` configuration settings outside of the `pages`, otherwise `relay-compiler` will generate files next to the source file in the `__generated__` directory, and this file will be considered a route, which will break production build.
|
||||
|
||||
### Remove React Properties
|
||||
|
||||
Allows to remove JSX properties. This is often used for testing. Similar to `babel-plugin-react-remove-properties`.
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
"@types/http-proxy": "1.17.3",
|
||||
"@types/jest": "24.0.13",
|
||||
"@types/node": "13.11.0",
|
||||
"@types/relay-runtime": "13.0.0",
|
||||
"@types/selenium-webdriver": "4.0.15",
|
||||
"@types/sharp": "0.29.3",
|
||||
"@types/string-hash": "1.1.1",
|
||||
|
@ -147,6 +148,8 @@
|
|||
"react-dom": "17.0.2",
|
||||
"react-dom-18": "npm:react-dom@18.0.0-rc.0",
|
||||
"react-ssr-prepass": "1.0.8",
|
||||
"relay-compiler": "13.0.2",
|
||||
"relay-runtime": "13.0.2",
|
||||
"react-virtualized": "9.22.3",
|
||||
"release": "6.3.0",
|
||||
"request-promise-core": "1.1.2",
|
||||
|
|
1
packages/next-swc/Cargo.lock
generated
1
packages/next-swc/Cargo.lock
generated
|
@ -800,6 +800,7 @@ dependencies = [
|
|||
"easy-error",
|
||||
"either",
|
||||
"fxhash",
|
||||
"once_cell",
|
||||
"pathdiff",
|
||||
"regex",
|
||||
"serde",
|
||||
|
|
|
@ -8,6 +8,7 @@ crate-type = ["cdylib", "rlib"]
|
|||
|
||||
[dependencies]
|
||||
chrono = "0.4"
|
||||
once_cell = "1.8.0"
|
||||
easy-error = "1.0.0"
|
||||
either = "1"
|
||||
fxhash = "0.2.1"
|
||||
|
@ -30,5 +31,3 @@ regex = "1.5"
|
|||
swc_ecma_transforms_testing = "0.59.0"
|
||||
testing = "0.18.0"
|
||||
walkdir = "2.3.2"
|
||||
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ pub mod next_dynamic;
|
|||
pub mod next_ssg;
|
||||
pub mod page_config;
|
||||
pub mod react_remove_properties;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod relay;
|
||||
pub mod remove_console;
|
||||
pub mod shake_exports;
|
||||
pub mod styled_jsx;
|
||||
|
@ -91,6 +93,10 @@ pub struct TransformOptions {
|
|||
#[serde(default)]
|
||||
pub react_remove_properties: Option<react_remove_properties::Config>,
|
||||
|
||||
#[serde(default)]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub relay: Option<relay::Config>,
|
||||
|
||||
#[serde(default)]
|
||||
pub shake_exports: Option<shake_exports::Config>,
|
||||
}
|
||||
|
@ -99,7 +105,19 @@ pub fn custom_before_pass(
|
|||
cm: Arc<SourceMap>,
|
||||
file: Arc<SourceFile>,
|
||||
opts: &TransformOptions,
|
||||
) -> impl Fold {
|
||||
) -> impl Fold + '_ {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let relay_plugin = noop();
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let relay_plugin = {
|
||||
if let Some(config) = &opts.relay {
|
||||
Either::Left(relay::relay(config, file.name.clone()))
|
||||
} else {
|
||||
Either::Right(noop())
|
||||
}
|
||||
};
|
||||
|
||||
chain!(
|
||||
disallow_re_export_all_in_page::disallow_re_export_all_in_page(opts.is_page_file),
|
||||
styled_jsx::styled_jsx(cm.clone()),
|
||||
|
@ -130,6 +148,7 @@ pub fn custom_before_pass(
|
|||
page_config::page_config(opts.is_development, opts.is_page_file),
|
||||
!opts.disable_page_config
|
||||
),
|
||||
relay_plugin,
|
||||
match &opts.remove_console {
|
||||
Some(config) if config.truthy() =>
|
||||
Either::Left(remove_console::remove_console(config.clone())),
|
||||
|
|
170
packages/next-swc/crates/core/src/relay.rs
Normal file
170
packages/next-swc/crates/core/src/relay.rs
Normal file
|
@ -0,0 +1,170 @@
|
|||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use serde::Deserialize;
|
||||
use std::path::{Path, PathBuf};
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::errors::HANDLER;
|
||||
use swc_common::FileName;
|
||||
use swc_ecmascript::ast::*;
|
||||
use swc_ecmascript::utils::{quote_ident, ExprFactory};
|
||||
use swc_ecmascript::visit::{Fold, FoldWith};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum RelayLanguageConfig {
|
||||
TypeScript,
|
||||
Flow,
|
||||
}
|
||||
|
||||
impl Default for RelayLanguageConfig {
|
||||
fn default() -> Self {
|
||||
Self::Flow
|
||||
}
|
||||
}
|
||||
|
||||
struct Relay<'a> {
|
||||
root_dir: PathBuf,
|
||||
file_name: FileName,
|
||||
config: &'a Config,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Default, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Config {
|
||||
pub src: PathBuf,
|
||||
pub artifact_directory: Option<PathBuf>,
|
||||
#[serde(default)]
|
||||
pub language: RelayLanguageConfig,
|
||||
}
|
||||
|
||||
fn pull_first_operation_name_from_tpl(tpl: &TaggedTpl) -> Option<String> {
|
||||
tpl.tpl.quasis.iter().find_map(|quasis| {
|
||||
static OPERATION_REGEX: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(r"(fragment|mutation|query|subscription) (\w+)").unwrap());
|
||||
|
||||
let capture_group = OPERATION_REGEX.captures_iter(&quasis.raw.value).next();
|
||||
|
||||
capture_group.map(|capture_group| capture_group[2].to_string())
|
||||
})
|
||||
}
|
||||
|
||||
fn build_require_expr_from_path(path: &str) -> Expr {
|
||||
Expr::Call(CallExpr {
|
||||
span: Default::default(),
|
||||
callee: quote_ident!("require").as_callee(),
|
||||
args: vec![
|
||||
Lit::Str(Str {
|
||||
span: Default::default(),
|
||||
value: JsWord::from(path),
|
||||
has_escape: false,
|
||||
kind: Default::default(),
|
||||
})
|
||||
.as_arg(),
|
||||
],
|
||||
type_args: None,
|
||||
})
|
||||
}
|
||||
|
||||
impl<'a> Fold for Relay<'a> {
|
||||
fn fold_expr(&mut self, expr: Expr) -> Expr {
|
||||
let expr = expr.fold_children_with(self);
|
||||
|
||||
match &expr {
|
||||
Expr::TaggedTpl(tpl) => {
|
||||
if let Some(built_expr) = self.build_call_expr_from_tpl(tpl) {
|
||||
built_expr
|
||||
} else {
|
||||
expr
|
||||
}
|
||||
}
|
||||
_ => expr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum BuildRequirePathError {
|
||||
FileNameNotReal,
|
||||
ArtifactDirectoryExpected,
|
||||
}
|
||||
|
||||
fn path_for_artifact(
|
||||
root_dir: &Path,
|
||||
config: &Config,
|
||||
definition_name: &str,
|
||||
) -> Result<PathBuf, BuildRequirePathError> {
|
||||
let filename = match &config.language {
|
||||
RelayLanguageConfig::Flow => format!("{}.graphql.js", definition_name),
|
||||
RelayLanguageConfig::TypeScript => {
|
||||
format!("{}.graphql.ts", definition_name)
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(artifact_directory) = &config.artifact_directory {
|
||||
Ok(root_dir.join(artifact_directory).join(filename))
|
||||
} else {
|
||||
Err(BuildRequirePathError::ArtifactDirectoryExpected)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Relay<'a> {
|
||||
fn build_require_path(
|
||||
&mut self,
|
||||
operation_name: &str,
|
||||
) -> Result<PathBuf, BuildRequirePathError> {
|
||||
match &self.file_name {
|
||||
FileName::Real(_real_file_name) => {
|
||||
path_for_artifact(&self.root_dir, self.config, operation_name)
|
||||
}
|
||||
_ => Err(BuildRequirePathError::FileNameNotReal),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_call_expr_from_tpl(&mut self, tpl: &TaggedTpl) -> Option<Expr> {
|
||||
if let Expr::Ident(ident) = &*tpl.tag {
|
||||
if &*ident.sym != "graphql" {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let operation_name = pull_first_operation_name_from_tpl(tpl);
|
||||
|
||||
match operation_name {
|
||||
None => None,
|
||||
Some(operation_name) => match self.build_require_path(operation_name.as_str()) {
|
||||
Ok(final_path) => Some(build_require_expr_from_path(final_path.to_str().unwrap())),
|
||||
Err(err) => {
|
||||
let base_error = "Could not transform GraphQL template to a Relay import.";
|
||||
let error_message = match err {
|
||||
BuildRequirePathError::FileNameNotReal => "Source file was not a real \
|
||||
file. This is likely a bug and \
|
||||
should be reported to Next.js"
|
||||
.to_string(),
|
||||
BuildRequirePathError::ArtifactDirectoryExpected => {
|
||||
"The `artifactDirectory` is expected to be set in the Relay config \
|
||||
file to work correctly with Next.js."
|
||||
.to_string()
|
||||
}
|
||||
};
|
||||
|
||||
HANDLER.with(|handler| {
|
||||
handler.span_err(
|
||||
tpl.span,
|
||||
format!("{} {}", base_error, error_message).as_str(),
|
||||
);
|
||||
});
|
||||
|
||||
None
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn relay<'a>(config: &'a Config, file_name: FileName) -> impl Fold + '_ {
|
||||
Relay {
|
||||
root_dir: std::env::current_dir().unwrap(),
|
||||
file_name,
|
||||
config,
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ use next_swc::{
|
|||
next_ssg::next_ssg,
|
||||
page_config::page_config_test,
|
||||
react_remove_properties::remove_properties,
|
||||
relay::{relay, Config as RelayConfig, RelayLanguageConfig},
|
||||
remove_console::remove_console,
|
||||
shake_exports::{shake_exports, Config as ShakeExportsConfig},
|
||||
styled_jsx::styled_jsx,
|
||||
|
@ -149,6 +150,22 @@ fn page_config_fixture(input: PathBuf) {
|
|||
test_fixture(syntax(), &|_tr| page_config_test(), &input, &output);
|
||||
}
|
||||
|
||||
#[fixture("tests/fixture/relay/**/input.ts*")]
|
||||
fn relay_no_artifact_dir_fixture(input: PathBuf) {
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
let config = RelayConfig {
|
||||
language: RelayLanguageConfig::TypeScript,
|
||||
artifact_directory: Some(PathBuf::from("__generated__")),
|
||||
..Default::default()
|
||||
};
|
||||
test_fixture(
|
||||
syntax(),
|
||||
&|_tr| relay(&config, FileName::Real(PathBuf::from("input.tsx"))),
|
||||
&input,
|
||||
&output,
|
||||
);
|
||||
}
|
||||
|
||||
#[fixture("tests/fixture/remove-console/**/input.js")]
|
||||
fn remove_console_fixture(input: PathBuf) {
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
|
|
42
packages/next-swc/crates/core/tests/fixture/relay/input.tsx
Normal file
42
packages/next-swc/crates/core/tests/fixture/relay/input.tsx
Normal file
|
@ -0,0 +1,42 @@
|
|||
const variableQuery = graphql`
|
||||
query InputVariableQuery {
|
||||
hello
|
||||
}
|
||||
`
|
||||
|
||||
fetchQuery(graphql`
|
||||
query InputUsedInFunctionCallQuery {
|
||||
hello
|
||||
}
|
||||
`)
|
||||
|
||||
function SomeQueryComponent() {
|
||||
useLazyLoadQuery(graphql`
|
||||
query InputInHookQuery {
|
||||
hello
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
const variableMutation = graphql`
|
||||
query InputVariableMutation {
|
||||
someMutation
|
||||
}
|
||||
`
|
||||
|
||||
commitMutation(
|
||||
environment,
|
||||
graphql`
|
||||
query InputUsedInFunctionCallMutation {
|
||||
someMutation
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
function SomeMutationComponent() {
|
||||
useMutation(graphql`
|
||||
query InputInHookMutation {
|
||||
someMutation
|
||||
}
|
||||
`)
|
||||
}
|
10
packages/next-swc/crates/core/tests/fixture/relay/output.js
Normal file
10
packages/next-swc/crates/core/tests/fixture/relay/output.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
const variableQuery = require("$DIR/__generated__/InputVariableQuery.graphql.ts");
|
||||
fetchQuery(require("$DIR/__generated__/InputUsedInFunctionCallQuery.graphql.ts"));
|
||||
function SomeQueryComponent() {
|
||||
useLazyLoadQuery(require("$DIR/__generated__/InputInHookQuery.graphql.ts"));
|
||||
}
|
||||
const variableMutation = require("$DIR/__generated__/InputVariableMutation.graphql.ts");
|
||||
commitMutation(environment, require("$DIR/__generated__/InputUsedInFunctionCallMutation.graphql.ts"));
|
||||
function SomeMutationComponent() {
|
||||
useMutation(require("$DIR/__generated__/InputInHookMutation.graphql.ts"));
|
||||
}
|
|
@ -59,6 +59,7 @@ fn test(input: &Path, minify: bool) {
|
|||
styled_components: Some(assert_json("{}")),
|
||||
remove_console: None,
|
||||
react_remove_properties: None,
|
||||
relay: None,
|
||||
shake_exports: None,
|
||||
};
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ export function getBaseSWCOptions({
|
|||
: null,
|
||||
removeConsole: nextConfig?.experimental?.removeConsole,
|
||||
reactRemoveProperties: nextConfig?.experimental?.reactRemoveProperties,
|
||||
relay: nextConfig?.experimental?.relay,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1621,6 +1621,7 @@ export default async function getBaseWebpackConfig(
|
|||
removeConsole: config.experimental.removeConsole,
|
||||
reactRemoveProperties: config.experimental.reactRemoveProperties,
|
||||
styledComponents: config.experimental.styledComponents,
|
||||
relay: config.experimental.relay,
|
||||
})
|
||||
|
||||
const cache: any = {
|
||||
|
|
|
@ -172,6 +172,11 @@ export type NextConfig = { [key: string]: any } & {
|
|||
urlImports?: NonNullable<webpack5.Configuration['experiments']>['buildHttp']
|
||||
outputFileTracingRoot?: string
|
||||
outputStandalone?: boolean
|
||||
relay?: {
|
||||
src: string
|
||||
artifactDirectory?: string
|
||||
language?: 'typescript' | 'flow'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
63
test/integration/relay-graphql-swc-multi-project/project-a/__generated__/pagesAQuery.graphql.ts
generated
Normal file
63
test/integration/relay-graphql-swc-multi-project/project-a/__generated__/pagesAQuery.graphql.ts
generated
Normal file
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* @generated SignedSource<<afaeba3a661c4bb0d2a399327c82d32b>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest, Query } from 'relay-runtime'
|
||||
export type pagesAQuery$variables = {}
|
||||
export type pagesAQueryVariables = pagesAQuery$variables
|
||||
export type pagesAQuery$data = {
|
||||
readonly greeting: string
|
||||
}
|
||||
export type pagesAQueryResponse = pagesAQuery$data
|
||||
export type pagesAQuery = {
|
||||
variables: pagesAQueryVariables
|
||||
response: pagesAQuery$data
|
||||
}
|
||||
|
||||
const node: ConcreteRequest = (function () {
|
||||
var v0 = [
|
||||
{
|
||||
alias: null,
|
||||
args: null,
|
||||
kind: 'ScalarField',
|
||||
name: 'greeting',
|
||||
storageKey: null,
|
||||
},
|
||||
]
|
||||
return {
|
||||
fragment: {
|
||||
argumentDefinitions: [],
|
||||
kind: 'Fragment',
|
||||
metadata: null,
|
||||
name: 'pagesAQuery',
|
||||
selections: v0 /*: any*/,
|
||||
type: 'Query',
|
||||
abstractKey: null,
|
||||
},
|
||||
kind: 'Request',
|
||||
operation: {
|
||||
argumentDefinitions: [],
|
||||
kind: 'Operation',
|
||||
name: 'pagesAQuery',
|
||||
selections: v0 /*: any*/,
|
||||
},
|
||||
params: {
|
||||
cacheID: 'bc59dc1b50eecd19488f004d5cd93913',
|
||||
id: null,
|
||||
metadata: {},
|
||||
name: 'pagesAQuery',
|
||||
operationKind: 'query',
|
||||
text: 'query pagesAQuery {\n greeting\n}\n',
|
||||
},
|
||||
}
|
||||
})()
|
||||
|
||||
;(node as any).hash = '7f699085b71746bb18cb74e3a0776f46'
|
||||
|
||||
export default node
|
|
@ -0,0 +1,12 @@
|
|||
const relay = require('../relay.config')
|
||||
|
||||
module.exports = {
|
||||
experimental: {
|
||||
relay: {
|
||||
src: './pages',
|
||||
artifactDirectory: './__generated__',
|
||||
language: relay.projects['project-b'].language,
|
||||
},
|
||||
externalDir: true,
|
||||
},
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<{ data: { greeting: string } }>
|
||||
) {
|
||||
res.status(200).json({
|
||||
data: {
|
||||
greeting: 'Hello, World!',
|
||||
},
|
||||
})
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
import {
|
||||
Environment,
|
||||
FetchFunction,
|
||||
fetchQuery,
|
||||
graphql,
|
||||
Network,
|
||||
RecordSource,
|
||||
Store,
|
||||
} from 'relay-runtime'
|
||||
import { GetServerSideProps } from 'next'
|
||||
import { pagesAQuery } from '../__generated__/pagesAQuery.graphql'
|
||||
|
||||
type Props = { greeting: string }
|
||||
|
||||
export default function Index({ greeting }: Props) {
|
||||
return <p>Project A:{greeting}</p>
|
||||
}
|
||||
|
||||
function createGraphQLFetcher(host: string | undefined): FetchFunction {
|
||||
return async function fetchGraphQL(params, variables) {
|
||||
const url = host ? `http://${host}/api/query` : `/api/query`
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: params.text,
|
||||
variables,
|
||||
}),
|
||||
})
|
||||
|
||||
return await response.json()
|
||||
}
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async ({ req }) => {
|
||||
const environment = new Environment({
|
||||
store: new Store(new RecordSource({}), {}),
|
||||
network: Network.create(createGraphQLFetcher(req.headers.host)),
|
||||
})
|
||||
|
||||
const result = await fetchQuery<pagesAQuery>(
|
||||
environment,
|
||||
graphql`
|
||||
query pagesAQuery {
|
||||
greeting
|
||||
}
|
||||
`,
|
||||
{}
|
||||
).toPromise()
|
||||
|
||||
if (!result) {
|
||||
throw new Error(
|
||||
'Mock GraphQL Server network request finished without a response!'
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
props: { greeting: result.greeting },
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"jsx": "preserve",
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"incremental": true,
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
}
|
63
test/integration/relay-graphql-swc-multi-project/project-b/__generated__/pagesBQuery.graphql.ts
generated
Normal file
63
test/integration/relay-graphql-swc-multi-project/project-b/__generated__/pagesBQuery.graphql.ts
generated
Normal file
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* @generated SignedSource<<9f92ea3ccfda1f64fa269e68b912abae>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest, Query } from 'relay-runtime'
|
||||
export type pagesBQuery$variables = {}
|
||||
export type pagesBQueryVariables = pagesBQuery$variables
|
||||
export type pagesBQuery$data = {
|
||||
readonly greeting: string
|
||||
}
|
||||
export type pagesBQueryResponse = pagesBQuery$data
|
||||
export type pagesBQuery = {
|
||||
variables: pagesBQueryVariables
|
||||
response: pagesBQuery$data
|
||||
}
|
||||
|
||||
const node: ConcreteRequest = (function () {
|
||||
var v0 = [
|
||||
{
|
||||
alias: null,
|
||||
args: null,
|
||||
kind: 'ScalarField',
|
||||
name: 'greeting',
|
||||
storageKey: null,
|
||||
},
|
||||
]
|
||||
return {
|
||||
fragment: {
|
||||
argumentDefinitions: [],
|
||||
kind: 'Fragment',
|
||||
metadata: null,
|
||||
name: 'pagesBQuery',
|
||||
selections: v0 /*: any*/,
|
||||
type: 'Query',
|
||||
abstractKey: null,
|
||||
},
|
||||
kind: 'Request',
|
||||
operation: {
|
||||
argumentDefinitions: [],
|
||||
kind: 'Operation',
|
||||
name: 'pagesBQuery',
|
||||
selections: v0 /*: any*/,
|
||||
},
|
||||
params: {
|
||||
cacheID: 'e7cc6f8c55ef42783faec7a49b72ae71',
|
||||
id: null,
|
||||
metadata: {},
|
||||
name: 'pagesBQuery',
|
||||
operationKind: 'query',
|
||||
text: 'query pagesBQuery {\n greeting\n}\n',
|
||||
},
|
||||
}
|
||||
})()
|
||||
|
||||
;(node as any).hash = '83bf9452eafa7635d81bdc98603cd75f'
|
||||
|
||||
export default node
|
|
@ -0,0 +1,12 @@
|
|||
const relay = require('../relay.config')
|
||||
|
||||
module.exports = {
|
||||
experimental: {
|
||||
relay: {
|
||||
src: './pages',
|
||||
artifactDirectory: './__generated__',
|
||||
language: relay.projects['project-b'].language,
|
||||
},
|
||||
externalDir: true,
|
||||
},
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<{ data: { greeting: string } }>
|
||||
) {
|
||||
res.status(200).json({
|
||||
data: {
|
||||
greeting: 'Hello, World!',
|
||||
},
|
||||
})
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
import {
|
||||
Environment,
|
||||
FetchFunction,
|
||||
fetchQuery,
|
||||
graphql,
|
||||
Network,
|
||||
RecordSource,
|
||||
Store,
|
||||
} from 'relay-runtime'
|
||||
import { GetServerSideProps } from 'next'
|
||||
import { pagesBQuery } from '../__generated__/pagesBQuery.graphql'
|
||||
|
||||
type Props = { greeting: string }
|
||||
|
||||
export default function Index({ greeting }: Props) {
|
||||
return <p>Project B:{greeting}</p>
|
||||
}
|
||||
|
||||
function createGraphQLFetcher(host: string | undefined): FetchFunction {
|
||||
return async function fetchGraphQL(params, variables) {
|
||||
const url = host ? `http://${host}/api/query` : `/api/query`
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: params.text,
|
||||
variables,
|
||||
}),
|
||||
})
|
||||
|
||||
return await response.json()
|
||||
}
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async ({ req }) => {
|
||||
const environment = new Environment({
|
||||
store: new Store(new RecordSource({}), {}),
|
||||
network: Network.create(createGraphQLFetcher(req.headers.host)),
|
||||
})
|
||||
|
||||
const result = await fetchQuery<pagesBQuery>(
|
||||
environment,
|
||||
graphql`
|
||||
query pagesBQuery {
|
||||
greeting
|
||||
}
|
||||
`,
|
||||
{}
|
||||
).toPromise()
|
||||
|
||||
if (!result) {
|
||||
throw new Error(
|
||||
'Mock GraphQL Server network request finished without a response!'
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
props: { greeting: result.greeting },
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"jsx": "preserve",
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"incremental": true,
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
module.exports = {
|
||||
root: './',
|
||||
sources: {
|
||||
'project-a/pages': 'project-a',
|
||||
'project-b/pages': 'project-b',
|
||||
},
|
||||
projects: {
|
||||
'project-a': {
|
||||
schema: 'schema.graphql',
|
||||
language: 'typescript',
|
||||
output: 'project-a/__generated__',
|
||||
},
|
||||
'project-b': {
|
||||
schema: 'schema.graphql',
|
||||
language: 'typescript',
|
||||
output: 'project-b/__generated__',
|
||||
},
|
||||
},
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
type Query {
|
||||
greeting: String!
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/* eslint-env jest */
|
||||
import { join } from 'path'
|
||||
import { execSync } from 'child_process'
|
||||
import {
|
||||
findPort,
|
||||
killApp,
|
||||
launchApp,
|
||||
nextBuild,
|
||||
nextStart,
|
||||
renderViaHTTP,
|
||||
} from 'next-test-utils'
|
||||
|
||||
let app
|
||||
let appPort
|
||||
const projectAAppDir = join(__dirname, '../project-a')
|
||||
const projectBAppDir = join(__dirname, '../project-b')
|
||||
|
||||
const runTests = (project) => {
|
||||
it('should resolve index page correctly', async () => {
|
||||
const html = await renderViaHTTP(appPort, '/')
|
||||
expect(html).toContain(project)
|
||||
expect(html).toContain(`Hello, World!`)
|
||||
})
|
||||
}
|
||||
|
||||
const runRelayCompiler = () => {
|
||||
// Relay expects the current directory to contain a relay.json
|
||||
// This ensures the CWD is the one with relay.json since running
|
||||
// the relay-compiler through yarn would make the root of the repo the CWD.
|
||||
execSync('../../../node_modules/relay-compiler/cli.js', {
|
||||
cwd: './test/integration/relay-graphql-swc-multi-project',
|
||||
})
|
||||
}
|
||||
|
||||
describe('Relay Compiler Transform - Multi Project Config', () => {
|
||||
beforeAll(() => {
|
||||
runRelayCompiler()
|
||||
})
|
||||
|
||||
describe('dev mode', () => {
|
||||
describe('project-a', () => {
|
||||
beforeAll(async () => {
|
||||
appPort = await findPort()
|
||||
app = await launchApp(projectAAppDir, appPort, { cwd: projectAAppDir })
|
||||
})
|
||||
|
||||
afterAll(() => killApp(app))
|
||||
|
||||
runTests('Project A')
|
||||
})
|
||||
|
||||
describe('project-b', () => {
|
||||
beforeAll(async () => {
|
||||
appPort = await findPort()
|
||||
app = await launchApp(projectBAppDir, appPort, { cwd: projectBAppDir })
|
||||
})
|
||||
|
||||
afterAll(() => killApp(app))
|
||||
|
||||
runTests('Project B')
|
||||
})
|
||||
})
|
||||
|
||||
describe('production mode', () => {
|
||||
describe('project-a', () => {
|
||||
beforeAll(async () => {
|
||||
await nextBuild(projectAAppDir, [], { cwd: projectAAppDir })
|
||||
appPort = await findPort()
|
||||
app = await nextStart(projectAAppDir, appPort)
|
||||
})
|
||||
|
||||
afterAll(() => killApp(app))
|
||||
|
||||
runTests('Project A')
|
||||
})
|
||||
|
||||
describe('project-b', () => {
|
||||
beforeAll(async () => {
|
||||
await nextBuild(projectBAppDir, [], { cwd: projectBAppDir })
|
||||
appPort = await findPort()
|
||||
app = await nextStart(projectBAppDir, appPort)
|
||||
})
|
||||
|
||||
afterAll(() => killApp(app))
|
||||
|
||||
runTests('Project B')
|
||||
})
|
||||
})
|
||||
})
|
63
test/integration/relay-graphql-swc-single-project/__generated__/pagesQuery.graphql.ts
generated
Normal file
63
test/integration/relay-graphql-swc-single-project/__generated__/pagesQuery.graphql.ts
generated
Normal file
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* @generated SignedSource<<187ead9fb6e7b26d71c9161bda6ab902>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest, Query } from 'relay-runtime'
|
||||
export type pagesQuery$variables = {}
|
||||
export type pagesQueryVariables = pagesQuery$variables
|
||||
export type pagesQuery$data = {
|
||||
readonly greeting: string
|
||||
}
|
||||
export type pagesQueryResponse = pagesQuery$data
|
||||
export type pagesQuery = {
|
||||
variables: pagesQueryVariables
|
||||
response: pagesQuery$data
|
||||
}
|
||||
|
||||
const node: ConcreteRequest = (function () {
|
||||
var v0 = [
|
||||
{
|
||||
alias: null,
|
||||
args: null,
|
||||
kind: 'ScalarField',
|
||||
name: 'greeting',
|
||||
storageKey: null,
|
||||
},
|
||||
]
|
||||
return {
|
||||
fragment: {
|
||||
argumentDefinitions: [],
|
||||
kind: 'Fragment',
|
||||
metadata: null,
|
||||
name: 'pagesQuery',
|
||||
selections: v0 /*: any*/,
|
||||
type: 'Query',
|
||||
abstractKey: null,
|
||||
},
|
||||
kind: 'Request',
|
||||
operation: {
|
||||
argumentDefinitions: [],
|
||||
kind: 'Operation',
|
||||
name: 'pagesQuery',
|
||||
selections: v0 /*: any*/,
|
||||
},
|
||||
params: {
|
||||
cacheID: '167b6de16340efeb876a7787c90e7cec',
|
||||
id: null,
|
||||
metadata: {},
|
||||
name: 'pagesQuery',
|
||||
operationKind: 'query',
|
||||
text: 'query pagesQuery {\n greeting\n}\n',
|
||||
},
|
||||
}
|
||||
})()
|
||||
|
||||
;(node as any).hash = '4017856344f36f61252354e2eb442d98'
|
||||
|
||||
export default node
|
|
@ -0,0 +1,7 @@
|
|||
const relay = require('./relay.config')
|
||||
|
||||
module.exports = {
|
||||
experimental: {
|
||||
relay,
|
||||
},
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<{ data: { greeting: string } }>
|
||||
) {
|
||||
res.status(200).json({
|
||||
data: {
|
||||
greeting: 'Hello, World!',
|
||||
},
|
||||
})
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
import {
|
||||
Environment,
|
||||
FetchFunction,
|
||||
fetchQuery,
|
||||
graphql,
|
||||
Network,
|
||||
RecordSource,
|
||||
Store,
|
||||
} from 'relay-runtime'
|
||||
import { GetServerSideProps } from 'next'
|
||||
import { pagesQuery } from '../__generated__/pagesQuery.graphql'
|
||||
|
||||
type Props = { greeting: string }
|
||||
|
||||
export default function Index({ greeting }: Props) {
|
||||
return <p>{greeting}</p>
|
||||
}
|
||||
|
||||
function createGraphQLFetcher(host: string | undefined): FetchFunction {
|
||||
return async function fetchGraphQL(params, variables) {
|
||||
const url = host ? `http://${host}/api/query` : `/api/query`
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: params.text,
|
||||
variables,
|
||||
}),
|
||||
})
|
||||
|
||||
return await response.json()
|
||||
}
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async ({ req }) => {
|
||||
const environment = new Environment({
|
||||
store: new Store(new RecordSource({}), {}),
|
||||
network: Network.create(createGraphQLFetcher(req.headers.host)),
|
||||
})
|
||||
|
||||
const result = await fetchQuery<pagesQuery>(
|
||||
environment,
|
||||
graphql`
|
||||
query pagesQuery {
|
||||
greeting
|
||||
}
|
||||
`,
|
||||
{}
|
||||
).toPromise()
|
||||
|
||||
if (!result) {
|
||||
throw new Error(
|
||||
'Mock GraphQL Server network request finished without a response!'
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
props: { greeting: result.greeting },
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
src: './pages',
|
||||
schema: './schema.graphql',
|
||||
artifactDirectory: './__generated__',
|
||||
language: 'typescript',
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
type Query {
|
||||
greeting: String!
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* eslint-env jest */
|
||||
import { join } from 'path'
|
||||
import { execSync } from 'child_process'
|
||||
import {
|
||||
findPort,
|
||||
killApp,
|
||||
launchApp,
|
||||
nextBuild,
|
||||
nextStart,
|
||||
renderViaHTTP,
|
||||
} from 'next-test-utils'
|
||||
|
||||
let app
|
||||
let appPort
|
||||
const appDir = join(__dirname, '../')
|
||||
|
||||
const runTests = () => {
|
||||
it('should resolve index page correctly', async () => {
|
||||
const html = await renderViaHTTP(appPort, '/')
|
||||
expect(html).toContain('Hello, World!')
|
||||
})
|
||||
}
|
||||
|
||||
const runRelayCompiler = () => {
|
||||
// Relay expects the current directory to contain a relay.json
|
||||
// This ensures the CWD is the one with relay.json since running
|
||||
// the relay-compiler through yarn would make the root of the repo the CWD.
|
||||
execSync('../../../node_modules/relay-compiler/cli.js', {
|
||||
cwd: './test/integration/relay-graphql-swc-single-project',
|
||||
})
|
||||
}
|
||||
|
||||
describe('Relay Compiler Transform - Single Project Config', () => {
|
||||
describe('dev mode', () => {
|
||||
beforeAll(async () => {
|
||||
runRelayCompiler()
|
||||
appPort = await findPort()
|
||||
app = await launchApp(appDir, appPort, { cwd: appDir })
|
||||
})
|
||||
afterAll(() => killApp(app))
|
||||
|
||||
runTests()
|
||||
})
|
||||
|
||||
describe('production mode', () => {
|
||||
beforeAll(async () => {
|
||||
runRelayCompiler()
|
||||
await nextBuild(appDir, [], { cwd: appDir })
|
||||
appPort = await findPort()
|
||||
app = await nextStart(appDir, appPort)
|
||||
})
|
||||
|
||||
afterAll(() => killApp(app))
|
||||
|
||||
runTests()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"jsx": "preserve",
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"incremental": true,
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
}
|
74
yarn.lock
74
yarn.lock
|
@ -2260,6 +2260,13 @@
|
|||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.0.0":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa"
|
||||
integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.10.2":
|
||||
version "7.12.13"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.13.tgz#0a21452352b02542db0ffb928ac2d3ca7cb6d66d"
|
||||
|
@ -4848,6 +4855,11 @@
|
|||
"@types/prop-types" "*"
|
||||
csstype "^2.2.0"
|
||||
|
||||
"@types/relay-runtime@13.0.0":
|
||||
version "13.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/relay-runtime/-/relay-runtime-13.0.0.tgz#d0009275522ff826f2e4dab40419f2db58417ecf"
|
||||
integrity sha512-yzv6F8EZPWA2rtfFP2qMluS8tsz1q4lfdYxLegCshdAjX5uqxTR2pAliATj9wrzD6OMZF4fl9aU+Y+zmSfm2EA==
|
||||
|
||||
"@types/resolve@1.17.1":
|
||||
version "1.17.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
|
||||
|
@ -7914,6 +7926,13 @@ cross-fetch@3.0.6, cross-fetch@^3.0.6:
|
|||
dependencies:
|
||||
node-fetch "2.6.1"
|
||||
|
||||
cross-fetch@^3.0.4:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39"
|
||||
integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==
|
||||
dependencies:
|
||||
node-fetch "2.6.1"
|
||||
|
||||
cross-spawn-async@^2.1.1:
|
||||
version "2.2.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc"
|
||||
|
@ -9848,6 +9867,24 @@ fb-watchman@^2.0.0:
|
|||
dependencies:
|
||||
bser "2.1.1"
|
||||
|
||||
fbjs-css-vars@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8"
|
||||
integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==
|
||||
|
||||
fbjs@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.2.tgz#dfae08a85c66a58372993ce2caf30863f569ff94"
|
||||
integrity sha512-qv+boqYndjElAJHNN3NoM8XuwQZ1j2m3kEvTgdle8IDjr6oUbkEpvABWtj/rQl3vq4ew7dnElBxL4YJAwTVqQQ==
|
||||
dependencies:
|
||||
cross-fetch "^3.0.4"
|
||||
fbjs-css-vars "^1.0.0"
|
||||
loose-envify "^1.0.0"
|
||||
object-assign "^4.1.0"
|
||||
promise "^7.1.1"
|
||||
setimmediate "^1.0.5"
|
||||
ua-parser-js "^0.7.30"
|
||||
|
||||
fd-slicer@~1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
|
||||
|
@ -11586,6 +11623,13 @@ interpret@^2.2.0:
|
|||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9"
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
invariant@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
||||
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
ip@^1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
|
||||
|
@ -13566,7 +13610,7 @@ longest-streak@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4"
|
||||
integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==
|
||||
|
||||
loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
dependencies:
|
||||
|
@ -16802,6 +16846,13 @@ promise@8.0.1:
|
|||
dependencies:
|
||||
asap "~2.0.3"
|
||||
|
||||
promise@^7.1.1:
|
||||
version "7.3.1"
|
||||
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
|
||||
integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
|
||||
dependencies:
|
||||
asap "~2.0.3"
|
||||
|
||||
prompts@2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.1.0.tgz#bf90bc71f6065d255ea2bdc0fe6520485c1b45db"
|
||||
|
@ -17549,6 +17600,20 @@ rehype-retext@^2.0.1:
|
|||
dependencies:
|
||||
hast-util-to-nlcst "^1.0.0"
|
||||
|
||||
relay-compiler@13.0.2:
|
||||
version "13.0.2"
|
||||
resolved "https://registry.yarnpkg.com/relay-compiler/-/relay-compiler-13.0.2.tgz#2ec086bcc55ac8cb94cc08a19be129e037ca8044"
|
||||
integrity sha512-Gg/5FNj8gz03GRkG5KjMNpDB4nOeApDFZq+8CZehu3KkQQ+vNIurX6RiTY3UNUYvg5SX2A9DS5bq5iHJ8iEV3A==
|
||||
|
||||
relay-runtime@13.0.2:
|
||||
version "13.0.2"
|
||||
resolved "https://registry.yarnpkg.com/relay-runtime/-/relay-runtime-13.0.2.tgz#02adb73ddc159c57b92a23c52984bf73fae0d1fc"
|
||||
integrity sha512-sP4lNGfFcOm7tQD12qlvwsiOREDgjkw4FQAjtemmtwivKOqI4qHAL22Ar62r5TPVlASn4iVWMk7rIdIJI20KGQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.0.0"
|
||||
fbjs "^3.0.2"
|
||||
invariant "^2.2.4"
|
||||
|
||||
release@6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/release/-/release-6.3.0.tgz#bbd351d7460948f1ed55ea02b4b2393f98a1637a"
|
||||
|
@ -18307,7 +18372,7 @@ set-value@^2.0.0, set-value@^2.0.1:
|
|||
is-plain-object "^2.0.3"
|
||||
split-string "^3.0.1"
|
||||
|
||||
setimmediate@1.0.5, setimmediate@^1.0.4:
|
||||
setimmediate@1.0.5, setimmediate@^1.0.4, setimmediate@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
|
||||
integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
|
||||
|
@ -19975,6 +20040,11 @@ ua-parser-js@0.7.28:
|
|||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.28.tgz#8ba04e653f35ce210239c64661685bf9121dec31"
|
||||
integrity sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g==
|
||||
|
||||
ua-parser-js@^0.7.30:
|
||||
version "0.7.31"
|
||||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6"
|
||||
integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.7.3"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a"
|
||||
|
|
Loading…
Reference in a new issue