Skip to content
This repository was archived by the owner on Sep 27, 2023. It is now read-only.

Commit 7f71c0d

Browse files
authored
Merge pull request #83 from timjacobi/master
support --noImplicitAny
2 parents b773504 + f8d8a87 commit 7f71c0d

File tree

7 files changed

+86
-6
lines changed

7 files changed

+86
-6
lines changed

src/addAnyTypeCast.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import * as ts from "typescript";
2+
3+
export default function addAsAnyToObjectLiterals(oldSource: string): string {
4+
function transformer<T extends ts.Node>(context: ts.TransformationContext) {
5+
return function transform(rootNode: T) {
6+
function visit(node: ts.Node): ts.Node {
7+
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
8+
return ts.createAsExpression(
9+
node as ts.Expression,
10+
ts.createTypeReferenceNode("any", [])
11+
);
12+
}
13+
return ts.visitEachChild(node, visit, context);
14+
}
15+
return ts.visitNode(rootNode, visit);
16+
};
17+
}
18+
19+
const source = ts.createSourceFile(
20+
"",
21+
oldSource,
22+
ts.ScriptTarget.ES2015,
23+
true,
24+
ts.ScriptKind.TS
25+
);
26+
27+
const result = ts.transform(source, [transformer]);
28+
29+
const printer: ts.Printer = ts.createPrinter({
30+
newLine: ts.NewLineKind.LineFeed
31+
});
32+
return printer.printFile(result.transformed[0] as ts.SourceFile);
33+
}

src/formatGeneratedModule.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { FormatModule } from "relay-compiler";
2+
import * as ts from "typescript";
3+
import addAnyTypeCast from "./addAnyTypeCast";
24

3-
export const formatGeneratedModule: FormatModule = ({
5+
export const formatterFactory = (
6+
compilerOptions: ts.CompilerOptions = {}
7+
): FormatModule => ({
48
moduleName,
59
documentType,
610
docText,
@@ -14,13 +18,18 @@ export const formatGeneratedModule: FormatModule = ({
1418
? `import { ${documentType} } from "${relayRuntimeModule}";`
1519
: "";
1620
const docTextComment = docText ? "\n/*\n" + docText.trim() + "\n*/\n" : "";
21+
let nodeStatement = `const node: ${documentType ||
22+
"never"} = ${concreteText};`;
23+
if (compilerOptions.noImplicitAny) {
24+
nodeStatement = addAnyTypeCast(nodeStatement).trim();
25+
}
1726
return `/* tslint:disable */
1827
1928
${documentTypeImport}
2029
${typeText || ""}
2130
2231
${docTextComment}
23-
const node: ${documentType || "never"} = ${concreteText};
32+
${nodeStatement}
2433
(node as any).hash = '${sourceHash}';
2534
export default node;
2635
`;

src/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import { PluginInterface } from "relay-compiler";
22

33
import { find } from "./FindGraphQLTags";
4-
import { formatGeneratedModule } from "./formatGeneratedModule";
4+
import { formatterFactory } from "./formatGeneratedModule";
5+
import { loadCompilerOptions } from "./loadCompilerOptions";
56
import * as TypeScriptGenerator from "./TypeScriptGenerator";
67

78
export default function plugin(): PluginInterface {
89
return {
910
inputExtensions: ["ts", "tsx"],
1011
outputExtension: "ts",
1112
findGraphQLTags: find,
12-
formatModule: formatGeneratedModule,
13+
formatModule: formatterFactory(loadCompilerOptions()),
1314
typeGenerator: TypeScriptGenerator
1415
};
1516
}

src/loadCompilerOptions.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as ts from "typescript";
2+
3+
export const loadCompilerOptions = (): ts.CompilerOptions => {
4+
const configFileName = ts.findConfigFile(process.cwd(), ts.sys.fileExists);
5+
if (!configFileName) {
6+
return {};
7+
}
8+
const result = ts.readConfigFile(configFileName, ts.sys.readFile);
9+
if (result.error) {
10+
return {};
11+
}
12+
return result.config.compilerOptions;
13+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* tslint:disable */
2+
3+
import { ConcreteFragment } from "relay-runtime";
4+
export type CompleteExample = { readonly id: string }
5+
6+
7+
const node: ConcreteFragment = {"the":{"fragment":{"data":42}}};
8+
(node as any).hash = 'edcba';
9+
export default node;

test/fixtures/generated-module/complete-example.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ import { ConcreteFragment } from "relay-runtime";
44
export type CompleteExample = { readonly id: string }
55

66

7-
const node: ConcreteFragment = {"the":{"fragment":{"data":42}}};
7+
const node: ConcreteFragment = ({ "the": { "fragment": { "data": 42 } } } as any);
88
(node as any).hash = 'edcba';
99
export default node;

test/formatGeneratedModule-test.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { join } from 'path'
33

44
import * as diff from 'jest-diff'
55

6-
import { formatGeneratedModule } from '../src/formatGeneratedModule'
6+
import { formatterFactory } from '../src/formatGeneratedModule'
77

88
expect.extend({
99
toMatchFile(received, fixturePath) {
@@ -37,6 +37,7 @@ expect.extend({
3737

3838
describe('formatGeneratedModule', () => {
3939
it('works', () => {
40+
const formatGeneratedModule = formatterFactory({noImplicitAny: true});
4041
expect(formatGeneratedModule({
4142
moduleName: 'complete-example',
4243
documentType: 'ConcreteFragment',
@@ -50,6 +51,7 @@ describe('formatGeneratedModule', () => {
5051
})
5152

5253
it('works without passing relay runtime module explicitly', () => {
54+
const formatGeneratedModule = formatterFactory({noImplicitAny: true});
5355
expect(formatGeneratedModule({
5456
moduleName: 'complete-example',
5557
documentType: 'ConcreteFragment',
@@ -60,4 +62,17 @@ describe('formatGeneratedModule', () => {
6062
sourceHash: 'edcba',
6163
})).toMatchFile(join(__dirname, 'fixtures/generated-module/complete-example.ts'))
6264
})
65+
66+
it('doesn\'t add a typecast if noImplicitAny is not set', () => {
67+
const formatGeneratedModule = formatterFactory();
68+
expect(formatGeneratedModule({
69+
moduleName: 'complete-example',
70+
documentType: 'ConcreteFragment',
71+
docText: null,
72+
concreteText: JSON.stringify({ the: { fragment: { data: 42 } }}),
73+
typeText: 'export type CompleteExample = { readonly id: string }',
74+
hash: 'abcde',
75+
sourceHash: 'edcba',
76+
})).toMatchFile(join(__dirname, 'fixtures/generated-module/complete-example-no-cast.ts'))
77+
})
6378
})

0 commit comments

Comments
 (0)