mirror: reflect nested fields in schema info (#917)

Summary:
See #915 for context. This adds nested field data to the “useful info”
data structure added in #857.

Test Plan:
Unit tests for `_buildSchemaInfo` updated.

wchargin-branch: mirror-schemainfo-shallow
This commit is contained in:
William Chargin 2018-10-04 15:30:04 -07:00 committed by GitHub
parent 3d2206088c
commit 49f0803a7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 76 additions and 3 deletions

View File

@ -1504,9 +1504,20 @@ type SchemaInfo = {|
+objectTypes: {|
+[Schema.Typename]: {|
+fields: {|+[Schema.Fieldname]: Schema.FieldType|},
+nestedFields: {|
+[Schema.Fieldname]: {|
+primitives: {|
+[Schema.Fieldname]: Schema.PrimitiveFieldType,
|},
+nodes: {|
+[Schema.Fieldname]: Schema.NodeFieldType,
|},
|},
|},
+primitiveFieldNames: $ReadOnlyArray<Schema.Fieldname>,
+linkFieldNames: $ReadOnlyArray<Schema.Fieldname>,
+connectionFieldNames: $ReadOnlyArray<Schema.Fieldname>,
+nestedFieldNames: $ReadOnlyArray<Schema.Fieldname>,
// There is always exactly one ID field, so it needs no
// special representation. (It's still included in the `fields`
// dictionary, though.)
@ -1524,9 +1535,20 @@ export function _buildSchemaInfo(schema: Schema.Schema): SchemaInfo {
objectTypes: (({}: any): {|
[Schema.Typename]: {|
+fields: {|+[Schema.Fieldname]: Schema.FieldType|},
+nestedFields: {|
[Schema.Fieldname]: {|
+primitives: {|
[Schema.Fieldname]: Schema.PrimitiveFieldType,
|},
+nodes: {|
[Schema.Fieldname]: Schema.NodeFieldType,
|},
|},
|},
+primitiveFieldNames: Array<Schema.Fieldname>,
+linkFieldNames: Array<Schema.Fieldname>,
+connectionFieldNames: Array<Schema.Fieldname>,
+nestedFieldNames: Array<Schema.Fieldname>,
|},
|}),
unionTypes: (({}: any): {|
@ -1541,14 +1563,24 @@ export function _buildSchemaInfo(schema: Schema.Schema): SchemaInfo {
case "OBJECT": {
const entry: {|
+fields: {|+[Schema.Fieldname]: Schema.FieldType|},
+nestedFields: $PropertyType<
$ElementType<
$PropertyType<typeof result, "objectTypes">,
Schema.Fieldname
>,
"nestedFields"
>,
+primitiveFieldNames: Array<Schema.Fieldname>,
+linkFieldNames: Array<Schema.Fieldname>,
+connectionFieldNames: Array<Schema.Fieldname>,
+nestedFieldNames: Array<Schema.Fieldname>,
|} = {
fields: type.fields,
nestedFields: ({}: any),
primitiveFieldNames: [],
linkFieldNames: [],
connectionFieldNames: [],
nestedFieldNames: [],
};
result.objectTypes[typename] = entry;
for (const fieldname of Object.keys(type.fields)) {
@ -1565,8 +1597,29 @@ export function _buildSchemaInfo(schema: Schema.Schema): SchemaInfo {
case "CONNECTION":
entry.connectionFieldNames.push(fieldname);
break;
case "NESTED":
throw new Error("Nested fields not supported.");
case "NESTED": {
entry.nestedFieldNames.push(fieldname);
const nestedFieldData: $ElementType<
$PropertyType<typeof entry, "nestedFields">,
Schema.Fieldname
> = {primitives: ({}: any), nodes: ({}: any)};
for (const eggFieldname of Object.keys(field.eggs)) {
const eggField = field.eggs[eggFieldname];
switch (eggField.type) {
case "PRIMITIVE":
nestedFieldData.primitives[eggFieldname] = eggField;
break;
case "NODE":
nestedFieldData.nodes[eggFieldname] = eggField;
break;
// istanbul ignore next
default:
throw new Error((eggField.type: empty));
}
}
entry.nestedFields[fieldname] = nestedFieldData;
break;
}
// istanbul ignore next
default:
throw new Error((field.type: empty));

View File

@ -2751,7 +2751,19 @@ describe("graphql/mirror", () => {
describe("_buildSchemaInfo", () => {
it("processes object types properly", () => {
const result = _buildSchemaInfo(buildGithubSchema());
const s = Schema;
const schema = {
...buildGithubSchema(),
Commit: s.object({
id: s.id(),
oid: s.primitive(),
author: /* GitActor */ s.nested({
date: s.primitive(),
user: s.node("User"),
}),
}),
};
const result = _buildSchemaInfo(schema);
expect(Object.keys(result.objectTypes).sort()).toEqual(
Array.from(
new Set([
@ -2777,6 +2789,14 @@ describe("graphql/mirror", () => {
expect(
result.objectTypes["Issue"].connectionFieldNames.slice().sort()
).toEqual(["comments", "timeline"].sort());
expect(result.objectTypes["Issue"].nestedFieldNames).toEqual([]);
expect(result.objectTypes["Commit"].nestedFieldNames).toEqual(["author"]);
expect(result.objectTypes["Commit"].nestedFields).toEqual({
author: {
primitives: {date: Schema.primitive()},
nodes: {user: Schema.node("User")},
},
});
});
it("processes union types correctly", () => {
const result = _buildSchemaInfo(buildGithubSchema());