@graphcommerce/algolia-recommend 9.0.0-canary.84

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.
@@ -0,0 +1,74 @@
1
+ input TrendingProductsInput {
2
+ maxRecommendations: Int = 8
3
+
4
+ """
5
+ Minimum score a recommendation must have to be included in the response.
6
+ """
7
+ threshold: Float! = 75
8
+
9
+ """
10
+ Facet attribute. To be used in combination with `facetValue`.
11
+ If specified, only recommendations matching the facet filter will be returned.
12
+ """
13
+ facetName: String!
14
+
15
+ """
16
+ Facet value. To be used in combination with `facetName`.
17
+ If specified, only recommendations matching the facet filter will be returned.
18
+ """
19
+ facetValue: String!
20
+
21
+ """
22
+ One or more keywords to use in a full-text search.
23
+ """
24
+ search: String
25
+
26
+ """
27
+ The product attributes to search for and return.
28
+ """
29
+ filter: ProductAttributeFilterInput
30
+
31
+ """
32
+ When there are no related products, use this fallback query
33
+ """
34
+ fallback: AlgoliaFallbackParams
35
+ }
36
+
37
+ input TrendingFacetValuesInput {
38
+ maxRecommendations: Int = 8
39
+
40
+ """
41
+ Minimum score a recommendation must have to be included in the response.
42
+ """
43
+ threshold: Float! = 75
44
+ """
45
+ Facet attribute for which to retrieve trending facet values.
46
+ """
47
+ facetName: String!
48
+
49
+ """
50
+ One or more keywords to use in a full-text search.
51
+ """
52
+ search: String
53
+
54
+ """
55
+ The product attributes to search for and return.
56
+ """
57
+ filter: ProductAttributeFilterInput
58
+
59
+ """
60
+ When there are no related products, use this fallback query
61
+ """
62
+ fallback: AlgoliaFallbackParams
63
+ }
64
+
65
+ type TrendingFacetValue {
66
+ facetName: String!
67
+ facetValue: String!
68
+ }
69
+
70
+ extend type Query {
71
+ trendingProducts(input: TrendingProductsInput!): [ProductInterface]
72
+
73
+ trendingFacetValues(input: TrendingFacetValuesInput!): [TrendingFacetValue]
74
+ }
@@ -0,0 +1,131 @@
1
+ import yaml from 'js-yaml'
2
+ import { writeFile, readFile } from 'node:fs/promises'
3
+ import { OpenAPIV3 } from 'openapi-types'
4
+ import prettier from 'prettier'
5
+ import conf from '@graphcommerce/prettier-config-pwa'
6
+ import { algoliaSchemaBaseFilter } from '@graphcommerce/algolia-products/scripts/base-schema-filter.mjs'
7
+
8
+ const response = await fetch(
9
+ 'https://raw.githubusercontent.com/algolia/api-clients-automation/main/specs/bundled/recommend.yml',
10
+ )
11
+
12
+ const openApiSchema = yaml.load(await response.text()) as OpenAPIV3.Document
13
+
14
+ const allMethods = [
15
+ OpenAPIV3.HttpMethods.TRACE,
16
+ OpenAPIV3.HttpMethods.POST,
17
+ OpenAPIV3.HttpMethods.PUT,
18
+ OpenAPIV3.HttpMethods.GET,
19
+ OpenAPIV3.HttpMethods.DELETE,
20
+ OpenAPIV3.HttpMethods.PATCH,
21
+ OpenAPIV3.HttpMethods.OPTIONS,
22
+ OpenAPIV3.HttpMethods.HEAD,
23
+ ]
24
+
25
+ const { info, openapi, components, tags, ...rest } = openApiSchema
26
+
27
+ function filterPaths(
28
+ paths: OpenAPIV3.PathsObject,
29
+ allow: Record<string, OpenAPIV3.HttpMethods[]>,
30
+ ): OpenAPIV3.PathsObject {
31
+ const allowedEntries = Object.entries(allow)
32
+
33
+ return Object.fromEntries(
34
+ Object.entries(paths)
35
+ .map(([path, pathItem]) => {
36
+ if (!pathItem) return [path, pathItem]
37
+ const newValue = pathItem
38
+
39
+ const [allowedPath, allowedMethods] =
40
+ allowedEntries.find(([allowedPath]) => allowedPath === path) ?? []
41
+
42
+ if (!allowedPath || !allowedMethods) return [path, undefined]
43
+
44
+ allMethods
45
+ .filter((method) => !allowedMethods.includes(method))
46
+ .forEach((method) => {
47
+ newValue[method] = undefined
48
+ })
49
+
50
+ return [path, newValue]
51
+ })
52
+ .filter(([path, pathItem]) => {
53
+ if (!pathItem) return false
54
+ if (allMethods.every((key) => !pathItem[key])) return false
55
+ return true
56
+ }),
57
+ )
58
+ }
59
+
60
+ function isRef(value: any): value is OpenAPIV3.ReferenceObject {
61
+ return typeof value === 'object' && '$ref' in value
62
+ }
63
+
64
+ const newSchema: OpenAPIV3.Document = {
65
+ openapi,
66
+ info,
67
+ paths: filterPaths(openApiSchema.paths, {
68
+ '/1/indexes/*/recommendations': [OpenAPIV3.HttpMethods.POST],
69
+ }),
70
+ components: {
71
+ ...openApiSchema.components,
72
+ schemas: Object.fromEntries(
73
+ Object.entries(openApiSchema.components?.schemas ?? {}).map(
74
+ ([incomingKey, incomingSchema]) => {
75
+ const [schemaKey, schema] = algoliaSchemaBaseFilter(incomingKey, incomingSchema)
76
+ if (isRef(schema)) return [schemaKey, schema]
77
+
78
+ // Some object have an addition type 'object' which removes all types of the object, we only add known properties here.
79
+ const ref = schema.allOf?.find((item) => isRef(item))
80
+ const obj = schema.allOf?.find((item) => !isRef(item) && item.type === 'object')
81
+ if (ref && obj) {
82
+ return [schemaKey, { ...schema, allOf: [ref satisfies OpenAPIV3.ReferenceObject] }]
83
+ }
84
+
85
+ if (schemaKey === 'recommendedForYouQuery') {
86
+ return [
87
+ schemaKey,
88
+ {
89
+ ...schema,
90
+ oneOf: schema.oneOf?.filter(
91
+ (item) =>
92
+ !isRef(item) || item.$ref !== '#/components/schemas/recommendedForYouQuery',
93
+ ),
94
+ },
95
+ ]
96
+ }
97
+
98
+ if (schemaKey === 'fallbackParams') {
99
+ return [schemaKey, undefined]
100
+ }
101
+
102
+ return [
103
+ schemaKey,
104
+ {
105
+ ...schema,
106
+ properties: schema.properties
107
+ ? {
108
+ ...schema.properties,
109
+ ...(schema?.properties?.fallbackParameters
110
+ ? { fallbackParameters: { $ref: '#/components/schemas/searchParamsObject' } }
111
+ : {}),
112
+ ...(schema?.properties?.queryParameters
113
+ ? { queryParameters: { $ref: '#/components/schemas/searchParamsObject' } }
114
+ : {}),
115
+ }
116
+ : undefined,
117
+ },
118
+ ]
119
+ },
120
+ ),
121
+ ),
122
+ },
123
+ }
124
+
125
+ await writeFile(
126
+ './algolia-recommend-spec.yaml',
127
+ await prettier.format(yaml.dump(newSchema), {
128
+ parser: 'yaml',
129
+ ...conf,
130
+ }),
131
+ )
package/tsconfig.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "exclude": ["**/node_modules", "**/.*/"],
3
+ "include": ["**/*.ts", "**/*.tsx"],
4
+ "extends": "@graphcommerce/typescript-config-pwa/nextjs.json"
5
+ }