This repository has been archived by the owner on Jun 29, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 19
/
context.ts
112 lines (91 loc) · 2.6 KB
/
context.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import {relative, dirname} from 'path';
import * as t from '@babel/types';
import {ucFirst} from 'change-case';
import {AST, Fragment, isOperation, Operation} from 'graphql-tool-utilities';
import {EnumFormat} from '../../types';
export interface Options {
schemaTypesPath: string;
enumFormat?: EnumFormat;
addTypename?: boolean;
}
export interface OperationOptions extends Options {
partial?: boolean;
}
export type NamespaceExportableType = t.TSInterfaceDeclaration;
export class FileContext {
get schemaImports() {
const {
path,
importedTypes,
options: {schemaTypesPath},
} = this;
return importedTypes.size > 0
? t.importDeclaration(
[...importedTypes].map((type) =>
t.importSpecifier(t.identifier(type), t.identifier(type)),
),
t.stringLiteral(importPath(path, schemaTypesPath)),
)
: null;
}
private readonly importedTypes = new Set<string>();
constructor(
private readonly path: string,
private readonly options: Options,
) {}
import(type: string) {
this.importedTypes.add(type);
}
}
export class OperationContext {
get typeName() {
let typeName: string;
if (isOperation(this.operation)) {
const {operationName, operationType} = this.operation;
typeName = `${ucFirst(operationName)}${ucFirst(operationType)}Data`;
} else {
const {fragmentName} = this.operation;
typeName = `${ucFirst(fragmentName)}FragmentData`;
}
return this.options.partial
? typeName.replace(/Data$/, 'PartialData')
: typeName;
}
get namespace() {
const {exported, typeName} = this;
return exported.length > 0
? t.tsModuleDeclaration(
t.identifier(typeName),
t.tsModuleBlock(
exported.map((type) => t.exportNamedDeclaration(type, [])),
),
)
: null;
}
get exported() {
return this.exportedTypes;
}
private readonly exportedTypes: NamespaceExportableType[] = [];
constructor(
public operation: Operation | Fragment,
public ast: AST,
public options: OperationOptions,
public file: FileContext,
) {}
export(type: NamespaceExportableType) {
this.exportedTypes.push(type);
return t.tsTypeReference(
t.tsQualifiedName(
t.identifier(this.typeName),
t.identifier(type.id.name),
),
);
}
}
function importPath(from: string, to: string) {
const relativePath = relative(dirname(from), to);
const normalizedPath = relativePath.startsWith('..')
? relativePath
: `./${relativePath}`;
return normalizedPath.replace(/\.ts$/, '');
}