From 6e207af179731c32418e2708c334d2a7a5a98e6d Mon Sep 17 00:00:00 2001 From: Carlos Cortizas <97907068+CarlosCortizasCT@users.noreply.github.com> Date: Wed, 14 Aug 2024 15:54:28 +0200 Subject: [PATCH] New `ProductProjection` model (#631) * feat: new product-projection model * refactor: readme included * fix: apply review feedback --- .github/CODEOWNERS | 1 + models/product-projection/LICENSE | 21 + models/product-projection/README.md | 37 ++ models/product-projection/package.json | 33 ++ models/product-projection/src/builder.spec.ts | 412 ++++++++++++++++++ models/product-projection/src/builder.ts | 15 + models/product-projection/src/generator.ts | 36 ++ models/product-projection/src/index.ts | 4 + .../happy-cow-milk-product-projection.ts | 32 ++ .../product-projection/src/presets/index.ts | 5 + models/product-projection/src/transformers.ts | 178 ++++++++ models/product-projection/src/types.ts | 73 ++++ models/product/package.json | 1 - pnpm-lock.yaml | 59 ++- 14 files changed, 886 insertions(+), 21 deletions(-) create mode 100644 models/product-projection/LICENSE create mode 100644 models/product-projection/README.md create mode 100644 models/product-projection/package.json create mode 100644 models/product-projection/src/builder.spec.ts create mode 100644 models/product-projection/src/builder.ts create mode 100644 models/product-projection/src/generator.ts create mode 100644 models/product-projection/src/index.ts create mode 100644 models/product-projection/src/presets/happy-cow-milk-product-projection.ts create mode 100644 models/product-projection/src/presets/index.ts create mode 100644 models/product-projection/src/transformers.ts create mode 100644 models/product-projection/src/types.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 018254393..787b42a84 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -38,6 +38,7 @@ /models/payment @commercetools/checkout-team-fe /models/product @commercetools/pacman-team-fe /models/product-discount @commercetools/priceless-team-fe +/models/product-projection @commercetools/pacman-team-fe /models/product-selection @commercetools/context-team-fe /models/product-type @commercetools/pacman-team-fe /models/project @commercetools/shield-team-fe diff --git a/models/product-projection/LICENSE b/models/product-projection/LICENSE new file mode 100644 index 000000000..e113013cb --- /dev/null +++ b/models/product-projection/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) commercetools GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/models/product-projection/README.md b/models/product-projection/README.md new file mode 100644 index 000000000..c5c5fdaf7 --- /dev/null +++ b/models/product-projection/README.md @@ -0,0 +1,37 @@ +# @commercetools-test-data/product-projection + +This package provides the data model for the commercetools platform `ProductProjection` type + +https://docs.commercetools.com/api/projects/productProjections + +# Install + +```bash +$ pnpm add -D @commercetools-test-data/product-projection +``` + +# Usage + +```ts +import { + ProductProjection, + type TProductProjection, + type TProductProjectionRest, + type TProductProjectionGraphql, +} from '@commercetools-test-data/product-projection'; + +const productProjection = + ProductProjection.random().build(); + +// For REST entities +const productProjectionRest = + ProductProjection.random().buildRest(); + +// For Graphql entities +const productProjectionGraphql = + ProductProjection.random().buildGraphql(); + +// Presets +const happyCowProductProjection = ProductProjection.presets; +happyCowMilkProductProjection().build(); +``` diff --git a/models/product-projection/package.json b/models/product-projection/package.json new file mode 100644 index 000000000..877189518 --- /dev/null +++ b/models/product-projection/package.json @@ -0,0 +1,33 @@ +{ + "name": "@commercetools-test-data/product-projection", + "version": "10.0.0", + "description": "Data model for the commercetools platform `ProductProjection` type", + "bugs": "https://github.com/commercetools/test-data/issues", + "repository": { + "type": "git", + "url": "https://github.com/commercetools/test-data.git", + "directory": "models/product" + }, + "keywords": ["javascript", "typescript", "test-data"], + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "main": "dist/commercetools-test-data-product-projection.cjs.js", + "module": "dist/commercetools-test-data-product-projection.esm.js", + "files": ["dist", "package.json", "LICENSE", "README.md"], + "dependencies": { + "@babel/runtime": "^7.17.9", + "@babel/runtime-corejs3": "^7.17.9", + "@commercetools-test-data/category": "10.0.0", + "@commercetools-test-data/commons": "10.0.0", + "@commercetools-test-data/core": "10.0.0", + "@commercetools-test-data/product": "10.0.0", + "@commercetools-test-data/product-type": "10.0.0", + "@commercetools-test-data/state": "10.0.0", + "@commercetools-test-data/tax-category": "10.0.0", + "@commercetools-test-data/utils": "10.0.0", + "@commercetools/platform-sdk": "^7.0.0", + "@faker-js/faker": "^8.0.0" + } +} diff --git a/models/product-projection/src/builder.spec.ts b/models/product-projection/src/builder.spec.ts new file mode 100644 index 000000000..709e044ec --- /dev/null +++ b/models/product-projection/src/builder.spec.ts @@ -0,0 +1,412 @@ +/* eslint-disable jest/no-disabled-tests */ +/* eslint-disable jest/valid-title */ +import { Category } from '@commercetools-test-data/category'; +import { LocalizedString, Reference } from '@commercetools-test-data/commons'; +import { createBuilderSpec } from '@commercetools-test-data/core/test-utils'; +import { ProductVariant } from '@commercetools-test-data/product'; +import { ProductType } from '@commercetools-test-data/product-type'; +import { + TProductProjection, + TProductProjectionGraphql, + TProductProjectionRest, +} from './types'; +import * as ProductProjection from './index'; + +describe('builder', () => { + const expectedGeneralLocalizedString = expect.objectContaining({ + de: expect.any(String), + en: expect.any(String), + fr: expect.any(String), + }); + const expectedGeneralLocalizedField = expect.arrayContaining([ + expect.objectContaining({ + locale: 'en', + value: expect.any(String), + __typename: 'LocalizedString', + }), + ]); + + it( + ...createBuilderSpec( + 'default', + ProductProjection.random(), + expect.objectContaining({ + id: expect.any(String), + version: expect.any(Number), + key: expect.any(String), + productType: expect.objectContaining({ + id: expect.any(String), + key: expect.any(String), + version: expect.any(Number), + createdAt: expect.any(String), + createdBy: expect.objectContaining({ + customer: expect.objectContaining({ typeId: 'customer' }), + }), + lastModifiedAt: expect.any(String), + lastModifiedBy: expect.objectContaining({ + customer: expect.objectContaining({ typeId: 'customer' }), + }), + name: expect.any(String), + description: expect.any(String), + attributes: expect.arrayContaining([ + expect.objectContaining({ + type: expect.objectContaining({ name: expect.any(String) }), + name: expect.any(String), + label: expect.objectContaining({ + de: expect.any(String), + en: expect.any(String), + fr: expect.any(String), + }), + isRequired: expect.any(Boolean), + attributeConstraint: expect.any(String), + inputTip: expect.objectContaining({ + de: expect.any(String), + en: expect.any(String), + fr: expect.any(String), + }), + inputHint: expect.any(String), + isSearchable: expect.any(Boolean), + }), + ]), + }), + name: expectedGeneralLocalizedString, + description: expectedGeneralLocalizedString, + slug: expectedGeneralLocalizedString, + categories: [], + categoryOrderHints: null, + metaTitle: null, + metaDescription: null, + metaKeywords: null, + searchKeywords: [], + hasStagedChanges: expect.any(Boolean), + published: expect.any(Boolean), + masterVariant: expect.objectContaining({ + key: expect.any(String), + sku: expect.any(String), + prices: expect.arrayContaining([ + expect.objectContaining({ + value: expect.any(Object), + }), + ]), + price: null, + images: expect.arrayContaining([ + expect.objectContaining({ + url: expect.any(String), + }), + ]), + attributes: expect.arrayContaining([ + expect.objectContaining({ + name: expect.any(String), + }), + ]), + assets: expect.arrayContaining([]), + availability: null, + isMatchingVariant: expect.any(Boolean), + scopedPrice: null, + scopedPriceDiscounted: null, + }), + variants: [], + taxCategory: null, + state: null, + createdAt: expect.any(String), + lastModifiedAt: expect.any(String), + reviewRatingStatistics: null, + priceMode: null, + }) + ) + ); + + it( + ...createBuilderSpec( + 'rest', + ProductProjection.random(), + expect.objectContaining({ + id: expect.any(String), + version: expect.any(Number), + key: expect.any(String), + productType: expect.objectContaining({ + id: expect.any(String), + key: expect.any(String), + version: expect.any(Number), + createdAt: expect.any(String), + createdBy: expect.objectContaining({ + customer: expect.objectContaining({ typeId: 'customer' }), + }), + lastModifiedAt: expect.any(String), + lastModifiedBy: expect.objectContaining({ + customer: expect.objectContaining({ typeId: 'customer' }), + }), + name: expect.any(String), + description: expect.any(String), + attributes: expect.arrayContaining([ + expect.objectContaining({ + type: expect.objectContaining({ name: expect.any(String) }), + name: expect.any(String), + label: expectedGeneralLocalizedString, + isRequired: expect.any(Boolean), + attributeConstraint: expect.any(String), + inputTip: expectedGeneralLocalizedString, + inputHint: expect.any(String), + isSearchable: expect.any(Boolean), + }), + ]), + }), + name: expectedGeneralLocalizedString, + description: expectedGeneralLocalizedString, + slug: expectedGeneralLocalizedString, + categories: [], + categoryOrderHints: null, + metaTitle: null, + metaDescription: null, + metaKeywords: null, + searchKeywords: [], + hasStagedChanges: expect.any(Boolean), + published: expect.any(Boolean), + masterVariant: expect.objectContaining({ + key: expect.any(String), + sku: expect.any(String), + prices: expect.arrayContaining([ + expect.objectContaining({ + value: expect.any(Object), + }), + ]), + price: null, + images: expect.arrayContaining([ + expect.objectContaining({ + url: expect.any(String), + }), + ]), + attributes: expect.arrayContaining([ + expect.objectContaining({ + name: expect.any(String), + }), + ]), + assets: expect.arrayContaining([]), + availability: null, + isMatchingVariant: expect.any(Boolean), + scopedPrice: null, + scopedPriceDiscounted: null, + }), + variants: [], + taxCategory: null, + state: null, + createdAt: expect.any(String), + lastModifiedAt: expect.any(String), + reviewRatingStatistics: null, + priceMode: null, + }) + ) + ); + + it( + ...createBuilderSpec( + 'graphql', + ProductProjection.random(), + expect.objectContaining({ + id: expect.any(String), + version: expect.any(Number), + key: expect.any(String), + productType: expect.objectContaining({ + __typename: 'ProductTypeDefinition', + id: expect.any(String), + key: expect.any(String), + }), + productTypeRef: expect.objectContaining({ + typeId: 'product-type', + id: expect.any(String), + __typename: 'Reference', + }), + name: expect.any(String), + nameAllLocales: expectedGeneralLocalizedField, + description: expect.any(String), + descriptionAllLocales: expectedGeneralLocalizedField, + slug: expect.any(String), + slugAllLocales: expectedGeneralLocalizedField, + categories: [], + categoryOrderHints: [], + metaTitle: undefined, + metaDescription: undefined, + metaKeywords: undefined, + searchKeywords: [], + hasStagedChanges: expect.any(Boolean), + published: expect.any(Boolean), + masterVariant: expect.objectContaining({ + __typename: 'ProductVariant', + key: expect.any(String), + sku: expect.any(String), + }), + variants: [], + taxCategory: undefined, + state: undefined, + createdAt: expect.any(String), + lastModifiedAt: expect.any(String), + reviewRatingStatistics: undefined, + priceMode: null, + }) + ) + ); + + it('should allow customization', () => { + const productProjectionMock = ProductProjection.presets + .happyCowMilkProductProjection() + .categories([ + Category.random() + .id('category-id') + .name(LocalizedString.presets.empty().en('category-name')), + ]) + .categoryOrderHints({ + 'category-1': '0.4', + }) + .id('happy-cow-milk-id') + .key('happy-cow-milk-key') + .metaKeywords(LocalizedString.presets.empty().en('happy')) + .priceMode('Embedded') + .productType(ProductType.presets.milk().id('product-type-id')) + .reviewRatingStatistics({ + averageRating: 3.12345, + highestRating: 4.9, + lowestRating: 2.1, + count: 25, + ratingsDistribution: {}, + }) + .searchKeywords({ + en: [{ text: 'product search keyword' }], + }) + .state(Reference.presets.stateReference()) + .taxCategory(Reference.presets.taxCategoryReference()) + .variants([ProductVariant.random().key('alternative-variant-key')]) + .version(222) + .buildGraphql(); + + const expectedLocalizedName = expect.arrayContaining([ + expect.objectContaining({ + locale: 'en', + value: 'Happy Cow Milk', + }), + expect.objectContaining({ + locale: 'de', + value: 'Fröhliche Kuhmilch', + }), + ]); + const expectedLocalizedDescription = expect.arrayContaining([ + expect.objectContaining({ + locale: 'en', + value: 'Very happy milk produced by very happy cow!', + }), + expect.objectContaining({ + locale: 'de', + value: 'Sehr glückliche Milch von sehr glücklicher Kuh!', + }), + ]); + + expect(productProjectionMock).toEqual( + expect.objectContaining({ + categories: expect.arrayContaining([ + expect.objectContaining({ + id: 'category-id', + name: 'category-name', + __typename: 'Category', + }), + ]), + categoryOrderHints: expect.arrayContaining([ + { + categoryId: 'category-1', + orderHint: '0.4', + __typename: 'CategoryOrderHint', + }, + ]), + categoriesRef: expect.arrayContaining([ + expect.objectContaining({ + typeId: 'category', + id: 'category-id', + __typename: 'Reference', + }), + ]), + description: 'Very happy milk produced by very happy cow!', + descriptionAllLocales: expectedLocalizedDescription, + hasStagedChanges: false, + id: 'happy-cow-milk-id', + key: 'happy-cow-milk-key', + masterVariant: expect.objectContaining({ + __typename: 'ProductVariant', + key: 'happy-cow-master-variant-key', + sku: 'happy-cow-master-variant-sku', + }), + metaDescription: 'Very happy milk produced by very happy cow!', + metaDescriptionAllLocales: expectedLocalizedDescription, + metaKeywords: 'happy', + metaKeywordsAllLocales: expect.arrayContaining([ + expect.objectContaining({ + locale: 'en', + value: 'happy', + }), + ]), + metaTitle: 'Happy Cow Milk', + metaTitleAllLocales: expectedLocalizedName, + name: 'Happy Cow Milk', + nameAllLocales: expectedLocalizedName, + priceMode: 'Embedded', + productType: expect.objectContaining({ + __typename: 'ProductTypeDefinition', + name: 'Milk Product Type', + }), + productTypeRef: expect.objectContaining({ + typeId: 'product-type', + id: 'product-type-id', + __typename: 'Reference', + }), + published: true, + reviewRatingStatistics: expect.objectContaining({ + averageRating: 3.12345, + highestRating: 4.9, + lowestRating: 2.1, + count: 25, + ratingsDistribution: {}, + __typename: 'ReviewRatingStatistics', + }), + searchKeywords: expect.arrayContaining([ + expect.objectContaining({ + locale: 'en', + searchKeywords: [ + { + text: 'product search keyword', + suggestTokenizer: undefined, + }, + ], + __typename: 'SearchKeywordsProductSearch', + }), + ]), + slug: 'happy-cow-milk-slug', + slugAllLocales: expect.arrayContaining([ + expect.objectContaining({ + locale: 'en', + value: 'happy-cow-milk-slug', + }), + ]), + state: expect.objectContaining({ + id: 'product-type-id', + __typename: 'State', + }), + stateRef: expect.objectContaining({ + typeId: 'state', + __typename: 'Reference', + }), + taxCategory: expect.objectContaining({ + id: 'product-type-id', + __typename: 'TaxCategory', + }), + taxCategoryRef: expect.objectContaining({ + typeId: 'tax-category', + __typename: 'Reference', + }), + variants: expect.arrayContaining([ + expect.objectContaining({ + key: 'alternative-variant-key', + __typename: 'ProductVariant', + }), + ]), + version: 222, + }) + ); + }); +}); diff --git a/models/product-projection/src/builder.ts b/models/product-projection/src/builder.ts new file mode 100644 index 000000000..09cd3697f --- /dev/null +++ b/models/product-projection/src/builder.ts @@ -0,0 +1,15 @@ +import { Builder } from '@commercetools-test-data/core'; +import generator from './generator'; +import transformers from './transformers'; +import type { + TProductProjection, + TCreateProductProjectionBuilder, +} from './types'; + +const Model: TCreateProductProjectionBuilder = () => + Builder({ + generator, + transformers, + }); + +export default Model; diff --git a/models/product-projection/src/generator.ts b/models/product-projection/src/generator.ts new file mode 100644 index 000000000..4f80eb2ed --- /dev/null +++ b/models/product-projection/src/generator.ts @@ -0,0 +1,36 @@ +import { LocalizedString } from '@commercetools-test-data/commons'; +import { Generator, fake, sequence } from '@commercetools-test-data/core'; +import { ProductVariant } from '@commercetools-test-data/product'; +import { ProductType } from '@commercetools-test-data/product-type'; +import { createRelatedDates } from '@commercetools-test-data/utils'; +import { TProductProjection } from './types'; + +const [getOlderDate, getNewerDate] = createRelatedDates(); + +export default Generator({ + fields: { + id: fake((f) => f.string.uuid()), + key: fake((f) => f.lorem.words()), + version: sequence(), + createdAt: fake(getOlderDate), + lastModifiedAt: fake(getNewerDate), + productType: fake(() => ProductType.random()), + name: fake(() => LocalizedString.random()), + description: fake(() => LocalizedString.random()), + slug: fake(() => LocalizedString.presets.ofSlugs()), + categories: [], + categoryOrderHints: null, + metaTitle: null, + metaDescription: null, + metaKeywords: null, + searchKeywords: [], + hasStagedChanges: fake((f) => f.datatype.boolean()), + published: fake((f) => f.datatype.boolean()), + masterVariant: fake(() => ProductVariant.random()), + variants: [], + taxCategory: null, + state: null, + reviewRatingStatistics: null, + priceMode: null, + }, +}); diff --git a/models/product-projection/src/index.ts b/models/product-projection/src/index.ts new file mode 100644 index 000000000..b19319eb5 --- /dev/null +++ b/models/product-projection/src/index.ts @@ -0,0 +1,4 @@ +export { default as random } from './builder'; +export { default as presets } from './presets'; + +export * from './types'; diff --git a/models/product-projection/src/presets/happy-cow-milk-product-projection.ts b/models/product-projection/src/presets/happy-cow-milk-product-projection.ts new file mode 100644 index 000000000..c95d79b3a --- /dev/null +++ b/models/product-projection/src/presets/happy-cow-milk-product-projection.ts @@ -0,0 +1,32 @@ +import { LocalizedString } from '@commercetools-test-data/commons'; +import { ProductVariant } from '@commercetools-test-data/product'; +import { ProductType } from '@commercetools-test-data/product-type'; +import ProductProjection from '../builder'; + +const happyCowMilk = () => { + const productName = LocalizedString.presets + .empty() + .en('Happy Cow Milk') + .de('Fröhliche Kuhmilch'); + + const productDescription = LocalizedString.presets + .empty() + .en('Very happy milk produced by very happy cow!') + .de('Sehr glückliche Milch von sehr glücklicher Kuh!'); + + const slug = LocalizedString.presets.empty().en('happy-cow-milk-slug'); + + return ProductProjection() + .productType(ProductType.presets.milk()) + .slug(slug) + .key('happy-cow-milk-key') + .name(productName) + .description(productDescription) + .metaTitle(productName) + .metaDescription(productDescription) + .masterVariant(ProductVariant.presets.happyCowMilkMasterVariant()) + .published(true) + .hasStagedChanges(false); +}; + +export default happyCowMilk; diff --git a/models/product-projection/src/presets/index.ts b/models/product-projection/src/presets/index.ts new file mode 100644 index 000000000..aa495b374 --- /dev/null +++ b/models/product-projection/src/presets/index.ts @@ -0,0 +1,5 @@ +import happyCowMilkProductProjection from './happy-cow-milk-product-projection'; + +const presets = { happyCowMilkProductProjection }; + +export default presets; diff --git a/models/product-projection/src/transformers.ts b/models/product-projection/src/transformers.ts new file mode 100644 index 000000000..602dd518c --- /dev/null +++ b/models/product-projection/src/transformers.ts @@ -0,0 +1,178 @@ +import { + LocalizedString, + Reference, + type TReferenceGraphql, +} from '@commercetools-test-data/commons'; +import { Transformer } from '@commercetools-test-data/core'; +import { State, TState } from '@commercetools-test-data/state'; +import { + TaxCategory, + TTaxCategory, +} from '@commercetools-test-data/tax-category'; +import type { + TCategoryOrderHintGraphql, + TProductProjection, + TProductProjectionGraphql, + TProductProjectionRest, + TSearchKeywords, +} from './types'; + +const transformers = { + default: Transformer('default', { + buildFields: [ + 'productType', + 'name', + 'description', + 'slug', + 'categories', + 'categoryOrderHints', + 'metaTitle', + 'metaDescription', + 'metaKeywords', + 'searchKeywords', + 'masterVariant', + 'variants', + 'taxCategory', + 'state', + ], + }), + rest: Transformer('rest', { + buildFields: [ + 'productType', + 'name', + 'description', + 'slug', + 'categories', + 'categoryOrderHints', + 'metaTitle', + 'metaDescription', + 'metaKeywords', + 'masterVariant', + 'variants', + 'taxCategory', + 'state', + ], + }), + graphql: Transformer( + 'graphql', + { + buildFields: [ + 'productType', + 'categories', + 'masterVariant', + 'variants', + 'taxCategory', + 'state', + ], + replaceFields: ({ fields }) => { + const nameAllLocales = LocalizedString.toLocalizedField(fields.name)!; + const descriptionAllLocales = LocalizedString.toLocalizedField( + fields.description + ); + const slugAllLocales = LocalizedString.toLocalizedField(fields.slug)!; + const metaTitleAllLocales = LocalizedString.toLocalizedField( + fields.metaTitle + ); + const metaKeywordsAllLocales = LocalizedString.toLocalizedField( + fields.metaKeywords + ); + const metaDescriptionAllLocales = LocalizedString.toLocalizedField( + fields.metaDescription + ); + const productTypeRef = Reference.random() + .id(fields.productType.id) + .typeId('product-type') + .buildGraphql(); + const state = fields.state + ? State.random().id(fields.productType.id).buildGraphql() + : undefined; + const stateRef = fields.state + ? Reference.random() + .id(fields.productType.id) + .typeId('state') + .buildGraphql() + : undefined; + const taxCategory = fields.taxCategory + ? TaxCategory.random() + .id(fields.productType.id) + .buildGraphql() + : undefined; + const taxCategoryRef = fields.taxCategory + ? Reference.random() + .id(fields.productType.id) + .typeId('tax-category') + .buildGraphql() + : undefined; + const categoriesRef = fields.categories.map((category) => ({ + id: category.id, + typeId: 'category' as const, + __typename: 'Reference' as const, + })); + const categoryOrderHints: Array = + Object.entries(fields.categoryOrderHints || {}).map( + ([key, value]) => ({ + categoryId: key, + orderHint: value, + __typename: 'CategoryOrderHint', + }) + ); + const searchKeywords: Array = Object.entries( + fields.searchKeywords || {} + ).map(([locale, searchKeywords]) => ({ + locale, + searchKeywords: searchKeywords.map((searchKeyword) => ({ + text: searchKeyword.text, + suggestTokenizer: searchKeyword.suggestTokenizer, + })), + __typename: 'SearchKeywordsProductSearch', + })); + const reviewRatingStatistics = fields.reviewRatingStatistics + ? { + ...fields.reviewRatingStatistics, + __typename: 'ReviewRatingStatistics' as const, + } + : undefined; + + return { + ...fields, + name: LocalizedString.resolveGraphqlDefaultLocaleValue( + nameAllLocales + )!, + nameAllLocales, + description: LocalizedString.resolveGraphqlDefaultLocaleValue( + descriptionAllLocales + ), + descriptionAllLocales, + slug: LocalizedString.resolveGraphqlDefaultLocaleValue( + slugAllLocales + )!, + slugAllLocales, + metaTitle: + LocalizedString.resolveGraphqlDefaultLocaleValue( + metaTitleAllLocales + ), + metaTitleAllLocales, + metaKeywords: LocalizedString.resolveGraphqlDefaultLocaleValue( + metaKeywordsAllLocales + ), + metaKeywordsAllLocales, + metaDescription: LocalizedString.resolveGraphqlDefaultLocaleValue( + metaDescriptionAllLocales + ), + metaDescriptionAllLocales, + reviewRatingStatistics, + productTypeRef, + state, + stateRef, + taxCategory, + taxCategoryRef, + categoriesRef, + categoryOrderHints, + searchKeywords, + __typename: 'ProductProjection', + }; + }, + } + ), +}; +export default transformers; diff --git a/models/product-projection/src/types.ts b/models/product-projection/src/types.ts new file mode 100644 index 000000000..bd464cd9b --- /dev/null +++ b/models/product-projection/src/types.ts @@ -0,0 +1,73 @@ +import { + ProductProjection, + ReviewRatingStatistics, + SuggestTokenizer, +} from '@commercetools/platform-sdk'; +import { + TLocalizedStringDraftGraphql, + TReferenceGraphql, +} from '@commercetools-test-data/commons'; +import type { TBuilder } from '@commercetools-test-data/core'; +import { TState } from '@commercetools-test-data/state'; +import { TTaxCategory } from '@commercetools-test-data/tax-category'; + +export type TProductProjection = ProductProjection; + +export type TProductProjectionRest = TProductProjection; + +export type TCategoryOrderHintGraphql = { + categoryId: string; + orderHint: string; + __typename: 'CategoryOrderHint'; +}; + +export type TSearchKeyword = { + text: string; + suggestTokenizer?: SuggestTokenizer; +}; + +export type TSearchKeywords = { + locale: string; + searchKeywords: TSearchKeyword[]; +}; + +export type TProductProjectionGraphql = Omit< + TProductProjection, + | 'categoryOrderHints' + | 'description' + | 'metaTitle' + | 'metaDescription' + | 'metaKeywords' + | 'name' + | 'searchKeywords' + | 'slug' + | 'state' + | 'taxCategory' +> & { + categoryOrderHints: TCategoryOrderHintGraphql[]; + categoriesRef: TReferenceGraphql[]; + description?: string; + descriptionAllLocales?: TLocalizedStringDraftGraphql | null; + name: string; + nameAllLocales: TLocalizedStringDraftGraphql; + metaDescription?: string; + metaDescriptionAllLocales?: TLocalizedStringDraftGraphql | null; + metaKeywords?: string; + metaKeywordsAllLocales?: TLocalizedStringDraftGraphql | null; + metaTitle?: string; + metaTitleAllLocales?: TLocalizedStringDraftGraphql | null; + productTypeRef: TReferenceGraphql; + reviewRatingStatistics?: ReviewRatingStatistics & { + __typename: 'ReviewRatingStatistics'; + }; + searchKeywords: TSearchKeywords[]; + slug: string; + slugAllLocales: TLocalizedStringDraftGraphql; + state?: TState; + stateRef?: TReferenceGraphql; + taxCategory?: TTaxCategory | null; + taxCategoryRef?: TReferenceGraphql | null; +}; + +export type TProductProjectionBuilder = TBuilder; +export type TCreateProductProjectionBuilder = () => TProductProjectionBuilder; diff --git a/models/product/package.json b/models/product/package.json index 2ae4d745a..e27807e66 100644 --- a/models/product/package.json +++ b/models/product/package.json @@ -25,7 +25,6 @@ "@commercetools-test-data/commons": "10.0.0", "@commercetools-test-data/core": "10.0.0", "@commercetools-test-data/product-type": "10.0.0", - "@commercetools-test-data/product-variant": "5.11.2", "@commercetools-test-data/tax-category": "10.0.0", "@commercetools-test-data/utils": "10.0.0", "@commercetools/platform-sdk": "^7.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1711359a..4934875fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -748,9 +748,6 @@ importers: '@commercetools-test-data/product-type': specifier: 10.0.0 version: link:../product-type - '@commercetools-test-data/product-variant': - specifier: 5.11.2 - version: 5.11.2 '@commercetools-test-data/tax-category': specifier: 10.0.0 version: link:../tax-category @@ -794,6 +791,45 @@ importers: specifier: ^8.0.0 version: 8.4.1 + models/product-projection: + dependencies: + '@babel/runtime': + specifier: ^7.17.9 + version: 7.24.6 + '@babel/runtime-corejs3': + specifier: ^7.17.9 + version: 7.24.6 + '@commercetools-test-data/category': + specifier: 10.0.0 + version: link:../category + '@commercetools-test-data/commons': + specifier: 10.0.0 + version: link:../commons + '@commercetools-test-data/core': + specifier: 10.0.0 + version: link:../../core + '@commercetools-test-data/product': + specifier: 10.0.0 + version: link:../product + '@commercetools-test-data/product-type': + specifier: 10.0.0 + version: link:../product-type + '@commercetools-test-data/state': + specifier: 10.0.0 + version: link:../state + '@commercetools-test-data/tax-category': + specifier: 10.0.0 + version: link:../tax-category + '@commercetools-test-data/utils': + specifier: 10.0.0 + version: link:../../utils + '@commercetools/platform-sdk': + specifier: ^7.0.0 + version: 7.8.0 + '@faker-js/faker': + specifier: ^8.0.0 + version: 8.4.1 + models/product-selection: dependencies: '@babel/runtime': @@ -2108,10 +2144,6 @@ packages: '@commercetools-test-data/core@5.11.2': resolution: {integrity: sha512-iz++zEBengERwg3REm51RsEFmiUeNPQz1K9K2kZjH1sAkFxOf1ydmpM0Tt4Awmi/OHQ+G2tGKKdJewm8AQyHNg==} - '@commercetools-test-data/product-variant@5.11.2': - resolution: {integrity: sha512-7VT0Iez2bi8fhpqJOzVx/WfmLV+mAXlc5SOxZoTeP1JyUyY07GiujI0ctKAh8Q3/0qzVyJ08RFV1BLtYxLWeKA==} - deprecated: Use the @commercetools-test-data/product package instead - '@commercetools-test-data/utils@5.11.2': resolution: {integrity: sha512-7CU08wvYiQJ+tltvnEDunX/QtVgHimnMtNmwXBicL6/7OsiN/QHtW3pIuN8Sb/OQva6zUPLgOQe/6UbVHB+WpA==} @@ -7603,19 +7635,6 @@ snapshots: '@types/lodash': 4.17.4 lodash: 4.17.21 - '@commercetools-test-data/product-variant@5.11.2': - dependencies: - '@babel/runtime': 7.24.6 - '@babel/runtime-corejs3': 7.24.6 - '@commercetools-test-data/attribute-definition': 5.11.2 - '@commercetools-test-data/commons': 5.11.2 - '@commercetools-test-data/core': 5.11.2 - '@commercetools-test-data/utils': 5.11.2 - '@commercetools/platform-sdk': 4.11.0 - '@faker-js/faker': 8.4.1 - transitivePeerDependencies: - - encoding - '@commercetools-test-data/utils@5.11.2': dependencies: '@babel/runtime': 7.24.6