forked from api-platform/api-doc-parser
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparseGraphQl.ts
More file actions
122 lines (107 loc) · 3.26 KB
/
Copy pathparseGraphQl.ts
File metadata and controls
122 lines (107 loc) · 3.26 KB
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
113
114
115
116
117
118
119
120
121
122
import { getIntrospectionQuery } from "graphql/utilities/index.js";
import fetchQuery from "./fetchQuery.js";
import { Api } from "../Api.js";
import { Field } from "../Field.js";
import { Resource } from "../Resource.js";
import type {
IntrospectionObjectType,
IntrospectionOutputTypeRef,
IntrospectionQuery,
} from "graphql/utilities";
const getRangeFromGraphQlType = (type: IntrospectionOutputTypeRef): string => {
if (type.kind === "NON_NULL") {
if (type.ofType.kind === "LIST") {
return `Array<${getRangeFromGraphQlType(type.ofType.ofType)}>`;
}
return type.ofType.name;
}
if (type.kind === "LIST") {
return `Array<${getRangeFromGraphQlType(type.ofType)}>`;
}
return type.name;
};
const getReferenceFromGraphQlType = (
type: IntrospectionOutputTypeRef
): null | string => {
if (type.kind === "OBJECT" && type.name.endsWith("Connection")) {
return type.name.slice(0, type.name.lastIndexOf("Connection"));
}
return null;
};
export default async (
entrypointUrl: string,
options: RequestInit = {}
): Promise<{
api: Api;
response: Response;
}> => {
const introspectionQuery = getIntrospectionQuery();
const {
response,
body: { data },
} = await fetchQuery<IntrospectionQuery>(
entrypointUrl,
introspectionQuery,
options
);
if (!data?.__schema) {
throw new Error(
"Schema has not been retrieved from the introspection query."
);
}
const schema = data?.__schema;
const typeResources = schema.types.filter(
(type) =>
type.kind === "OBJECT" &&
type.name !== schema.queryType.name &&
type.name !== schema.mutationType?.name &&
type.name !== schema.subscriptionType?.name &&
!type.name.startsWith("__") &&
// mutation
!type.name.startsWith(type.name[0].toLowerCase()) &&
!type.name.endsWith("Connection") &&
!type.name.endsWith("Edge") &&
!type.name.endsWith("PageInfo")
) as IntrospectionObjectType[];
const resources: Resource[] = [];
typeResources.forEach((typeResource) => {
const fields: Field[] = [];
const readableFields: Field[] = [];
const writableFields: Field[] = [];
typeResource.fields.forEach((resourceFieldType) => {
const field = new Field(resourceFieldType.name, {
range: getRangeFromGraphQlType(resourceFieldType.type),
reference: getReferenceFromGraphQlType(resourceFieldType.type),
required: resourceFieldType.type.kind === "NON_NULL",
description: resourceFieldType.description,
deprecated: resourceFieldType.isDeprecated,
});
fields.push(field);
readableFields.push(field);
writableFields.push(field);
});
resources.push(
new Resource(typeResource.name, "", {
fields,
readableFields,
writableFields,
})
);
});
resources.forEach((resource) => {
resource.fields?.forEach((field) => {
if (null !== field.reference) {
field.reference =
resources.find((resource) => resource.name === field.reference) ||
null;
} else if (null !== field.range) {
field.reference =
resources.find((resource) => resource.name === field.range) || null;
}
});
});
return {
api: new Api(entrypointUrl, { resources }),
response,
};
};