@xyd-js/gql 0.0.0-build
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/TODO.md +8 -0
- package/__fixtures__/-1.opendocs.docs-nested/input.graphql +66 -0
- package/__fixtures__/-1.opendocs.docs-nested/output.json +554 -0
- package/__fixtures__/-1.opendocs.flat/input.graphql +19 -0
- package/__fixtures__/-1.opendocs.flat/output.json +243 -0
- package/__fixtures__/-1.opendocs.scopes/input.graphql +33 -0
- package/__fixtures__/-1.opendocs.scopes/output.json +378 -0
- package/__fixtures__/-1.opendocs.sidebar/input.graphql +44 -0
- package/__fixtures__/-1.opendocs.sort/input.graphql +92 -0
- package/__fixtures__/-1.opendocs.sort/output.json +1078 -0
- package/__fixtures__/-1.opendocs.sort+group/input.graphql +111 -0
- package/__fixtures__/-1.opendocs.sort+group/output.json +1114 -0
- package/__fixtures__/-1.opendocs.sort+group+path/input.graphql +118 -0
- package/__fixtures__/-1.opendocs.sort+group+path/output.json +1114 -0
- package/__fixtures__/-2.complex.github/input.graphql +69424 -0
- package/__fixtures__/-2.complex.github/output.json +269874 -0
- package/__fixtures__/-2.complex.livesession/input.graphql +23 -0
- package/__fixtures__/-2.complex.livesession/output.json +302 -0
- package/__fixtures__/-2.complex.monday/input.graphql +6089 -0
- package/__fixtures__/-2.complex.monday/output.json +1 -0
- package/__fixtures__/-3.array-non-null-return/input.graphql +9 -0
- package/__fixtures__/-3.array-non-null-return/output.json +151 -0
- package/__fixtures__/1.basic/input.graphql +118 -0
- package/__fixtures__/1.basic/output.json +630 -0
- package/__fixtures__/2.circular/input.graphql +17 -0
- package/__fixtures__/2.circular/output.json +248 -0
- package/__fixtures__/3.opendocs/input.graphql +27 -0
- package/__fixtures__/3.opendocs/output.json +338 -0
- package/__fixtures__/4.union/input.graphql +19 -0
- package/__fixtures__/4.union/output.json +344 -0
- package/__fixtures__/5.flat/input.graphql +27 -0
- package/__fixtures__/5.flat/output.json +383 -0
- package/__fixtures__/6.default-values/input.graphql +47 -0
- package/__fixtures__/6.default-values/output.json +655 -0
- package/__fixtures__/7.type-args/input.graphql +19 -0
- package/__fixtures__/7.type-args/output.json +301 -0
- package/__fixtures__/8.default-sort/input.graphql +60 -0
- package/__fixtures__/8.default-sort/output.json +1078 -0
- package/__tests__/gqlSchemaToReferences.test.ts +109 -0
- package/__tests__/utils.ts +45 -0
- package/declarations.d.ts +4 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +1503 -0
- package/dist/index.js.map +1 -0
- package/dist/opendocs.graphql +56 -0
- package/index.ts +3 -0
- package/package.json +29 -0
- package/src/context.ts +17 -0
- package/src/converters/gql-arg.ts +51 -0
- package/src/converters/gql-enum.ts +27 -0
- package/src/converters/gql-field.ts +164 -0
- package/src/converters/gql-input.ts +34 -0
- package/src/converters/gql-interface.ts +35 -0
- package/src/converters/gql-mutation.ts +36 -0
- package/src/converters/gql-object.ts +83 -0
- package/src/converters/gql-operation.ts +128 -0
- package/src/converters/gql-query.ts +36 -0
- package/src/converters/gql-sample.ts +159 -0
- package/src/converters/gql-scalar.ts +16 -0
- package/src/converters/gql-subscription.ts +36 -0
- package/src/converters/gql-types.ts +195 -0
- package/src/converters/gql-union.ts +40 -0
- package/src/gql-core.ts +362 -0
- package/src/index.ts +3 -0
- package/src/opendocs.graphql +56 -0
- package/src/opendocs.ts +253 -0
- package/src/schema.ts +293 -0
- package/src/types.ts +103 -0
- package/src/utils.ts +25 -0
- package/tsconfig.json +18 -0
- package/tsup.config.ts +33 -0
- package/tsup.examples-config.ts +30 -0
- package/vitest.config.ts +21 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
GraphQLEnumType,
|
|
3
|
+
GraphQLInputObjectType,
|
|
4
|
+
GraphQLInterfaceType,
|
|
5
|
+
GraphQLObjectType,
|
|
6
|
+
GraphQLScalarType,
|
|
7
|
+
GraphQLSchema,
|
|
8
|
+
GraphQLUnionType,
|
|
9
|
+
GraphQLNamedType,
|
|
10
|
+
} from "graphql";
|
|
11
|
+
import {
|
|
12
|
+
isIntrospectionType,
|
|
13
|
+
isSpecifiedScalarType
|
|
14
|
+
} from "graphql";
|
|
15
|
+
|
|
16
|
+
import {Reference} from "@xyd-js/uniform";
|
|
17
|
+
|
|
18
|
+
import {GQLSchemaToReferencesOptions, NestedGraphqlType} from "../types";
|
|
19
|
+
import {gqlObjectToUniformRef} from "./gql-object";
|
|
20
|
+
import {gqlInputToUniformRef} from "./gql-input";
|
|
21
|
+
import {gqlEnumToUniformRef} from "./gql-enum";
|
|
22
|
+
import {gqlScalarToUniformRef} from "./gql-scalar";
|
|
23
|
+
import {gqlUnionToUniformRef} from "./gql-union";
|
|
24
|
+
import {gqlInterfaceToUniformRef} from "./gql-interface";
|
|
25
|
+
import {Context} from "../context";
|
|
26
|
+
|
|
27
|
+
// TODO: missing types like interfaces, fragments.
|
|
28
|
+
export function graphqlTypesToUniformReferences(
|
|
29
|
+
schema: GraphQLSchema,
|
|
30
|
+
options?: GQLSchemaToReferencesOptions,
|
|
31
|
+
): Reference[] {
|
|
32
|
+
const references: Reference[] = []
|
|
33
|
+
const typeMap = schema.getTypeMap();
|
|
34
|
+
|
|
35
|
+
const sharedProcessedTypes = new Set<NestedGraphqlType>();
|
|
36
|
+
|
|
37
|
+
for (const gqlType of Object.values(typeMap)) {
|
|
38
|
+
const builtInType = isSpecifiedScalarType(gqlType) ||
|
|
39
|
+
isIntrospectionType(gqlType) ||
|
|
40
|
+
gqlType.name === "Mutation" ||
|
|
41
|
+
gqlType.name === "Query" ||
|
|
42
|
+
gqlType.name === "Subscription" ||
|
|
43
|
+
isInternalOpenDocsType(gqlType)
|
|
44
|
+
|
|
45
|
+
if (builtInType) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let ref: Reference | null = null
|
|
50
|
+
|
|
51
|
+
let flat = false;
|
|
52
|
+
if (options?.flat) {
|
|
53
|
+
flat = true;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
switch (gqlType.constructor.name) {
|
|
57
|
+
case 'GraphQLObjectType': {
|
|
58
|
+
const type = gqlType as GraphQLObjectType;
|
|
59
|
+
const regionKey = `object.${type.name}`;
|
|
60
|
+
if (!options?.regions || !options?.regions?.length || options.regions.includes(regionKey)) {
|
|
61
|
+
|
|
62
|
+
ref = gqlObjectToUniformRef(
|
|
63
|
+
new Context(
|
|
64
|
+
sharedProcessedTypes,
|
|
65
|
+
options,
|
|
66
|
+
{
|
|
67
|
+
flat,
|
|
68
|
+
},
|
|
69
|
+
schema
|
|
70
|
+
),
|
|
71
|
+
type,
|
|
72
|
+
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
break
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
case 'GraphQLInputObjectType': {
|
|
79
|
+
const type = gqlType as GraphQLInputObjectType;
|
|
80
|
+
const regionKey = `input.${type.name}`;
|
|
81
|
+
if (!options?.regions || !options?.regions?.length || options.regions.includes(regionKey)) {
|
|
82
|
+
ref = gqlInputToUniformRef(
|
|
83
|
+
new Context(
|
|
84
|
+
sharedProcessedTypes,
|
|
85
|
+
options,
|
|
86
|
+
{
|
|
87
|
+
flat,
|
|
88
|
+
},
|
|
89
|
+
schema
|
|
90
|
+
),
|
|
91
|
+
type
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
break
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
case 'GraphQLEnumType': {
|
|
98
|
+
const type = gqlType as GraphQLEnumType;
|
|
99
|
+
const regionKey = `enum.${type.name}`;
|
|
100
|
+
if (!options?.regions || !options?.regions?.length || options.regions.includes(regionKey)) {
|
|
101
|
+
ref = gqlEnumToUniformRef(
|
|
102
|
+
new Context(
|
|
103
|
+
new Set(),
|
|
104
|
+
options,
|
|
105
|
+
{},
|
|
106
|
+
schema
|
|
107
|
+
),
|
|
108
|
+
type
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
break
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
case 'GraphQLScalarType': {
|
|
115
|
+
const type = gqlType as GraphQLScalarType;
|
|
116
|
+
const regionKey = `scalar.${type.name}`;
|
|
117
|
+
if (!options?.regions || !options?.regions?.length || options.regions.includes(regionKey)) {
|
|
118
|
+
ref = gqlScalarToUniformRef(
|
|
119
|
+
new Context(
|
|
120
|
+
new Set(),
|
|
121
|
+
options,
|
|
122
|
+
{},
|
|
123
|
+
schema
|
|
124
|
+
),
|
|
125
|
+
type
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
break
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
case 'GraphQLUnionType': {
|
|
132
|
+
const type = gqlType as GraphQLUnionType;
|
|
133
|
+
const regionKey = `union.${type.name}`;
|
|
134
|
+
if (!options?.regions || !options?.regions?.length || options.regions.includes(regionKey)) {
|
|
135
|
+
ref = gqlUnionToUniformRef(
|
|
136
|
+
new Context(
|
|
137
|
+
sharedProcessedTypes,
|
|
138
|
+
options,
|
|
139
|
+
{
|
|
140
|
+
flat,
|
|
141
|
+
flatArg: flat || false
|
|
142
|
+
},
|
|
143
|
+
schema
|
|
144
|
+
),
|
|
145
|
+
type,
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
break
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
case 'GraphQLInterfaceType': {
|
|
153
|
+
const type = gqlType as GraphQLInterfaceType;
|
|
154
|
+
const regionKey = `interface.${type.name}`;
|
|
155
|
+
if (!options?.regions || !options?.regions?.length || options.regions.includes(regionKey)) {
|
|
156
|
+
ref = gqlInterfaceToUniformRef(
|
|
157
|
+
new Context(
|
|
158
|
+
new Set(),
|
|
159
|
+
options,
|
|
160
|
+
{
|
|
161
|
+
flat
|
|
162
|
+
},
|
|
163
|
+
schema
|
|
164
|
+
),
|
|
165
|
+
type,
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
break
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
default: {
|
|
172
|
+
console.debug(`Unsupported type: ${gqlType.constructor.name}`)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (ref) {
|
|
177
|
+
references.push(ref);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return references;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function isInternalOpenDocsType(type: GraphQLNamedType): boolean {
|
|
185
|
+
const internalTypes = [
|
|
186
|
+
'OpenDocsScope',
|
|
187
|
+
'OpenDocsSidebarItemType',
|
|
188
|
+
'OpenDocsPage',
|
|
189
|
+
'OpenDocsExampleInput',
|
|
190
|
+
'OpenDocsSortInput',
|
|
191
|
+
'OpenDocsSortStackInput'
|
|
192
|
+
|
|
193
|
+
]
|
|
194
|
+
return internalTypes.includes(type.name)
|
|
195
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {GraphQLUnionType} from "graphql";
|
|
2
|
+
|
|
3
|
+
import {Definition, DefinitionProperty, Reference} from "@xyd-js/uniform";
|
|
4
|
+
|
|
5
|
+
import {gqlObjectToUniformDefinitionProperty} from "./gql-object";
|
|
6
|
+
import {uniformify} from "../gql-core";
|
|
7
|
+
import {Context} from "../context";
|
|
8
|
+
|
|
9
|
+
export function gqlUnionToUniformRef(ctx: Context, unionType: GraphQLUnionType): Reference {
|
|
10
|
+
const properties = gqlUnionToUniformDefinitionProperties(ctx, unionType)
|
|
11
|
+
|
|
12
|
+
const definitions: Definition[] = [
|
|
13
|
+
{
|
|
14
|
+
title: "Possible types",
|
|
15
|
+
properties,
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
return uniformify(
|
|
20
|
+
ctx,
|
|
21
|
+
unionType,
|
|
22
|
+
definitions,
|
|
23
|
+
[]
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function gqlUnionToUniformDefinitionProperties(
|
|
28
|
+
ctx: Context,
|
|
29
|
+
unionType: GraphQLUnionType
|
|
30
|
+
): DefinitionProperty[] {
|
|
31
|
+
return unionType.getTypes().map(type => {
|
|
32
|
+
if (type.constructor.name === "GraphQLObjectType") {
|
|
33
|
+
return gqlObjectToUniformDefinitionProperty(
|
|
34
|
+
ctx,
|
|
35
|
+
type,
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
return []
|
|
39
|
+
}).flat()
|
|
40
|
+
}
|
package/src/gql-core.ts
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GraphQLArgument,
|
|
3
|
+
GraphQLEnumType,
|
|
4
|
+
GraphQLEnumValue,
|
|
5
|
+
GraphQLInputObjectType,
|
|
6
|
+
GraphQLInterfaceType,
|
|
7
|
+
GraphQLObjectType,
|
|
8
|
+
GraphQLScalarType,
|
|
9
|
+
GraphQLUnionType,
|
|
10
|
+
GraphQLField,
|
|
11
|
+
GraphQLInputField,
|
|
12
|
+
GraphQLNamedType,
|
|
13
|
+
|
|
14
|
+
isIntrospectionType,
|
|
15
|
+
isSpecifiedScalarType, GraphQLNonNull,
|
|
16
|
+
GraphQLList
|
|
17
|
+
} from "graphql";
|
|
18
|
+
import GithubSlugger from 'github-slugger';
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
Definition,
|
|
22
|
+
DefinitionProperty,
|
|
23
|
+
DefinitionPropertyMeta,
|
|
24
|
+
ExampleGroup,
|
|
25
|
+
Reference,
|
|
26
|
+
ReferenceCategory,
|
|
27
|
+
ReferenceType
|
|
28
|
+
} from "@xyd-js/uniform";
|
|
29
|
+
|
|
30
|
+
import {GQLTypeInfo, GQLOperation} from "./types";
|
|
31
|
+
import {gqlFieldToUniformDefinitionProperty} from "./converters/gql-field";
|
|
32
|
+
import {Context} from "./context";
|
|
33
|
+
import {openDocsCanonical, openDocsToGroup} from "./opendocs";
|
|
34
|
+
|
|
35
|
+
export type GraphqlUniformReferenceType =
|
|
36
|
+
| GraphQLScalarType
|
|
37
|
+
| GraphQLObjectType
|
|
38
|
+
| GraphQLInterfaceType
|
|
39
|
+
| GraphQLUnionType
|
|
40
|
+
| GraphQLEnumType
|
|
41
|
+
| GraphQLInputObjectType
|
|
42
|
+
| GQLOperation
|
|
43
|
+
| GraphQLField<any, any> | GraphQLInputField | GraphQLArgument
|
|
44
|
+
|
|
45
|
+
export function extractScopesFromDocDirective(
|
|
46
|
+
ctx: Context,
|
|
47
|
+
gqlType: GraphqlUniformReferenceType,
|
|
48
|
+
): string[] {
|
|
49
|
+
const scopes: string[] = []
|
|
50
|
+
|
|
51
|
+
const schema = ctx?.schema
|
|
52
|
+
|
|
53
|
+
if (gqlType.astNode?.directives) {
|
|
54
|
+
for (const directive of gqlType.astNode.directives) {
|
|
55
|
+
if (directive.name.value === "doc") {
|
|
56
|
+
const scopesArg = directive.arguments?.find(arg => arg.name.value === 'scopes')
|
|
57
|
+
if (scopesArg?.value.kind === 'ListValue') {
|
|
58
|
+
for (const scopeValue of scopesArg.value.values) {
|
|
59
|
+
if (scopeValue.kind === 'EnumValue') {
|
|
60
|
+
// For enum values, we need to find the enum type and its value with @scope directive
|
|
61
|
+
let enumType: GraphQLEnumType | undefined
|
|
62
|
+
|
|
63
|
+
// First check if current type is an enum
|
|
64
|
+
if (gqlType instanceof GraphQLEnumType) {
|
|
65
|
+
enumType = gqlType
|
|
66
|
+
}
|
|
67
|
+
// If not and we have a schema, try to find the enum type
|
|
68
|
+
else if (schema) {
|
|
69
|
+
const type = schema.getType('OpenDocsScope')
|
|
70
|
+
if (type instanceof GraphQLEnumType) {
|
|
71
|
+
enumType = type
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (enumType) {
|
|
76
|
+
const enumValue = enumType.getValue(scopeValue.value)
|
|
77
|
+
if (enumValue?.astNode?.directives) {
|
|
78
|
+
for (const enumDirective of enumValue.astNode.directives) {
|
|
79
|
+
if (enumDirective.name.value === 'scope') {
|
|
80
|
+
const valueArg = enumDirective.arguments?.find(arg => arg.name.value === 'value')
|
|
81
|
+
if (valueArg?.value.kind === 'StringValue') {
|
|
82
|
+
scopes.push(valueArg.value.value)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
} else if (scopeValue.kind === 'StringValue') {
|
|
89
|
+
// Handle string literal (e.g. "user:write")
|
|
90
|
+
scopes.push(scopeValue.value)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return scopes
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function uniformify(
|
|
102
|
+
ctx: Context,
|
|
103
|
+
gqlType: GraphqlUniformReferenceType,
|
|
104
|
+
definitions: Definition[],
|
|
105
|
+
examples: ExampleGroup[],
|
|
106
|
+
): Reference {
|
|
107
|
+
let canonicalPrefix = ""
|
|
108
|
+
let graphqlTypeShort = ""
|
|
109
|
+
let refType: ReferenceType | undefined = undefined
|
|
110
|
+
|
|
111
|
+
if (gqlType instanceof GraphQLScalarType) {
|
|
112
|
+
canonicalPrefix = "scalars"
|
|
113
|
+
graphqlTypeShort = "scalar"
|
|
114
|
+
refType = ReferenceType.GRAPHQL_SCALAR
|
|
115
|
+
} else if (gqlType instanceof GraphQLObjectType) {
|
|
116
|
+
canonicalPrefix = "objects"
|
|
117
|
+
graphqlTypeShort = "object"
|
|
118
|
+
refType = ReferenceType.GRAPHQL_OBJECT
|
|
119
|
+
} else if (gqlType instanceof GraphQLInterfaceType) {
|
|
120
|
+
canonicalPrefix = "interfaces"
|
|
121
|
+
graphqlTypeShort = "interface"
|
|
122
|
+
refType = ReferenceType.GRAPHQL_INTERFACE
|
|
123
|
+
} else if (gqlType instanceof GraphQLUnionType) {
|
|
124
|
+
canonicalPrefix = "unions"
|
|
125
|
+
graphqlTypeShort = "union"
|
|
126
|
+
refType = ReferenceType.GRAPHQL_UNION
|
|
127
|
+
} else if (gqlType instanceof GraphQLEnumType) {
|
|
128
|
+
canonicalPrefix = "enums"
|
|
129
|
+
graphqlTypeShort = "enum"
|
|
130
|
+
refType = ReferenceType.GRAPHQL_ENUM
|
|
131
|
+
} else if (gqlType instanceof GraphQLInputObjectType) {
|
|
132
|
+
canonicalPrefix = "inputs"
|
|
133
|
+
graphqlTypeShort = "input"
|
|
134
|
+
refType = ReferenceType.GRAPHQL_INPUT
|
|
135
|
+
} else if (gqlType instanceof GQLOperation) {
|
|
136
|
+
switch (gqlType._operationType) {
|
|
137
|
+
case "query": {
|
|
138
|
+
canonicalPrefix = "queries"
|
|
139
|
+
graphqlTypeShort = "query"
|
|
140
|
+
refType = ReferenceType.GRAPHQL_QUERY
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
case "mutation": {
|
|
144
|
+
canonicalPrefix = "mutations"
|
|
145
|
+
graphqlTypeShort = "mutation"
|
|
146
|
+
refType = ReferenceType.GRAPHQL_MUTATION
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case "subscription": {
|
|
150
|
+
canonicalPrefix = "subscriptions"
|
|
151
|
+
graphqlTypeShort = "subscription"
|
|
152
|
+
refType = ReferenceType.GRAPHQL_SUBSCRIPTION
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
const info = gqlFieldTypeInfo(gqlType)
|
|
158
|
+
if (info?.typeFlat && !isBuiltInType(info?.typeFlat)) {
|
|
159
|
+
if (info?.typeFlat) {
|
|
160
|
+
return uniformify(ctx, info.typeFlat, definitions, examples)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const slugger = new GithubSlugger();
|
|
166
|
+
// const slug = slugger.slug(gqlType.name);
|
|
167
|
+
const slug = gqlType.name;
|
|
168
|
+
|
|
169
|
+
const odCanonical = openDocsCanonical(ctx, gqlType);
|
|
170
|
+
|
|
171
|
+
let canonical = ""
|
|
172
|
+
if (odCanonical) {
|
|
173
|
+
canonical = odCanonical;
|
|
174
|
+
} else if (canonicalPrefix) {
|
|
175
|
+
canonical = [canonicalPrefix, slug].join("/")
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const scopes = extractScopesFromDocDirective(ctx, gqlType) || []
|
|
179
|
+
return {
|
|
180
|
+
title: gqlType.name,
|
|
181
|
+
description: gqlType.description || "",
|
|
182
|
+
canonical,
|
|
183
|
+
|
|
184
|
+
category: ReferenceCategory.GRAPHQL,
|
|
185
|
+
type: refType,
|
|
186
|
+
|
|
187
|
+
context: {
|
|
188
|
+
graphqlTypeShort: graphqlTypeShort,
|
|
189
|
+
graphqlName: gqlType.name,
|
|
190
|
+
group: openDocsToGroup(ctx, gqlType),
|
|
191
|
+
scopes
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
examples: {
|
|
195
|
+
groups: examples || [],
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
definitions,
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export function propsUniformify(
|
|
203
|
+
ctx: Context,
|
|
204
|
+
field: GraphQLField<any, any> | GraphQLInputField | GraphQLArgument,
|
|
205
|
+
properties?: DefinitionProperty[],
|
|
206
|
+
meta?: DefinitionPropertyMeta[]
|
|
207
|
+
): DefinitionProperty {
|
|
208
|
+
const fieldInfo = gqlFieldTypeInfo(field);
|
|
209
|
+
const objRef = uniformify(ctx, field, [], []);
|
|
210
|
+
|
|
211
|
+
const builtInType = fieldInfo?.typeFlat ? isBuiltInType(fieldInfo?.typeFlat) : undefined
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
name: field.name,
|
|
215
|
+
type: field.type.toJSON(),
|
|
216
|
+
description: field.description || "",
|
|
217
|
+
context: {
|
|
218
|
+
graphqlName: field.name,
|
|
219
|
+
graphqlTypeFlat: fieldInfo.typeFlat?.toJSON() || "",
|
|
220
|
+
graphqlBuiltInType: builtInType,
|
|
221
|
+
},
|
|
222
|
+
properties: properties || [],
|
|
223
|
+
meta: [
|
|
224
|
+
...gqlFieldToUniformMeta(field),
|
|
225
|
+
...(meta || []),
|
|
226
|
+
],
|
|
227
|
+
symbolDef: {
|
|
228
|
+
canonical: objRef?.canonical,
|
|
229
|
+
},
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function gqlObjectPropsUniformify(
|
|
234
|
+
ctx: Context,
|
|
235
|
+
obj: GraphQLInputObjectType | GraphQLObjectType,
|
|
236
|
+
meta?: DefinitionPropertyMeta[]
|
|
237
|
+
): DefinitionProperty {
|
|
238
|
+
const objRef = uniformify(ctx, obj, [], []);
|
|
239
|
+
const inputFields = obj.getFields?.()
|
|
240
|
+
const nestedProps: DefinitionProperty[] = []
|
|
241
|
+
|
|
242
|
+
const nestedDefinitionProperty: DefinitionProperty = {
|
|
243
|
+
name: obj.name,
|
|
244
|
+
type: obj.toJSON(),
|
|
245
|
+
description: obj.description || "",
|
|
246
|
+
context: objRef.context,
|
|
247
|
+
properties: nestedProps,
|
|
248
|
+
meta: [
|
|
249
|
+
...(meta || []),
|
|
250
|
+
],
|
|
251
|
+
symbolDef: {
|
|
252
|
+
canonical: objRef.canonical,
|
|
253
|
+
},
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (!ctx?.config?.flatArg) {
|
|
257
|
+
for (const [name, inputField] of Object.entries(inputFields)) {
|
|
258
|
+
const prop = gqlFieldToUniformDefinitionProperty(
|
|
259
|
+
ctx,
|
|
260
|
+
inputField,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
if (prop) {
|
|
264
|
+
nestedProps.push(prop)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return nestedDefinitionProperty
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export function gqlFieldToUniformMeta(
|
|
273
|
+
field: GraphQLField<any, any> | GraphQLInputField | GraphQLArgument
|
|
274
|
+
): DefinitionPropertyMeta[] {
|
|
275
|
+
const meta: DefinitionPropertyMeta[] = []
|
|
276
|
+
|
|
277
|
+
// Check if field is required (non-null)
|
|
278
|
+
if (isNonNullField(field.type) || isListOfNonNullItems(field.type)) {
|
|
279
|
+
meta.push({
|
|
280
|
+
name: "required",
|
|
281
|
+
value: "true"
|
|
282
|
+
})
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Handle directives
|
|
286
|
+
if (field.astNode?.directives) {
|
|
287
|
+
for (const directive of field.astNode.directives) {
|
|
288
|
+
// Handle @deprecated directive
|
|
289
|
+
if (directive.name.value === "deprecated") {
|
|
290
|
+
let foundDeprecatedReason = false
|
|
291
|
+
for (const arg of directive.arguments || []) {
|
|
292
|
+
if (arg.name.value === "reason") {
|
|
293
|
+
foundDeprecatedReason = true
|
|
294
|
+
meta.push({
|
|
295
|
+
name: "deprecated",
|
|
296
|
+
value: arg.value.kind === 'StringValue' ? arg.value.value : "true"
|
|
297
|
+
})
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (!foundDeprecatedReason) {
|
|
302
|
+
meta.push({
|
|
303
|
+
name: "deprecated",
|
|
304
|
+
value: "true"
|
|
305
|
+
})
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if ("defaultValue" in field && field.defaultValue !== undefined) {
|
|
312
|
+
meta.push({
|
|
313
|
+
name: "defaults",
|
|
314
|
+
value: field.defaultValue
|
|
315
|
+
})
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return meta
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export function gqlFieldTypeInfo(
|
|
322
|
+
field: GraphQLField<any, any> | GraphQLInputField
|
|
323
|
+
): GQLTypeInfo {
|
|
324
|
+
const getTypeInfo = (type: any): GraphQLNamedType | undefined => {
|
|
325
|
+
if (!type) return undefined;
|
|
326
|
+
|
|
327
|
+
// Handle non-null types
|
|
328
|
+
if (type instanceof GraphQLNonNull) {
|
|
329
|
+
return getTypeInfo(type.ofType);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
if (type instanceof GraphQLList) {
|
|
334
|
+
return getTypeInfo(type.ofType);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Return the actual type
|
|
338
|
+
return type;
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const graphqlTypeFlat = getTypeInfo(field.type);
|
|
342
|
+
|
|
343
|
+
return {
|
|
344
|
+
typeFlat: graphqlTypeFlat
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export function isBuiltInType(gqlType: GraphQLNamedType): boolean {
|
|
349
|
+
return isSpecifiedScalarType(gqlType) || isIntrospectionType(gqlType)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// TODO: fix any
|
|
353
|
+
function isNonNullField(type: any): boolean {
|
|
354
|
+
return type.constructor.name === "GraphQLNonNull"
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// TODO: fix any
|
|
358
|
+
function isListOfNonNullItems(type: any): boolean {
|
|
359
|
+
return "ofType" in type &&
|
|
360
|
+
type.constructor.name === "GraphQLList" &&
|
|
361
|
+
type.ofType.constructor.name === "GraphQLNonNull"
|
|
362
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
directive @scope(value: String!) on ENUM_VALUE
|
|
2
|
+
|
|
3
|
+
enum OpenDocsScope {
|
|
4
|
+
_PLACEHOLDER_
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
directive @docs(
|
|
8
|
+
route: String
|
|
9
|
+
sort: [OpenDocsSortInput!]
|
|
10
|
+
sortStack: [[String!]!]
|
|
11
|
+
flattenTypes: Boolean
|
|
12
|
+
sidebar: [OpenDocsPage]
|
|
13
|
+
group: [String]
|
|
14
|
+
) repeatable on SCHEMA
|
|
15
|
+
|
|
16
|
+
input OpenDocsPage {
|
|
17
|
+
type: OpenDocsSidebarItemType!
|
|
18
|
+
key: String!
|
|
19
|
+
group: String
|
|
20
|
+
path: String
|
|
21
|
+
pages: [OpenDocsPage]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
enum OpenDocsSidebarItemType {
|
|
25
|
+
OPERATION
|
|
26
|
+
TYPE
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
directive @doc(
|
|
30
|
+
group: [String!],
|
|
31
|
+
path: String,
|
|
32
|
+
example: OpenDocsExampleInput,
|
|
33
|
+
scopes: [OpenDocsScope],
|
|
34
|
+
) on QUERY |
|
|
35
|
+
FIELD_DEFINITION |
|
|
36
|
+
MUTATION |
|
|
37
|
+
SUBSCRIPTION |
|
|
38
|
+
OBJECT |
|
|
39
|
+
INPUT_OBJECT |
|
|
40
|
+
ENUM |
|
|
41
|
+
SCALAR |
|
|
42
|
+
UNION
|
|
43
|
+
|
|
44
|
+
# TODO: finish
|
|
45
|
+
input OpenDocsExampleInput {
|
|
46
|
+
"""
|
|
47
|
+
The name of the code
|
|
48
|
+
"""
|
|
49
|
+
code: String!
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
input OpenDocsSortInput {
|
|
53
|
+
node: String
|
|
54
|
+
group: [String!]
|
|
55
|
+
stack: Int
|
|
56
|
+
}
|