Răsfoiți Sursa

feat(core): Add facetValue query to Admin API

Michael Bromley 5 luni în urmă
părinte
comite
fae3c51968

+ 3 - 2
packages/core/e2e/collection.e2e-spec.ts

@@ -79,7 +79,8 @@ describe('Collection resolver', () => {
             },
         });
         assets = assetsResult.assets.items;
-        const facetValuesResult = await adminClient.query<Codegen.GetFacetValuesQuery>(GET_FACET_VALUES);
+        const facetValuesResult =
+            await adminClient.query<Codegen.GetFacetWithFacetValuesQuery>(GET_FACET_VALUES);
         facetValues = facetValuesResult.facets.items.reduce(
             (values, facet) => [...values, ...facet.values],
             [] as FacetValueFragment[],
@@ -2453,7 +2454,7 @@ export const MOVE_COLLECTION = gql`
 `;
 
 const GET_FACET_VALUES = gql`
-    query GetFacetValues {
+    query GetFacetWithFacetValues {
         facets {
             items {
                 values {

+ 37 - 0
packages/core/e2e/facet.e2e-spec.ts

@@ -23,6 +23,8 @@ import {
     CREATE_FACET,
     GET_FACET_LIST,
     GET_FACET_LIST_SIMPLE,
+    GET_FACET_VALUE,
+    GET_FACET_VALUES,
     GET_FACET_WITH_VALUES,
     GET_PRODUCT_WITH_VARIANTS,
     UPDATE_FACET,
@@ -196,6 +198,41 @@ describe('Facet resolver', () => {
         expect(result.facet?.valueList.totalItems).toBe(2);
     });
 
+    it('facetValues list query', async () => {
+        const result = await adminClient.query<
+            Codegen.GetFacetValuesQuery,
+            Codegen.GetFacetValuesQueryVariables
+        >(GET_FACET_VALUES, {
+            options: {
+                filter: {
+                    facetId: { eq: speakerTypeFacet.id },
+                },
+            },
+        });
+
+        expect(result.facetValues.totalItems).toBe(3);
+        expect(result.facetValues.items.length).toBe(3);
+        expect(result.facetValues.items.map(v => v.code).sort()).toEqual(['compact', 'hi-fi', 'pc']);
+        expect(result.facetValues.items.every(v => v.facet.id === speakerTypeFacet.id)).toBe(true);
+    });
+
+    it('facetValue single query', async () => {
+        const pcFacetValue = speakerTypeFacet.values.find(v => v.code === 'pc')!;
+        const result = await adminClient.query<
+            Codegen.GetFacetValueQuery,
+            Codegen.GetFacetValueQueryVariables
+        >(GET_FACET_VALUE, {
+            id: pcFacetValue.id,
+        });
+
+        expect(result.facetValue).toBeDefined();
+        expect(result.facetValue!.id).toBe(pcFacetValue.id);
+        expect(result.facetValue!.code).toBe('pc');
+        expect(result.facetValue!.name).toBe('PC Speakers');
+        expect(result.facetValue!.facet.id).toBe(speakerTypeFacet.id);
+        expect(result.facetValue!.facet.name).toBe('Speaker Category');
+    });
+
     it('product.facetValues resolver omits private facets in shop-api', async () => {
         const publicFacetValue = brandFacet.values[0];
         const privateFacetValue = speakerTypeFacet.values[0];

+ 211 - 40
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -2200,11 +2200,6 @@ export enum JobState {
     RUNNING = 'RUNNING',
 }
 
-export type KeyValueInput = {
-    key: Scalars['String']['input'];
-    value: Scalars['JSON']['input'];
-};
-
 /**
  * @description
  * Languages in the form of a ISO 639-1 language code with optional
@@ -2940,10 +2935,6 @@ export type Mutation = {
     setDraftOrderShippingAddress: Order;
     /** Sets the shipping method by id, which can be obtained with the `eligibleShippingMethodsForDraftOrder` query */
     setDraftOrderShippingMethod: SetOrderShippingMethodResult;
-    /** Set a single key-value pair (automatically scoped based on field configuration) */
-    setKeyValue: SetKeyValueResult;
-    /** Set multiple key-value pairs in a transaction (each automatically scoped) */
-    setKeyValues: Array<SetKeyValueResult>;
     setOrderCustomFields?: Maybe<Order>;
     /** Allows a different Customer to be assigned to an Order. Added in v2.2.0. */
     setOrderCustomer?: Maybe<Order>;
@@ -3538,14 +3529,6 @@ export type MutationSetDraftOrderShippingMethodArgs = {
     shippingMethodId: Scalars['ID']['input'];
 };
 
-export type MutationSetKeyValueArgs = {
-    input: KeyValueInput;
-};
-
-export type MutationSetKeyValuesArgs = {
-    inputs: Array<KeyValueInput>;
-};
-
 export type MutationSetOrderCustomFieldsArgs = {
     input: UpdateOrderInput;
 };
@@ -4886,14 +4869,11 @@ export type Query = {
     /** Returns all configured EntityDuplicators. */
     entityDuplicators: Array<EntityDuplicatorDefinition>;
     facet?: Maybe<Facet>;
+    facetValue?: Maybe<FacetValue>;
     facetValues: FacetValueList;
     facets: FacetList;
     fulfillmentHandlers: Array<ConfigurableOperationDefinition>;
     /** Get value for a specific key (automatically scoped based on field configuration) */
-    getKeyValue?: Maybe<Scalars['JSON']['output']>;
-    /** Get multiple key-value pairs (each automatically scoped) */
-    getKeyValues?: Maybe<Scalars['JSON']['output']>;
-    /** Get value for a specific key (automatically scoped based on field configuration) */
     getSettingsStoreValue?: Maybe<Scalars['JSON']['output']>;
     /** Get multiple key-value pairs (each automatically scoped) */
     getSettingsStoreValues?: Maybe<Scalars['JSON']['output']>;
@@ -5020,6 +5000,10 @@ export type QueryFacetArgs = {
     id: Scalars['ID']['input'];
 };
 
+export type QueryFacetValueArgs = {
+    id: Scalars['ID']['input'];
+};
+
 export type QueryFacetValuesArgs = {
     options?: InputMaybe<FacetValueListOptions>;
 };
@@ -5028,14 +5012,6 @@ export type QueryFacetsArgs = {
     options?: InputMaybe<FacetListOptions>;
 };
 
-export type QueryGetKeyValueArgs = {
-    key: Scalars['String']['input'];
-};
-
-export type QueryGetKeyValuesArgs = {
-    keys: Array<Scalars['String']['input']>;
-};
-
 export type QueryGetSettingsStoreValueArgs = {
     key: Scalars['String']['input'];
 };
@@ -5585,12 +5561,6 @@ export type ServerConfig = {
 
 export type SetCustomerForDraftOrderResult = EmailAddressConflictError | Order;
 
-export type SetKeyValueResult = {
-    error?: Maybe<Scalars['String']['output']>;
-    key: Scalars['String']['output'];
-    result: Scalars['Boolean']['output'];
-};
-
 export type SetOrderCustomerInput = {
     customerId: Scalars['ID']['input'];
     note?: InputMaybe<Scalars['String']['input']>;
@@ -6863,9 +6833,9 @@ export type MoveCollectionMutation = {
     };
 };
 
-export type GetFacetValuesQueryVariables = Exact<{ [key: string]: never }>;
+export type GetFacetWithFacetValuesQueryVariables = Exact<{ [key: string]: never }>;
 
-export type GetFacetValuesQuery = {
+export type GetFacetWithFacetValuesQuery = {
     facets: {
         items: Array<{
             values: Array<{
@@ -11072,6 +11042,39 @@ export type GetFacetWithValuesQuery = {
     } | null;
 };
 
+export type GetFacetValuesQueryVariables = Exact<{
+    options?: InputMaybe<FacetValueListOptions>;
+}>;
+
+export type GetFacetValuesQuery = {
+    facetValues: {
+        totalItems: number;
+        items: Array<{
+            id: string;
+            languageCode: LanguageCode;
+            code: string;
+            name: string;
+            translations: Array<{ id: string; languageCode: LanguageCode; name: string }>;
+            facet: { id: string; name: string };
+        }>;
+    };
+};
+
+export type GetFacetValueQueryVariables = Exact<{
+    id: Scalars['ID']['input'];
+}>;
+
+export type GetFacetValueQuery = {
+    facetValue?: {
+        id: string;
+        languageCode: LanguageCode;
+        code: string;
+        name: string;
+        translations: Array<{ id: string; languageCode: LanguageCode; name: string }>;
+        facet: { id: string; name: string };
+    } | null;
+};
+
 export type GetPromotionQueryVariables = Exact<{
     id: Scalars['ID']['input'];
 }>;
@@ -16755,13 +16758,13 @@ export const MoveCollectionDocument = {
         },
     ],
 } as unknown as DocumentNode<MoveCollectionMutation, MoveCollectionMutationVariables>;
-export const GetFacetValuesDocument = {
+export const GetFacetWithFacetValuesDocument = {
     kind: 'Document',
     definitions: [
         {
             kind: 'OperationDefinition',
             operation: 'query',
-            name: { kind: 'Name', value: 'GetFacetValues' },
+            name: { kind: 'Name', value: 'GetFacetWithFacetValues' },
             selectionSet: {
                 kind: 'SelectionSet',
                 selections: [
@@ -16837,7 +16840,7 @@ export const GetFacetValuesDocument = {
             },
         },
     ],
-} as unknown as DocumentNode<GetFacetValuesQuery, GetFacetValuesQueryVariables>;
+} as unknown as DocumentNode<GetFacetWithFacetValuesQuery, GetFacetWithFacetValuesQueryVariables>;
 export const GetCollectionProductsDocument = {
     kind: 'Document',
     definitions: [
@@ -33017,6 +33020,174 @@ export const GetFacetWithValuesDocument = {
         },
     ],
 } as unknown as DocumentNode<GetFacetWithValuesQuery, GetFacetWithValuesQueryVariables>;
+export const GetFacetValuesDocument = {
+    kind: 'Document',
+    definitions: [
+        {
+            kind: 'OperationDefinition',
+            operation: 'query',
+            name: { kind: 'Name', value: 'GetFacetValues' },
+            variableDefinitions: [
+                {
+                    kind: 'VariableDefinition',
+                    variable: { kind: 'Variable', name: { kind: 'Name', value: 'options' } },
+                    type: { kind: 'NamedType', name: { kind: 'Name', value: 'FacetValueListOptions' } },
+                },
+            ],
+            selectionSet: {
+                kind: 'SelectionSet',
+                selections: [
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'facetValues' },
+                        arguments: [
+                            {
+                                kind: 'Argument',
+                                name: { kind: 'Name', value: 'options' },
+                                value: { kind: 'Variable', name: { kind: 'Name', value: 'options' } },
+                            },
+                        ],
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                {
+                                    kind: 'Field',
+                                    name: { kind: 'Name', value: 'items' },
+                                    selectionSet: {
+                                        kind: 'SelectionSet',
+                                        selections: [
+                                            {
+                                                kind: 'FragmentSpread',
+                                                name: { kind: 'Name', value: 'FacetValue' },
+                                            },
+                                        ],
+                                    },
+                                },
+                                { kind: 'Field', name: { kind: 'Name', value: 'totalItems' } },
+                            ],
+                        },
+                    },
+                ],
+            },
+        },
+        {
+            kind: 'FragmentDefinition',
+            name: { kind: 'Name', value: 'FacetValue' },
+            typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'FacetValue' } },
+            selectionSet: {
+                kind: 'SelectionSet',
+                selections: [
+                    { kind: 'Field', name: { kind: 'Name', value: 'id' } },
+                    { kind: 'Field', name: { kind: 'Name', value: 'languageCode' } },
+                    { kind: 'Field', name: { kind: 'Name', value: 'code' } },
+                    { kind: 'Field', name: { kind: 'Name', value: 'name' } },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'translations' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'id' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'languageCode' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'name' } },
+                            ],
+                        },
+                    },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'facet' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'id' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'name' } },
+                            ],
+                        },
+                    },
+                ],
+            },
+        },
+    ],
+} as unknown as DocumentNode<GetFacetValuesQuery, GetFacetValuesQueryVariables>;
+export const GetFacetValueDocument = {
+    kind: 'Document',
+    definitions: [
+        {
+            kind: 'OperationDefinition',
+            operation: 'query',
+            name: { kind: 'Name', value: 'GetFacetValue' },
+            variableDefinitions: [
+                {
+                    kind: 'VariableDefinition',
+                    variable: { kind: 'Variable', name: { kind: 'Name', value: 'id' } },
+                    type: {
+                        kind: 'NonNullType',
+                        type: { kind: 'NamedType', name: { kind: 'Name', value: 'ID' } },
+                    },
+                },
+            ],
+            selectionSet: {
+                kind: 'SelectionSet',
+                selections: [
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'facetValue' },
+                        arguments: [
+                            {
+                                kind: 'Argument',
+                                name: { kind: 'Name', value: 'id' },
+                                value: { kind: 'Variable', name: { kind: 'Name', value: 'id' } },
+                            },
+                        ],
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'FragmentSpread', name: { kind: 'Name', value: 'FacetValue' } },
+                            ],
+                        },
+                    },
+                ],
+            },
+        },
+        {
+            kind: 'FragmentDefinition',
+            name: { kind: 'Name', value: 'FacetValue' },
+            typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'FacetValue' } },
+            selectionSet: {
+                kind: 'SelectionSet',
+                selections: [
+                    { kind: 'Field', name: { kind: 'Name', value: 'id' } },
+                    { kind: 'Field', name: { kind: 'Name', value: 'languageCode' } },
+                    { kind: 'Field', name: { kind: 'Name', value: 'code' } },
+                    { kind: 'Field', name: { kind: 'Name', value: 'name' } },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'translations' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'id' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'languageCode' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'name' } },
+                            ],
+                        },
+                    },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'facet' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'id' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'name' } },
+                            ],
+                        },
+                    },
+                ],
+            },
+        },
+    ],
+} as unknown as DocumentNode<GetFacetValueQuery, GetFacetValueQueryVariables>;
 export const GetPromotionDocument = {
     kind: 'Document',
     definitions: [

+ 22 - 0
packages/core/e2e/graphql/shared-definitions.ts

@@ -9,6 +9,7 @@ import {
     CURRENT_USER_FRAGMENT,
     CUSTOMER_FRAGMENT,
     CUSTOMER_GROUP_FRAGMENT,
+    FACET_VALUE_FRAGMENT,
     FACET_WITH_VALUES_FRAGMENT,
     FULFILLMENT_FRAGMENT,
     GLOBAL_SETTINGS_FRAGMENT,
@@ -1064,6 +1065,27 @@ export const GET_FACET_WITH_VALUES = gql`
     ${FACET_WITH_VALUES_FRAGMENT}
 `;
 
+export const GET_FACET_VALUES = gql`
+    query GetFacetValues($options: FacetValueListOptions) {
+        facetValues(options: $options) {
+            items {
+                ...FacetValue
+            }
+            totalItems
+        }
+    }
+    ${FACET_VALUE_FRAGMENT}
+`;
+
+export const GET_FACET_VALUE = gql`
+    query GetFacetValue($id: ID!) {
+        facetValue(id: $id) {
+            ...FacetValue
+        }
+    }
+    ${FACET_VALUE_FRAGMENT}
+`;
+
 export const GET_PROMOTION = gql`
     query GetPromotion($id: ID!) {
         promotion(id: $id) {

+ 12 - 2
packages/core/src/api/resolvers/admin/facet.resolver.ts

@@ -13,17 +13,18 @@ import {
     Permission,
     QueryFacetArgs,
     QueryFacetsArgs,
+    QueryFacetValueArgs,
     QueryFacetValuesArgs,
     RemoveFacetFromChannelResult,
 } from '@vendure/common/lib/generated-types';
 import { PaginatedList } from '@vendure/common/lib/shared-types';
 
-import { EntityNotFoundError } from '../../../common/error/errors';
 import { ErrorResultUnion } from '../../../common/error/error-result';
+import { EntityNotFoundError } from '../../../common/error/errors';
 import { Translated } from '../../../common/types/locale-types';
 import { ConfigService } from '../../../config/config.service';
-import { Facet } from '../../../entity/facet/facet.entity';
 import { FacetValue } from '../../../entity/facet-value/facet-value.entity';
+import { Facet } from '../../../entity/facet/facet.entity';
 import { FacetValueService } from '../../../service/services/facet-value.service';
 import { FacetService } from '../../../service/services/facet.service';
 import { RequestContext } from '../../common/request-context';
@@ -60,6 +61,15 @@ export class FacetResolver {
         return this.facetService.findOne(ctx, args.id, relations);
     }
 
+    @Query()
+    @Allow(Permission.ReadCatalog, Permission.ReadProduct, Permission.ReadFacet)
+    facetValue(
+        @Ctx() ctx: RequestContext,
+        @Args() args: QueryFacetValueArgs,
+    ): Promise<Translated<FacetValue> | undefined> {
+        return this.facetValueService.findOne(ctx, args.id);
+    }
+
     @Query()
     @Allow(Permission.ReadCatalog, Permission.ReadProduct, Permission.ReadFacet)
     facetValues(

+ 1 - 0
packages/core/src/api/schema/admin-api/facet.api.graphql

@@ -2,6 +2,7 @@ type Query {
     facets(options: FacetListOptions): FacetList!
     facet(id: ID!): Facet
     facetValues(options: FacetValueListOptions): FacetValueList!
+    facetValue(id: ID!): FacetValue
 }
 
 type Mutation {