Skip to content

Commit 7f0eaa4

Browse files
committed
Groundwork
1 parent b983084 commit 7f0eaa4

File tree

4 files changed

+102
-0
lines changed

4 files changed

+102
-0
lines changed

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
"version": "0.0.0",
44
"description": "GraphQL Semantic Output Conversion Kit - converts a cutting edge SDL file that supports semantic nullability into a more traditional SDL file legacy tools can support.",
55
"main": "dist/index.js",
6+
"bin": {
7+
"semantic-to-nullable": "dist/cli/to-nullable.js",
8+
"semantic-to-strict": "dist/cli/to-strict.js"
9+
},
610
"scripts": {
711
"test": "node --test"
812
},

src/cli.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import {
2+
buildSchema,
3+
GraphQLInterfaceType,
4+
GraphQLNamedType,
5+
GraphQLObjectType,
6+
GraphQLSchema,
7+
printSchema,
8+
validateSchema,
9+
} from "graphql";
10+
import type { Maybe } from "graphql/jsutils/Maybe";
11+
import { readFile, writeFile } from "node:fs/promises";
12+
import { parseArgs } from "node:util";
13+
14+
export async function main(toStrict = false) {
15+
const {
16+
values: { input, output },
17+
} = parseArgs({
18+
options: {
19+
input: {
20+
type: "string",
21+
short: "i",
22+
},
23+
output: {
24+
type: "string",
25+
short: "o",
26+
},
27+
},
28+
});
29+
if (!input) {
30+
throw new Error("Please specify an --input schema");
31+
}
32+
if (!output) {
33+
throw new Error("Please specify an --output location");
34+
}
35+
36+
const sdl = await readFile(input, "utf8");
37+
const schema = buildSchema(sdl);
38+
const errors = validateSchema(schema);
39+
if (errors.length > 0) {
40+
console.dir(errors);
41+
throw new Error("Invalid schema");
42+
}
43+
44+
const config = schema.toConfig();
45+
const convertType = makeConvertType(toStrict);
46+
const derivedSchema = new GraphQLSchema({
47+
...config,
48+
query: convertType(config.query),
49+
mutation: convertType(config.mutation),
50+
subscription: convertType(config.subscription),
51+
});
52+
53+
const newSdl = printSchema(derivedSchema);
54+
55+
await writeFile(output, newSdl + "\n");
56+
}
57+
58+
function makeConvertType(toStrict: boolean) {
59+
const cache = new Map<string, GraphQLNamedType>();
60+
61+
function convertType(type: null | undefined): null | undefined;
62+
function convertType(type: GraphQLObjectType): GraphQLObjectType;
63+
function convertType(
64+
type: Maybe<GraphQLObjectType>,
65+
): Maybe<GraphQLObjectType>;
66+
function convertType(type: GraphQLNamedType): GraphQLNamedType;
67+
function convertType(type: GraphQLNamedType | null | undefined) {
68+
if (!type) return type;
69+
if (cache.has(type.name)) {
70+
return cache.get(type.name);
71+
}
72+
const newType = (() => {
73+
if (type instanceof GraphQLObjectType) {
74+
const config = type.toConfig();
75+
return new GraphQLObjectType({
76+
...config,
77+
});
78+
} else if (type instanceof GraphQLInterfaceType) {
79+
const config = type.toConfig();
80+
return new GraphQLInterfaceType({
81+
...config,
82+
});
83+
} else {
84+
return type;
85+
}
86+
})();
87+
cache.set(type.name, newType);
88+
return newType;
89+
}
90+
91+
return convertType;
92+
}

src/cli/to-nullable.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { main } from "../cli.js";
2+
3+
main(false);

src/cli/to-strict.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { main } from "../cli.js";
2+
3+
main(true);

0 commit comments

Comments
 (0)