Merge pull request #11 from microsoft/relay-compiler-language-graphitation

Add graphitation specific wrapper around relay-compiler typescript plugin
This commit is contained in:
Eloy Durán 2021-04-23 16:05:35 +02:00 коммит произвёл GitHub
Родитель d7f9a7b9f4 3a23a29ec0
Коммит 1bcea46d02
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
19 изменённых файлов: 397 добавлений и 280 удалений

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Use generated typings in tests",
"packageName": "@graphitation/apollo-react-relay-duct-tape",
"email": "eloy.de.enige@gmail.com",
"dependentChangeType": "none"
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "none",
"comment": "chmod",
"packageName": "monorepo-scripts",
"email": "eloy.de.enige@gmail.com",
"dependentChangeType": "none"
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Initial import",
"packageName": "relay-compiler-language-graphitation",
"email": "eloy.de.enige@gmail.com",
"dependentChangeType": "none"
}

Просмотреть файл

@ -3,3 +3,5 @@
Compatibility wrapper that provides the react-relay API on top of Apollo Client.
_The name is a reference to the Apollo 13 mission._
Use this together with [relay-compiler-language-graphitation](../relay-compiler-language-graphitation) to have typings generated.

Просмотреть файл

@ -8,7 +8,7 @@
"test": "monorepo-scripts test",
"types": "monorepo-scripts types",
"just": "monorepo-scripts",
"relay": "relay-compiler --language typescript --schema ./src/__tests__/schema.graphql --src ./src"
"generate-interfaces": "relay-compiler --language graphitation --schema ./src/__tests__/schema.graphql --src ./src"
},
"devDependencies": {
"@apollo/client": "^3.3.15",
@ -20,7 +20,8 @@
"monorepo-scripts": "*",
"react": "^17.0.2",
"relay-compiler": "^11.0.2",
"relay-compiler-language-typescript": "^14.0.0"
"relay-compiler-language-graphitation": "^0.1.0",
"ts-expect": "^1.3.0"
},
"peerDependencies": {
"graphql": "^15.5.0",

Просмотреть файл

@ -0,0 +1,16 @@
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
;
import { FragmentRefs } from "@graphitation/apollo-react-relay-duct-tape";
export type hooksTestFragment = {
readonly id: string;
readonly name: string;
readonly __typename: "User";
readonly " $refType": "hooksTestFragment";
};
export type hooksTestFragment$data = hooksTestFragment;
export type hooksTestFragment$key = {
readonly " $data"?: hooksTestFragment$data;
readonly " $fragmentRefs": FragmentRefs<"hooksTestFragment">;
};

Просмотреть файл

@ -1,111 +1,17 @@
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from "relay-runtime";
;
import { FragmentRefs } from "@graphitation/apollo-react-relay-duct-tape";
export type hooksTestQueryVariables = {
id: string;
};
export type hooksTestQueryResponse = {
readonly user: {
readonly __typename: string;
readonly id: string;
readonly name: string;
readonly " $fragmentRefs": FragmentRefs<"hooksTestFragment">;
};
};
export type hooksTestQuery = {
readonly response: hooksTestQueryResponse;
readonly variables: hooksTestQueryVariables;
};
/*
query hooksTestQuery(
$id: ID!
) {
user(id: $id) {
__typename
id
name
}
}
*/
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "id"
}
],
v1 = [
{
"alias": null,
"args": [
{
"kind": "Variable",
"name": "id",
"variableName": "id"
}
],
"concreteType": "User",
"kind": "LinkedField",
"name": "user",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "name",
"storageKey": null
}
],
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "hooksTestQuery",
"selections": (v1/*: any*/),
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "hooksTestQuery",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "6c639dbf8d0688927412bd37fc17a021",
"id": null,
"metadata": {},
"name": "hooksTestQuery",
"operationKind": "query",
"text": "query hooksTestQuery(\n $id: ID!\n) {\n user(id: $id) {\n __typename\n id\n name\n }\n}\n"
}
};
})();
(node as any).hash = '7a1aec44ec5fa0e3d845c54f5d71d236';
export default node;

Просмотреть файл

@ -1,111 +1,17 @@
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from "relay-runtime";
;
import { FragmentRefs } from "@graphitation/apollo-react-relay-duct-tape";
export type hooksTestSubscriptionVariables = {
id: string;
};
export type hooksTestSubscriptionResponse = {
readonly userNameChanged: {
readonly __typename: string;
readonly id: string;
readonly name: string;
readonly " $fragmentRefs": FragmentRefs<"hooksTestFragment">;
};
};
export type hooksTestSubscription = {
readonly response: hooksTestSubscriptionResponse;
readonly variables: hooksTestSubscriptionVariables;
};
/*
subscription hooksTestSubscription(
$id: ID!
) {
userNameChanged(id: $id) {
__typename
id
name
}
}
*/
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "id"
}
],
v1 = [
{
"alias": null,
"args": [
{
"kind": "Variable",
"name": "id",
"variableName": "id"
}
],
"concreteType": "User",
"kind": "LinkedField",
"name": "userNameChanged",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "name",
"storageKey": null
}
],
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "hooksTestSubscription",
"selections": (v1/*: any*/),
"type": "Subscription",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "hooksTestSubscription",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "ad32680a90ff3dcb6a6060afc511e537",
"id": null,
"metadata": {},
"name": "hooksTestSubscription",
"operationKind": "subscription",
"text": "subscription hooksTestSubscription(\n $id: ID!\n) {\n userNameChanged(id: $id) {\n __typename\n id\n name\n }\n}\n"
}
};
})();
(node as any).hash = '5204570ce28f0c0003d6129fea7a3f0d';
export default node;

Просмотреть файл

@ -8,6 +8,7 @@ import {
ReactTestRenderer,
} from "react-test-renderer";
import { ApolloProvider } from "@apollo/client";
import { expectType } from "ts-expect";
import { graphql } from "@graphitation/graphql-js-tag";
import * as MockPayloadGenerator from "@graphitation/graphql-js-operation-payload-generator";
@ -16,32 +17,98 @@ import {
createMockClient,
} from "@graphitation/apollo-mock-client/src/index"; // FIXME
import {
GraphQLTaggedNode,
useFragment,
useLazyLoadQuery,
useSubscription,
} from "../hooks";
// import { GraphQLTaggedNode } from "./taggedNode";
import { FragmentRefs } from "../types";
import { useFragment, useLazyLoadQuery, useSubscription } from "../hooks";
import { hooksTestQuery } from "./__generated__/hooksTestQuery.graphql";
import { hooksTestSubscription } from "./__generated__/hooksTestSubscription.graphql";
import { hooksTestFragment$key } from "./__generated__/hooksTestFragment.graphql";
const schema = buildSchema(
readFileSync(join(__dirname, "schema.graphql"), "utf8")
);
/**
* Fragment test subject
*/
const fragment = graphql`
fragment hooksTestFragment on User {
__typename
id
name
}
`;
const FragmentComponent: React.FC<{ user: hooksTestFragment$key }> = (
props
) => {
const user = useFragment(fragment, props.user);
return <div id={user.__typename}>{user.name}</div>;
};
/**
* Query test subject
*/
const query = graphql`
query hooksTestQuery($id: ID!) {
user(id: $id) {
__typename
id
name
...hooksTestFragment
}
}
${fragment}
`;
const QueryComponent: React.FC = () => {
const { data, error } = useLazyLoadQuery<hooksTestQuery>(query, {
id: "some-user-id",
});
if (error) {
return <div id="error">{error.message}</div>;
} else if (data) {
return <FragmentComponent user={data.user} />;
} else {
return <div id="loading">Loading...</div>;
}
};
/**
* Subscription test subject
*/
const subscription = graphql`
subscription hooksTestSubscription($id: ID!) {
userNameChanged(id: $id) {
...hooksTestFragment
}
}
${fragment}
`;
type SubscriptionHookParams = Parameters<typeof useSubscription>[0];
interface SubjectProps {
onNext?: SubscriptionHookParams["onNext"];
onError?: SubscriptionHookParams["onError"] | null;
}
const SubscriptionComponent: React.FC<SubjectProps> = ({
onNext = jest.fn(),
onError = jest.fn(),
children,
}) => {
useSubscription<hooksTestSubscription>({
subscription,
variables: { id: "some-user-id" },
onNext,
onError: onError || undefined,
});
return <>{children}</>;
};
/**
* Tests
*/
let client: ApolloMockClient;
beforeEach(() => {
@ -50,24 +117,11 @@ beforeEach(() => {
describe(useLazyLoadQuery, () => {
it("uses Apollo's useQuery hook", async () => {
const Subject: React.FC = () => {
const { data, error } = useLazyLoadQuery<hooksTestQuery>(query, {
id: "some-user-id",
});
if (error) {
return <div id="error">{error.message}</div>;
} else if (data) {
return <div id={data.user.__typename}>{data.user.name}</div>;
} else {
return <div id="loading">Loading...</div>;
}
};
let tree: ReactTestRenderer;
act(() => {
tree = createTestRenderer(
<ApolloProvider client={client}>
<Subject />
<QueryComponent />
</ApolloProvider>
);
});
@ -89,74 +143,27 @@ describe(useLazyLoadQuery, () => {
describe(useFragment, () => {
it("currently simply passes through the data it receives", () => {
const fragment = ({} as unknown) as GraphQLTaggedNode;
const fragmentRef = { someKey: "some-data" } as any;
const fragmentRef: hooksTestFragment$key = {} as any;
expect(useFragment(fragment, fragmentRef)).toEqual(fragmentRef);
});
it("unmasks the opaque data's typing that gets emitted by the compiler", () => {
type SomeFragment$data = { someKey: string };
type SomeFragment$key = {
readonly " $data"?: SomeFragment$data;
readonly " $fragmentRefs": FragmentRefs<"SomeFragment">;
};
const fragment = ({} as unknown) as GraphQLTaggedNode;
const opaqueFragmentRef = ({} as unknown) as SomeFragment$key;
// This test just checks that there are no TS errors. Alas the test suite currently won't fail if that were the
// case, but at least there's a test that covers the intent.
const data: SomeFragment$data = useFragment(fragment, opaqueFragmentRef);
void data;
const fragmentRef: hooksTestFragment$key = {} as any;
const user = useFragment(fragment, fragmentRef);
expectType<string>(user.id);
expectType<string>(user.name);
});
});
describe(useSubscription, () => {
const subscription = graphql`
subscription hooksTestSubscription($id: ID!) {
userNameChanged(id: $id) {
__typename
id
name
}
}
`;
type SubscriptionHookParams = Parameters<typeof useSubscription>[0];
interface SubjectProps {
onNext?: SubscriptionHookParams["onNext"];
onError?: SubscriptionHookParams["onError"] | null;
}
const Subject: React.FC<SubjectProps> = ({
onNext = jest.fn(),
onError = jest.fn(),
children,
}) => {
useSubscription<hooksTestSubscription>({
subscription,
variables: { id: "some-user-id" },
onNext,
onError: onError || undefined,
});
return <>{children}</>;
};
it("uses Apollo's useSubscription hook", async () => {
const QueryComponent = () => {
const { data } = useLazyLoadQuery<hooksTestQuery>(query, {
id: "some-user-id",
});
return data ? <div>{data.user.name}</div> : null;
};
it("uses Apollo's useSubscription hook and updates the store", async () => {
let tree: ReactTestRenderer;
act(() => {
tree = createTestRenderer(
<ApolloProvider client={client}>
<Subject>
<SubscriptionComponent>
<QueryComponent />
</Subject>
</SubscriptionComponent>
</ApolloProvider>
);
});
@ -217,7 +224,7 @@ describe(useSubscription, () => {
act(() => {
createTestRenderer(
<ApolloProvider client={client}>
<Subject onNext={onNext} />
<SubscriptionComponent onNext={onNext} />
</ApolloProvider>
);
});
@ -246,7 +253,7 @@ describe(useSubscription, () => {
act(() => {
createTestRenderer(
<ApolloProvider client={client}>
<Subject onError={onError} />
<SubscriptionComponent onError={onError} />
</ApolloProvider>
);
});
@ -265,7 +272,7 @@ describe(useSubscription, () => {
act(() => {
createTestRenderer(
<ApolloProvider client={client}>
<Subject onError={null} />
<SubscriptionComponent onError={null} />
</ApolloProvider>
);
});

Просмотреть файл

@ -0,0 +1,9 @@
# relay-compiler-language-graphitation
A relay-compiler plugin that wraps [the TypeScript plugin](https://github.com/relay-tools/relay-compiler-language-typescript) and augments it slightly for our needs:
- Currently only emit typings, no relay-runtime metadata
- Allow interpolation of GraphQL fragment documents
- Rewrite `@graphitation_test_operation` to relay-compiler's `@raw_response_type` -- _this will likely be removed short-term_
- Rewrite `relay-runtime` import in generated artefacts to `@graphitation/apollo-react-relay-duct-tape`
- Strip `__isFoo` fields from raw response typings, which is something that relay-runtime needs

Просмотреть файл

@ -0,0 +1,24 @@
{
"name": "relay-compiler-language-graphitation",
"version": "0.1.0",
"main": "./lib/index.js",
"scripts": {
"build": "tsc",
"lint": "monorepo-scripts lint",
"just": "monorepo-scripts"
},
"dependencies": {
"graphql": "^14.6.0",
"relay-compiler-language-typescript": "^14.0.0",
"typescript": "^4.2.3"
},
"devDependencies": {
"@types/jest": "^26.0.22",
"@types/relay-compiler": "^8.0.0",
"monorepo-scripts": "*"
},
"publishConfig": {
"main": "./lib/index.js",
"access": "public"
}
}

Просмотреть файл

@ -0,0 +1,84 @@
/**
* Taken from https://github.com/relay-tools/relay-compiler-language-typescript/blob/b186ac3d9d9682949638211c3126c015f8706b0f/src/FindGraphQLTags.ts
* License: MIT
* Copyright 2018 Kaare Hoff Skovgaard kaare@kaareskovgaard.net, Eloy Durán eloy.de.enige@gmail.com
*/
/**
* NOTE: This is currently in-flight and mostly re-uses code from the above mentioned package, where it's tested.
*/
/* istanbul ignore file */
import * as ts from "typescript";
import {
GraphQLTag,
GraphQLTagFinder,
} from "relay-compiler/lib/language/RelayLanguagePluginInterface";
import { rewriteGraphitationDirectives } from "./rewriteGraphitationDirectives";
/**
* @note Difference from the TS language plugin is that we only support hooks, so no need for HOCs.
*/
function visit(node: ts.Node, addGraphQLTag: (tag: GraphQLTag) => void): void {
function visitNode(node: ts.Node) {
switch (node.kind) {
case ts.SyntaxKind.TaggedTemplateExpression: {
const taggedTemplate = node as ts.TaggedTemplateExpression;
if (isGraphQLTag(taggedTemplate.tag)) {
// TODO: This code previously had no validation and thus no
// keyName/sourceLocationOffset. Are these right?
addGraphQLTag({
keyName: null,
template: getGraphQLText(taggedTemplate),
sourceLocationOffset: getSourceLocationOffset(taggedTemplate),
});
}
}
}
ts.forEachChild(node, visitNode);
}
visitNode(node);
}
function isGraphQLTag(tag: ts.Node): boolean {
return (
tag.kind === ts.SyntaxKind.Identifier &&
(tag as ts.Identifier).text === "graphql"
);
}
/**
* @note The difference here is that we do allow substitutions, but only in the trailing part, so we always return the
* head. This might lead to a bad DX when the user does allow substitution in the document part and receiving
* hard to understand errors, but seeing as this is meant as temporary solution it may be a worthwhile trade-off.
*/
function getTemplateNode(quasi: ts.TaggedTemplateExpression) {
if (quasi.template.kind === ts.SyntaxKind.TemplateExpression) {
return quasi.template.head;
}
return quasi.template;
}
/**
* @note The difference here is that we rewrite graphitation specific directives to relay ones.
*/
function getGraphQLText(quasi: ts.TaggedTemplateExpression) {
return rewriteGraphitationDirectives(getTemplateNode(quasi).text);
}
function getSourceLocationOffset(quasi: ts.TaggedTemplateExpression) {
const pos = getTemplateNode(quasi).pos;
const loc = quasi.getSourceFile().getLineAndCharacterOfPosition(pos);
return {
line: loc.line + 1,
column: loc.character + 1,
};
}
export const find: GraphQLTagFinder = (text, filePath) => {
const result: GraphQLTag[] = [];
const ast = ts.createSourceFile(filePath, text, ts.ScriptTarget.Latest, true);
visit(ast, (tag) => result.push(tag));
return result;
};

Просмотреть файл

@ -0,0 +1,13 @@
/**
* NOTE: This is currently in-flight and mostly re-uses code from the above mentioned package, where it's tested.
*/
/* istanbul ignore file */
import { FormatModule } from "relay-compiler/lib/language/RelayLanguagePluginInterface";
export const formatModule: FormatModule = ({ hash, typeText }) =>
`/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
${hash ? `/* ${hash} */\n` : ""};
${typeText || ""}`;

Просмотреть файл

@ -0,0 +1,21 @@
import type { PluginInitializer } from "relay-compiler/lib/language/RelayLanguagePluginInterface";
import typescriptPluginInitializer from "relay-compiler-language-typescript";
import { find as findGraphQLTags } from "./findGraphQLTags";
import { formatModule } from "./formatModule";
import { generateFactory } from "./typeGenerator";
const pluginInitializer: PluginInitializer = () => {
const typescriptPlugin = typescriptPluginInitializer();
return {
...typescriptPlugin,
findGraphQLTags,
formatModule,
typeGenerator: {
...typescriptPlugin.typeGenerator,
generate: generateFactory(typescriptPlugin.typeGenerator.generate),
},
};
};
export = pluginInitializer;

Просмотреть файл

@ -0,0 +1,32 @@
/**
* NOTE: This is currently in-flight and mostly re-uses code from the above mentioned package, where it's tested.
*/
import { parse, print, visit } from "graphql";
/**
* This rewrites graphitation specific directives to relay ones. Currently it does the following:
*
* - `@graphitation_test_operation` is rewritten to `@raw_response_type`.
* In the future this should probably also add `@relay_test_operation`.
*
* @param document A single GraphQL document
*/
export function rewriteGraphitationDirectives(document: string) {
const documentNode = parse(document);
const rewrittenDocumentNode = visit(documentNode, {
Directive(directiveNode) {
if (directiveNode.name.value === "graphitation_test_operation") {
return {
...directiveNode,
name: {
kind: "Name",
value: "raw_response_type",
},
};
}
return undefined;
},
});
return print(rewrittenDocumentNode);
}

Просмотреть файл

@ -0,0 +1,20 @@
/**
* NOTE: This is currently in-flight and mostly re-uses code from the above mentioned package, where it's tested.
*/
/* istanbul ignore file */
import { TypeGenerator } from "relay-compiler/lib/language/RelayLanguagePluginInterface";
export function generateFactory(wrappedGenerate: TypeGenerator["generate"]) {
const generate: TypeGenerator["generate"] = (schema, node, options) => {
const generated = wrappedGenerate(schema, node, options);
return (
generated
.replace("relay-runtime", "@graphitation/apollo-react-relay-duct-tape")
// These fields in the `@raw_response_type` output are really just for relay-runtime, so for now we can just
// strip them out entirely.
.replace(/^\s+readonly __is[A-Z].+;\n/gm, "")
);
};
return generate;
}

Просмотреть файл

@ -0,0 +1,19 @@
{
"compilerOptions": {
"composite": false,
"incremental": true,
"tsBuildInfoFile": ".tsbuildinfo",
"target": "es5",
"module": "commonjs",
"moduleResolution": "Node",
"rootDir": "src",
"outDir": "lib",
"declaration": false,
"declarationMap": false,
"strict": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
},
"include": ["src"],
"references": []
}

Просмотреть файл

@ -14,7 +14,7 @@ export const test = () => {
return jestTask({
config: path.join(__dirname, "config", "jest.config.js"),
watch: argv().watch,
_: argv()._
_: argv()._,
});
};

Просмотреть файл

@ -1192,6 +1192,20 @@
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/relay-compiler@^8.0.0":
version "8.0.0"
resolved "https://registry.yarnpkg.com/@types/relay-compiler/-/relay-compiler-8.0.0.tgz#98961b923555145067d3895f8774f3024f14e6fa"
integrity sha512-rSR62gfhm2ZZp888RK93/jODOCA1j2MpWr5ibZEyYprmVG1G9KE5TfNUERCcc9z58F4d8tMIX00ZpBOU1sWcDA==
dependencies:
"@types/relay-runtime" "*"
graphql "^14.5.3"
typescript "^3.0.0"
"@types/relay-runtime@*":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@types/relay-runtime/-/relay-runtime-11.0.0.tgz#7ddbe41152d46b614d1f3f7f0672cfb721eb93f1"
integrity sha512-D5JNxDhkcPSIMZc2j3N/fh61399O309ph9RVmzbF+Fsyvepsqy7FirFKcJ2CMfYxE/kb8ZD/Xdzs3CYZEiQc4w==
"@types/scheduler@*":
version "0.16.1"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275"
@ -3324,6 +3338,13 @@ graphql-tag@^2.12.0:
dependencies:
tslib "^2.1.0"
graphql@^14.5.3, graphql@^14.6.0:
version "14.7.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.7.0.tgz#7fa79a80a69be4a31c27dda824dc04dac2035a72"
integrity sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA==
dependencies:
iterall "^1.2.2"
graphql@^15.0.0, graphql@^15.5.0:
version "15.5.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.0.tgz#39d19494dbe69d1ea719915b578bf920344a69d5"
@ -3838,6 +3859,11 @@ istanbul-reports@^3.0.2:
html-escaper "^2.0.0"
istanbul-lib-report "^3.0.0"
iterall@^1.2.2:
version "1.3.0"
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
jest-changed-files@^26.6.2:
version "26.6.2"
resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0"
@ -6303,6 +6329,11 @@ trim-repeated@^1.0.0:
dependencies:
escape-string-regexp "^1.0.2"
ts-expect@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/ts-expect/-/ts-expect-1.3.0.tgz#3f8d3966e0e22b5e2bb88337eb99db6816a4c1cf"
integrity sha512-e4g0EJtAjk64xgnFPD6kTBUtpnMVzDrMb12N1YZV0VvSlhnVT3SGxiYTLdGy8Q5cYHOIC/FAHmZ10eGrAguicQ==
ts-invariant@^0.7.0:
version "0.7.3"
resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.7.3.tgz#13aae22a4a165393aaf5cecdee45ef4128d358b8"
@ -6433,6 +6464,11 @@ typedarray-to-buffer@^3.1.5:
dependencies:
is-typedarray "^1.0.0"
typescript@^3.0.0:
version "3.9.9"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.9.tgz#e69905c54bc0681d0518bd4d587cc6f2d0b1a674"
integrity sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==
typescript@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.3.tgz#39062d8019912d43726298f09493d598048c1ce3"