@gleanql/codegen 0.1.14 → 0.1.16
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/dist/index.mjs +16 -1
- package/package.json +2 -2
- package/src/types.ts +19 -1
package/dist/index.mjs
CHANGED
|
@@ -138,7 +138,7 @@ function generateTypes(schema, options = {}) {
|
|
|
138
138
|
function renderTypeBlock(type, ctx) {
|
|
139
139
|
switch (type.kind) {
|
|
140
140
|
case "OBJECT": return renderObjectLike(type, ctx, JSON.stringify(type.name));
|
|
141
|
-
case "INTERFACE": return
|
|
141
|
+
case "INTERFACE": return renderInterface(type, ctx);
|
|
142
142
|
case "UNION": return renderUnion(type);
|
|
143
143
|
case "ENUM": return renderEnum(type);
|
|
144
144
|
case "INPUT_OBJECT": return renderInputObject(type, ctx);
|
|
@@ -159,6 +159,21 @@ function renderUnion(type) {
|
|
|
159
159
|
const body = members.length > 0 ? members.join(" | ") : "never";
|
|
160
160
|
return `export type ${type.name} = ${body};`;
|
|
161
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* An interface is narrowable: render it as the union of its possible types, so a
|
|
164
|
+
* `x.__typename === "Product"` guard refines the value to the concrete type and
|
|
165
|
+
* its fields (`x.title`) become accessible — the shape GraphQL selections on an
|
|
166
|
+
* interface root (`nodes(ids:) { ... on Product { title } }`) actually return.
|
|
167
|
+
* Each implementer already carries every interface field (introspection includes
|
|
168
|
+
* inherited fields on each object type), so common-field access (`x.id`) is
|
|
169
|
+
* preserved across the union. Falls back to a thin interface when no possible
|
|
170
|
+
* types surface (e.g. a schema exposing an interface no type implements).
|
|
171
|
+
*/
|
|
172
|
+
function renderInterface(type, ctx) {
|
|
173
|
+
const members = (type.possibleTypes ?? []).map((p) => namedTypeName(p)).filter((name) => !isInternalType(name));
|
|
174
|
+
if (members.length === 0) return renderObjectLike(type, ctx, typenameUnionOf(type));
|
|
175
|
+
return `export type ${type.name} = ${members.join(" | ")};`;
|
|
176
|
+
}
|
|
162
177
|
function renderEnum(type) {
|
|
163
178
|
const values = (type.enumValues ?? []).map((v) => JSON.stringify(v.name));
|
|
164
179
|
const body = values.length > 0 ? values.join(" | ") : "never";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gleanql/codegen",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Glean's schema codegen: introspection to schema model, branded types and graph accessors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Alexander Liljengard",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@gleanql/core": "0.1.
|
|
29
|
+
"@gleanql/core": "0.1.16"
|
|
30
30
|
},
|
|
31
31
|
"homepage": "https://gleanql.com",
|
|
32
32
|
"bugs": "https://github.com/gleanql/gleanql/issues",
|
package/src/types.ts
CHANGED
|
@@ -49,7 +49,7 @@ function renderTypeBlock(type: IntrospectionType, ctx: Ctx): string | undefined
|
|
|
49
49
|
case "OBJECT":
|
|
50
50
|
return renderObjectLike(type, ctx, JSON.stringify(type.name));
|
|
51
51
|
case "INTERFACE":
|
|
52
|
-
return
|
|
52
|
+
return renderInterface(type, ctx);
|
|
53
53
|
case "UNION":
|
|
54
54
|
return renderUnion(type);
|
|
55
55
|
case "ENUM":
|
|
@@ -82,6 +82,24 @@ function renderUnion(type: IntrospectionType): string {
|
|
|
82
82
|
return `export type ${type.name} = ${body};`;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
/**
|
|
86
|
+
* An interface is narrowable: render it as the union of its possible types, so a
|
|
87
|
+
* `x.__typename === "Product"` guard refines the value to the concrete type and
|
|
88
|
+
* its fields (`x.title`) become accessible — the shape GraphQL selections on an
|
|
89
|
+
* interface root (`nodes(ids:) { ... on Product { title } }`) actually return.
|
|
90
|
+
* Each implementer already carries every interface field (introspection includes
|
|
91
|
+
* inherited fields on each object type), so common-field access (`x.id`) is
|
|
92
|
+
* preserved across the union. Falls back to a thin interface when no possible
|
|
93
|
+
* types surface (e.g. a schema exposing an interface no type implements).
|
|
94
|
+
*/
|
|
95
|
+
function renderInterface(type: IntrospectionType, ctx: Ctx): string {
|
|
96
|
+
const members = (type.possibleTypes ?? [])
|
|
97
|
+
.map((p) => namedTypeName(p))
|
|
98
|
+
.filter((name) => !isInternalType(name));
|
|
99
|
+
if (members.length === 0) return renderObjectLike(type, ctx, typenameUnionOf(type));
|
|
100
|
+
return `export type ${type.name} = ${members.join(" | ")};`;
|
|
101
|
+
}
|
|
102
|
+
|
|
85
103
|
function renderEnum(type: IntrospectionType): string {
|
|
86
104
|
const values = (type.enumValues ?? []).map((v) => JSON.stringify(v.name));
|
|
87
105
|
const body = values.length > 0 ? values.join(" | ") : "never";
|