Repository navigation
Expand file tree
/
Copy pathcodegen.test.cjs
More file actions
126 lines (110 loc) · 3.57 KB
/
Copy pathcodegen.test.cjs
File metadata and controls
126 lines (110 loc) · 3.57 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
123
124
125
126
// Generates types for a function the way Shopify CLI does, then type-checks them.
const { test } = require("node:test");
const assert = require("node:assert/strict");
const { execFileSync } = require("node:child_process");
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const ts = require("typescript");
const root = path.join(__dirname, "..");
// A function schema and an input query that selects an enum field and uses
// enum and input object variables.
const schema = `
schema {
query: Input
mutation: MutationRoot
}
scalar Void
enum CountryCode { CA US }
enum DeliveryMethod { SHIPPING PICK_UP }
input LineFilter {
titles: [String!]
country: CountryCode
}
type CartLine {
id: ID!
deliveryMethod: DeliveryMethod
}
type Cart {
lines(filter: LineFilter, country: CountryCode): [CartLine!]!
}
type Input {
cart: Cart!
}
input FunctionRunResult {
lineCount: Int!
}
type MutationRoot {
run(result: FunctionRunResult!): Void!
}
`;
const inputQuery = `
query RunInput($filter: LineFilter!, $country: CountryCode) {
cart {
lines(filter: $filter, country: $country) {
id
deliveryMethod
}
}
}
`;
// The codegen block of the JavaScript function templates in Shopify/extensions-templates.
const templateCodegen = {
schema: "schema.graphql",
documents: "src/*.graphql",
generates: { "./generated/api.ts": { plugins: ["typescript", "typescript-operations"] } },
config: { omitOperationSuffix: true },
};
// Shopify CLI merges these defaults into the function's codegen config, writes it
// to a temporary file and runs graphql-code-generator from the function directory.
// See buildGraphqlTypes in Shopify/cli packages/app/src/cli/services/function/build.ts.
const cliDefaults = {
defaultScalarType: "unknown",
scalars: {
Date: "string",
DateTime: "string",
DateTimeWithoutTimezone: "string",
Decimal: "string",
Handle: "string",
ID: "string",
JSON: "unknown",
TimeWithoutTimezone: "string",
URL: "string",
Void: "null",
},
};
test("generated types have no type errors when a query uses enums and input objects", () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "function-"));
const configDir = fs.mkdtempSync(path.join(os.tmpdir(), "codegen-"));
try {
fs.writeFileSync(path.join(dir, "schema.graphql"), schema);
fs.mkdirSync(path.join(dir, "src"));
fs.writeFileSync(path.join(dir, "src", "run.graphql"), inputQuery);
// Codegen resolves its plugins from the function directory, as in an installed function.
fs.symlinkSync(path.join(root, "node_modules"), path.join(dir, "node_modules"), "dir");
const configPath = path.join(configDir, "codegen.json");
fs.writeFileSync(
configPath,
JSON.stringify({
...templateCodegen,
config: { ...cliDefaults, ...templateCodegen.config, scalars: cliDefaults.scalars },
}),
);
const bin = fs.realpathSync(path.join(root, "node_modules", ".bin", "graphql-code-generator"));
execFileSync(process.execPath, [bin, "--config", configPath], { cwd: dir, stdio: "pipe" });
const program = ts.createProgram([path.join(dir, "generated", "api.ts")], {
strict: true,
noEmit: true,
skipLibCheck: true,
target: ts.ScriptTarget.ES2022,
types: [],
});
const errors = ts
.getPreEmitDiagnostics(program)
.map((d) => ts.flattenDiagnosticMessageText(d.messageText, "\n"));
assert.deepEqual(errors, []);
} finally {
fs.rmSync(dir, { recursive: true, force: true });
fs.rmSync(configDir, { recursive: true, force: true });
}
});