@graphcommerce/magento-graphql 9.0.0-canary.97 → 9.0.0-canary.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/mesh/attributeValueResolver.ts +31 -0
- package/mesh/customAttributeMetadataV2.ts +68 -0
- package/mesh/customAttributeV2Resolver.ts +47 -0
- package/package.json +6 -5
- package/plugins/meshConfigAttrValue.ts +24 -0
- package/schema/AttributeValueInterface-attribute.graphqls +9 -0
- package/schema/ProductInterface-custom_attribute.graphqls +49 -0
- package/schema-247/Query-customAttributeMetadataV2.graphqls +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 9.0.0-canary.99
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#2416](https://github.com/graphcommerce-org/graphcommerce/pull/2416) [`651eea0`](https://github.com/graphcommerce-org/graphcommerce/commit/651eea0bdda1ed0f46f4c73d7edf52c8c1da5b54) - Created a new field for products: `custom_attribute(attribute_code: "attribute_code")` to retrieve attribute option value labels. This field is only available in Magento 2.4.7 and up. ([@paales](https://github.com/paales))
|
|
8
|
+
|
|
9
|
+
- [#2416](https://github.com/graphcommerce-org/graphcommerce/pull/2416) [`53af256`](https://github.com/graphcommerce-org/graphcommerce/commit/53af25671d3aca7f3daa2dd45ccd2237697e9254) - Added an `attribute`-field to `AttributeValueInterface` to be able to retrieve attribute metadata from the value of an attribute. ([@paales](https://github.com/paales))
|
|
10
|
+
|
|
11
|
+
## 9.0.0-canary.98
|
|
12
|
+
|
|
3
13
|
## 9.0.0-canary.97
|
|
4
14
|
|
|
5
15
|
## 9.0.0-canary.96
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import fragments from '@graphcommerce/graphql/generated/fragments.json'
|
|
2
|
+
import type {
|
|
3
|
+
AttributeValueInterfaceResolvers,
|
|
4
|
+
MeshContext,
|
|
5
|
+
Resolvers,
|
|
6
|
+
} from '@graphcommerce/graphql-mesh'
|
|
7
|
+
import { customAttributeMetadataV2 } from './customAttributeMetadataV2'
|
|
8
|
+
|
|
9
|
+
type AttributeValueResolver = Pick<AttributeValueInterfaceResolvers<MeshContext>, 'attribute'>
|
|
10
|
+
|
|
11
|
+
const attributeValueResolver: AttributeValueResolver = {
|
|
12
|
+
attribute: {
|
|
13
|
+
selectionSet: `{ code }`,
|
|
14
|
+
resolve: async (root, _, context) =>
|
|
15
|
+
root.attribute ??
|
|
16
|
+
(await customAttributeMetadataV2(
|
|
17
|
+
{ attribute_code: root.code, entity_type: 'catalog_product' },
|
|
18
|
+
context,
|
|
19
|
+
)),
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type AttributeValueTypes = NonNullable<
|
|
24
|
+
Awaited<ReturnType<AttributeValueInterfaceResolvers['__resolveType']>>
|
|
25
|
+
>
|
|
26
|
+
const attributeValueTypes = fragments.possibleTypes.AttributeValueInterface as AttributeValueTypes[]
|
|
27
|
+
const resolvers: Resolvers = {}
|
|
28
|
+
attributeValueTypes.forEach((attributeValueType) => {
|
|
29
|
+
if (!resolvers[attributeValueType]) resolvers[attributeValueType] = attributeValueResolver
|
|
30
|
+
})
|
|
31
|
+
export default resolvers
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { MeshContext, CustomAttributeMetadataInterface } from '@graphcommerce/graphql-mesh'
|
|
2
|
+
|
|
3
|
+
export type CustomAttributeInput = { attribute_code: string; entity_type: 'catalog_product' }
|
|
4
|
+
|
|
5
|
+
export async function customAttributeMetadataV2(
|
|
6
|
+
input: CustomAttributeInput,
|
|
7
|
+
context: MeshContext,
|
|
8
|
+
): Promise<CustomAttributeMetadataInterface | null> {
|
|
9
|
+
const cacheKey = `customAttributeMetadata-${input.entity_type}-${input.attribute_code}`
|
|
10
|
+
const cached = await context.cache.get(cacheKey)
|
|
11
|
+
if (cached) return cached
|
|
12
|
+
|
|
13
|
+
if (input.entity_type !== 'catalog_product')
|
|
14
|
+
throw Error('Only catalog_product is supported at this moment')
|
|
15
|
+
|
|
16
|
+
if (
|
|
17
|
+
!('customAttributeMetadataV2' in context.m2.Query) ||
|
|
18
|
+
typeof context.m2.Query.customAttributeMetadataV2 !== 'function'
|
|
19
|
+
)
|
|
20
|
+
throw Error('This field is only available in Magento 2.4.7 and up')
|
|
21
|
+
|
|
22
|
+
const attribute = await context.m2.Query.customAttributeMetadataV2({
|
|
23
|
+
context,
|
|
24
|
+
key: input,
|
|
25
|
+
argsFromKeys: (attributes) => ({ attributes }),
|
|
26
|
+
selectionSet: /* GraphQL */ `
|
|
27
|
+
{
|
|
28
|
+
items {
|
|
29
|
+
__typename
|
|
30
|
+
code
|
|
31
|
+
label
|
|
32
|
+
default_value
|
|
33
|
+
entity_type
|
|
34
|
+
frontend_class
|
|
35
|
+
frontend_input
|
|
36
|
+
is_required
|
|
37
|
+
is_unique
|
|
38
|
+
label
|
|
39
|
+
... on CatalogAttributeMetadata {
|
|
40
|
+
apply_to
|
|
41
|
+
is_comparable
|
|
42
|
+
is_filterable
|
|
43
|
+
is_filterable_in_search
|
|
44
|
+
is_html_allowed_on_front
|
|
45
|
+
is_searchable
|
|
46
|
+
is_used_for_price_rules
|
|
47
|
+
is_used_for_promo_rules
|
|
48
|
+
is_visible_in_advanced_search
|
|
49
|
+
is_visible_on_front
|
|
50
|
+
is_wysiwyg_enabled
|
|
51
|
+
used_in_product_listing
|
|
52
|
+
}
|
|
53
|
+
options {
|
|
54
|
+
label
|
|
55
|
+
is_default
|
|
56
|
+
value
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`,
|
|
61
|
+
valuesFromResults: (res, attributes) =>
|
|
62
|
+
attributes.map((attr) => res.items?.find((v) => v?.code === attr.attribute_code)),
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
// Cache for 1 hour
|
|
66
|
+
await context.cache.set(cacheKey, attribute, { ttl: 60 * 60 })
|
|
67
|
+
return attribute ?? null
|
|
68
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import fragments from '@graphcommerce/graphql/generated/fragments.json'
|
|
2
|
+
import type { MeshContext, ProductInterfaceResolvers, Resolvers } from '@graphcommerce/graphql-mesh'
|
|
3
|
+
import { Kind } from 'graphql'
|
|
4
|
+
import { CustomAttributeInput, customAttributeMetadataV2 } from './customAttributeMetadataV2'
|
|
5
|
+
|
|
6
|
+
type CustomAttributeV2Resolver = Pick<ProductInterfaceResolvers<MeshContext>, 'custom_attributeV2'>
|
|
7
|
+
|
|
8
|
+
const customAttributeV2Resolver: CustomAttributeV2Resolver = {
|
|
9
|
+
custom_attributeV2: {
|
|
10
|
+
selectionSet: (fieldNode) => ({
|
|
11
|
+
kind: Kind.SELECTION_SET,
|
|
12
|
+
selections: (fieldNode.arguments ?? [])
|
|
13
|
+
.map((arg) => arg.value)
|
|
14
|
+
.filter((value) => value.kind === Kind.STRING)
|
|
15
|
+
.map((value) => ({ kind: Kind.FIELD, name: { kind: Kind.NAME, value: value.value } })),
|
|
16
|
+
}),
|
|
17
|
+
resolve: async (root, { attribute_code: code }, context) => {
|
|
18
|
+
const value = String(root[code] ?? '')
|
|
19
|
+
const input: CustomAttributeInput = { attribute_code: code, entity_type: 'catalog_product' }
|
|
20
|
+
const attribute = await customAttributeMetadataV2(input, context)
|
|
21
|
+
|
|
22
|
+
if (!attribute || !value) return null
|
|
23
|
+
|
|
24
|
+
if (
|
|
25
|
+
attribute?.frontend_input &&
|
|
26
|
+
['SELECT', 'MULTISELECT'].includes(attribute.frontend_input)
|
|
27
|
+
) {
|
|
28
|
+
const values = attribute.frontend_input === 'SELECT' ? [value] : value.split(',')
|
|
29
|
+
const selected_options = values.map((v) => {
|
|
30
|
+
const found = attribute.options?.find((o) => o?.value === v || o?.label === v)
|
|
31
|
+
if (!found) return null
|
|
32
|
+
return { ...found, __typename: 'AttributeSelectedOption' }
|
|
33
|
+
})
|
|
34
|
+
return { __typename: 'AttributeSelectedOptions', code, selected_options, attribute }
|
|
35
|
+
}
|
|
36
|
+
return { __typename: 'AttributeValue', code, value, attribute }
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type ProductTypes = NonNullable<Awaited<ReturnType<ProductInterfaceResolvers['__resolveType']>>>
|
|
42
|
+
const productInterfaceTypes = fragments.possibleTypes.ProductInterface as ProductTypes[]
|
|
43
|
+
const resolvers: Resolvers = {}
|
|
44
|
+
productInterfaceTypes.forEach((productType) => {
|
|
45
|
+
if (!resolvers[productType]) resolvers[productType] = customAttributeV2Resolver
|
|
46
|
+
})
|
|
47
|
+
export default resolvers
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/magento-graphql",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "9.0.0-canary.
|
|
5
|
+
"version": "9.0.0-canary.99",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "index.ts",
|
|
8
8
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"@graphcommerce/eslint-config-pwa": "^9.0.0-canary.
|
|
17
|
-
"@graphcommerce/graphql": "^9.0.0-canary.
|
|
18
|
-
"@graphcommerce/prettier-config-pwa": "^9.0.0-canary.
|
|
19
|
-
"@graphcommerce/typescript-config-pwa": "^9.0.0-canary.
|
|
16
|
+
"@graphcommerce/eslint-config-pwa": "^9.0.0-canary.99",
|
|
17
|
+
"@graphcommerce/graphql": "^9.0.0-canary.99",
|
|
18
|
+
"@graphcommerce/prettier-config-pwa": "^9.0.0-canary.99",
|
|
19
|
+
"@graphcommerce/typescript-config-pwa": "^9.0.0-canary.99",
|
|
20
|
+
"graphql": "^16.0.0",
|
|
20
21
|
"next": "*",
|
|
21
22
|
"react": "^18.2.0",
|
|
22
23
|
"react-dom": "^18.2.0"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { meshConfig as meshConfigBase } from '@graphcommerce/graphql-mesh/meshConfig'
|
|
2
|
+
import type { FunctionPlugin, PluginConfig } from '@graphcommerce/next-config'
|
|
3
|
+
|
|
4
|
+
export const config: PluginConfig = {
|
|
5
|
+
module: '@graphcommerce/graphql-mesh/meshConfig',
|
|
6
|
+
type: 'function',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const meshConfig: FunctionPlugin<typeof meshConfigBase> = (
|
|
10
|
+
prev,
|
|
11
|
+
baseConfig,
|
|
12
|
+
graphCommerceConfig,
|
|
13
|
+
) =>
|
|
14
|
+
prev(
|
|
15
|
+
{
|
|
16
|
+
...baseConfig,
|
|
17
|
+
additionalResolvers: [
|
|
18
|
+
...(baseConfig.additionalResolvers ?? []),
|
|
19
|
+
'@graphcommerce/magento-graphql/mesh/customAttributeV2Resolver.ts',
|
|
20
|
+
'@graphcommerce/magento-graphql/mesh/attributeValueResolver.ts',
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
graphCommerceConfig,
|
|
24
|
+
)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
extend interface AttributeValueInterface {
|
|
2
|
+
attribute: CustomAttributeMetadataInterface
|
|
3
|
+
}
|
|
4
|
+
extend type AttributeValue {
|
|
5
|
+
attribute: CustomAttributeMetadataInterface
|
|
6
|
+
}
|
|
7
|
+
extend type AttributeSelectedOptions {
|
|
8
|
+
attribute: CustomAttributeMetadataInterface
|
|
9
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
extend interface ProductInterface {
|
|
2
|
+
"""
|
|
3
|
+
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value.
|
|
4
|
+
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query.
|
|
5
|
+
"""
|
|
6
|
+
custom_attributeV2(attribute_code: String!): AttributeValueInterface
|
|
7
|
+
}
|
|
8
|
+
extend type SimpleProduct {
|
|
9
|
+
"""
|
|
10
|
+
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value.
|
|
11
|
+
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query.
|
|
12
|
+
"""
|
|
13
|
+
custom_attributeV2(attribute_code: String!): AttributeValueInterface
|
|
14
|
+
}
|
|
15
|
+
extend type ConfigurableProduct {
|
|
16
|
+
"""
|
|
17
|
+
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value.
|
|
18
|
+
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query.
|
|
19
|
+
"""
|
|
20
|
+
custom_attributeV2(attribute_code: String!): AttributeValueInterface
|
|
21
|
+
}
|
|
22
|
+
extend type BundleProduct {
|
|
23
|
+
"""
|
|
24
|
+
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value.
|
|
25
|
+
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query.
|
|
26
|
+
"""
|
|
27
|
+
custom_attributeV2(attribute_code: String!): AttributeValueInterface
|
|
28
|
+
}
|
|
29
|
+
extend type DownloadableProduct {
|
|
30
|
+
"""
|
|
31
|
+
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value.
|
|
32
|
+
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query.
|
|
33
|
+
"""
|
|
34
|
+
custom_attributeV2(attribute_code: String!): AttributeValueInterface
|
|
35
|
+
}
|
|
36
|
+
extend type VirtualProduct {
|
|
37
|
+
"""
|
|
38
|
+
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value.
|
|
39
|
+
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query.
|
|
40
|
+
"""
|
|
41
|
+
custom_attributeV2(attribute_code: String!): AttributeValueInterface
|
|
42
|
+
}
|
|
43
|
+
extend type GroupedProduct {
|
|
44
|
+
"""
|
|
45
|
+
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value.
|
|
46
|
+
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query.
|
|
47
|
+
"""
|
|
48
|
+
custom_attributeV2(attribute_code: String!): AttributeValueInterface
|
|
49
|
+
}
|