From 49f0803a7afd6e0843595ad978a7debe9aa4e0bc Mon Sep 17 00:00:00 2001 From: William Chargin Date: Thu, 4 Oct 2018 15:30:04 -0700 Subject: [PATCH] mirror: reflect nested fields in schema info (#917) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/graphql/mirror.js | 57 ++++++++++++++++++++++++++++++++++++-- src/graphql/mirror.test.js | 22 ++++++++++++++- 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/graphql/mirror.js b/src/graphql/mirror.js index 9fc4d62..3e8abe9 100644 --- a/src/graphql/mirror.js +++ b/src/graphql/mirror.js @@ -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, +linkFieldNames: $ReadOnlyArray, +connectionFieldNames: $ReadOnlyArray, + +nestedFieldNames: $ReadOnlyArray, // 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, +linkFieldNames: Array, +connectionFieldNames: Array, + +nestedFieldNames: Array, |}, |}), 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, + Schema.Fieldname + >, + "nestedFields" + >, +primitiveFieldNames: Array, +linkFieldNames: Array, +connectionFieldNames: Array, + +nestedFieldNames: Array, |} = { 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, + 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)); diff --git a/src/graphql/mirror.test.js b/src/graphql/mirror.test.js index 69bea7e..a44ea4b 100644 --- a/src/graphql/mirror.test.js +++ b/src/graphql/mirror.test.js @@ -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());