Przeglądaj źródła

feat(core): Auto-generate GraphQL ListOptions for plugin extensions

Michael Bromley 6 lat temu
rodzic
commit
aa40776634

+ 19 - 0
packages/core/e2e/fixtures/test-plugins.ts

@@ -47,6 +47,14 @@ export class TestAdminPluginResolver {
     foo() {
         return ['bar'];
     }
+
+    @Query()
+    barList() {
+        return {
+            items: [{ id: 1, name: 'Test' }],
+            totalItems: 1,
+        };
+    }
 }
 
 @Resolver()
@@ -71,6 +79,17 @@ export class TestShopPluginResolver {
         schema: gql`
             extend type Query {
                 foo: [String]!
+                barList(options: BarListOptions): BarList!
+            }
+
+            input BarListOptions
+            type Bar implements Node {
+                id: ID!
+                name: String!
+            }
+            type BarList implements PaginatedList {
+                items: [Bar!]!
+                totalItems: Int!
             }
         `,
     },

+ 18 - 0
packages/core/e2e/plugin.e2e-spec.ts

@@ -85,6 +85,24 @@ describe('Plugins', () => {
         expect(result.baz).toEqual(['quux']);
     });
 
+    it('generates ListQueryOptions for api extensions', async () => {
+        const result = await adminClient.query(gql`
+            query {
+                barList(options: { skip: 0, take: 1 }) {
+                    items {
+                        id
+                        name
+                    }
+                    totalItems
+                }
+            }
+        `);
+        expect(result.barList).toEqual({
+            items: [{ id: 'T_1', name: 'Test' }],
+            totalItems: 1,
+        });
+    });
+
     it('DI works with defined providers', async () => {
         const result = await shopClient.query(gql`
             query {

+ 8 - 8
packages/core/src/api/config/configure-graphql-module.ts

@@ -3,7 +3,7 @@ import { GqlModuleOptions, GraphQLModule, GraphQLTypesLoader } from '@nestjs/gra
 import { StockMovementType } from '@vendure/common/lib/generated-types';
 import { notNullOrUndefined } from '@vendure/common/lib/shared-utils';
 import { GraphQLUpload } from 'apollo-server-core';
-import { extendSchema, printSchema } from 'graphql';
+import { buildSchema, extendSchema, printSchema } from 'graphql';
 import { GraphQLDateTime } from 'graphql-iso-date';
 import GraphQLJSON from 'graphql-type-json';
 import path from 'path';
@@ -161,17 +161,17 @@ async function createGraphQLOptions(
         // See https://github.com/nestjs/graphql/issues/336
         const normalizedPaths = options.typePaths.map(p => p.split(path.sep).join('/'));
         const typeDefs = await typesLoader.mergeTypesByPaths(normalizedPaths);
-        let schema = generateListOptions(typeDefs);
+        let schema = buildSchema(typeDefs);
+
+        getPluginAPIExtensions(configService.plugins, apiType)
+            .map(e => e.schema)
+            .filter(notNullOrUndefined)
+            .forEach(documentNode => (schema = extendSchema(schema, documentNode)));
+        schema = generateListOptions(schema);
         schema = addGraphQLCustomFields(schema, customFields, apiType === 'shop');
         schema = addServerConfigCustomFields(schema, customFields);
         schema = addOrderLineCustomFieldsInput(schema, customFields.OrderLine || []);
-        const pluginSchemaExtensions = getPluginAPIExtensions(configService.plugins, apiType)
-            .map(e => e.schema)
-            .filter(notNullOrUndefined);
 
-        for (const documentNode of pluginSchemaExtensions) {
-            schema = extendSchema(schema, documentNode);
-        }
         return printSchema(schema);
     }
 }

+ 2 - 6
packages/core/src/api/config/generate-list-options.ts

@@ -1,6 +1,5 @@
 import {
     buildSchema,
-    extendSchema,
     GraphQLEnumType,
     GraphQLField,
     GraphQLInputFieldConfig,
@@ -59,14 +58,11 @@ export function generateListOptions(typeDefsOrSchema: string | GraphQLSchema): G
                     ...(existingListOptions ? existingListOptions.getFields() : {}),
                 },
             });
-            let listOptionsInput: GraphQLInputObjectType;
-
-            listOptionsInput = generatedListOptions;
 
             if (!query.args.find(a => a.type.toString() === `${targetTypeName}ListOptions`)) {
                 query.args.push({
                     name: 'options',
-                    type: listOptionsInput,
+                    type: generatedListOptions,
                     description: null,
                     defaultValue: null,
                     extensions: null,
@@ -76,7 +72,7 @@ export function generateListOptions(typeDefsOrSchema: string | GraphQLSchema): G
 
             generatedTypes.push(filterParameter);
             generatedTypes.push(sortParameter);
-            generatedTypes.push(listOptionsInput);
+            generatedTypes.push(generatedListOptions);
         }
     }
     return mergeSchemas({ schemas: [schema, generatedTypes] });