@reactionary/provider-algolia 0.0.59 → 0.0.61
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/README.md +39 -2
- package/core/initialize.js +4 -4
- package/index.js +1 -1
- package/package.json +2 -2
- package/providers/index.js +2 -0
- package/providers/product-search.provider.js +132 -0
- package/schema/capabilities.schema.js +1 -1
- package/schema/index.js +3 -0
- package/schema/search.schema.js +3 -3
- package/src/index.d.ts +1 -1
- package/src/providers/index.d.ts +2 -0
- package/src/providers/product-search.provider.d.ts +40 -0
- package/src/schema/capabilities.schema.d.ts +1 -1
- package/src/schema/index.d.ts +3 -0
- package/src/schema/search.schema.d.ts +53 -12
- package/providers/search.provider.js +0 -78
- package/src/providers/search.provider.d.ts +0 -9
package/README.md
CHANGED
|
@@ -1,6 +1,43 @@
|
|
|
1
|
-
# provider
|
|
1
|
+
# Algolia provider for Reactionary
|
|
2
|
+
|
|
3
|
+
## Supports
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
| Feature | Support | Notes |
|
|
7
|
+
| ----------- | ----------- | --------- |
|
|
8
|
+
| product | Full | |
|
|
9
|
+
| productSearch | Full | |
|
|
10
|
+
| identity | N/A | |
|
|
11
|
+
| cart | N/A | |
|
|
12
|
+
| checkout | N/A | |
|
|
13
|
+
| order | N/A | Possibly later |
|
|
14
|
+
| inventory | N/A | |
|
|
15
|
+
| price | N/A | |
|
|
16
|
+
| category | N/A | Possibly later |
|
|
17
|
+
| store | N/A | Possibly later |
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
## Notes
|
|
21
|
+
The expected Algolia schema must contain at least these fields
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
objectID: string;
|
|
26
|
+
slug:string;
|
|
27
|
+
name: string;
|
|
28
|
+
variants: [
|
|
29
|
+
{
|
|
30
|
+
variantID: string;
|
|
31
|
+
image: string;
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
You can have more, for use with facets, and additional searchable fields, but these must be in the index, and constitutes what we are expecting to get back.
|
|
38
|
+
|
|
39
|
+
The `objectID` corrosponds to your productIdentifier, and `variantID` should match your SKU
|
|
2
40
|
|
|
3
|
-
This library was generated with [Nx](https://nx.dev).
|
|
4
41
|
|
|
5
42
|
## Building
|
|
6
43
|
|
package/core/initialize.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ProductSchema } from "@reactionary/core";
|
|
1
|
+
import { ProductSchema, ProductSearchResultItemSchema } from "@reactionary/core";
|
|
2
2
|
import { AlgoliaProductProvider } from "../providers/product.provider.js";
|
|
3
|
-
import { AlgoliaSearchProvider } from "../providers/search.provider.js";
|
|
3
|
+
import { AlgoliaSearchProvider } from "../providers/product-search.provider.js";
|
|
4
4
|
import { AlgoliaSearchResultSchema } from "../schema/search.schema.js";
|
|
5
5
|
function withAlgoliaCapabilities(configuration, capabilities) {
|
|
6
6
|
return (cache) => {
|
|
@@ -8,8 +8,8 @@ function withAlgoliaCapabilities(configuration, capabilities) {
|
|
|
8
8
|
if (capabilities.product) {
|
|
9
9
|
client.product = new AlgoliaProductProvider(configuration, ProductSchema, cache);
|
|
10
10
|
}
|
|
11
|
-
if (capabilities.
|
|
12
|
-
client.
|
|
11
|
+
if (capabilities.productSearch) {
|
|
12
|
+
client.productSearch = new AlgoliaSearchProvider(configuration, ProductSearchResultItemSchema, cache);
|
|
13
13
|
}
|
|
14
14
|
return client;
|
|
15
15
|
};
|
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from "./core/initialize.js";
|
|
2
2
|
export * from "./providers/product.provider.js";
|
|
3
|
-
export * from "./providers/search.provider.js";
|
|
3
|
+
export * from "./providers/product-search.provider.js";
|
|
4
4
|
export * from "./schema/configuration.schema.js";
|
|
5
5
|
export * from "./schema/capabilities.schema.js";
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactionary/provider-algolia",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.61",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "src/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@reactionary/core": "0.0.
|
|
7
|
+
"@reactionary/core": "0.0.61",
|
|
8
8
|
"algoliasearch": "^5.23.4",
|
|
9
9
|
"zod": "4.1.9"
|
|
10
10
|
},
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createPaginatedResponseSchema,
|
|
3
|
+
FacetIdentifierSchema,
|
|
4
|
+
FacetValueIdentifierSchema,
|
|
5
|
+
ImageSchema,
|
|
6
|
+
ProductSearchProvider,
|
|
7
|
+
ProductSearchResultFacetSchema,
|
|
8
|
+
ProductSearchResultFacetValueSchema,
|
|
9
|
+
ProductSearchResultItemVariantSchema
|
|
10
|
+
} from "@reactionary/core";
|
|
11
|
+
import { algoliasearch } from "algoliasearch";
|
|
12
|
+
import { AlgoliaSearchIdentifierSchema } from "../schema/search.schema.js";
|
|
13
|
+
class AlgoliaSearchProvider extends ProductSearchProvider {
|
|
14
|
+
constructor(config, schema, cache) {
|
|
15
|
+
super(schema, cache);
|
|
16
|
+
this.config = config;
|
|
17
|
+
}
|
|
18
|
+
async queryByTerm(payload, reqCtx) {
|
|
19
|
+
const client = algoliasearch(this.config.appId, this.config.apiKey);
|
|
20
|
+
const remote = await client.search({
|
|
21
|
+
requests: [
|
|
22
|
+
{
|
|
23
|
+
indexName: this.config.indexName,
|
|
24
|
+
query: payload.search.term,
|
|
25
|
+
page: payload.search.paginationOptions.pageNumber - 1,
|
|
26
|
+
hitsPerPage: payload.search.paginationOptions.pageSize,
|
|
27
|
+
facets: ["*"],
|
|
28
|
+
analytics: true,
|
|
29
|
+
clickAnalytics: true,
|
|
30
|
+
facetFilters: payload.search.facets.map(
|
|
31
|
+
(x) => `${encodeURIComponent(x.facet.key)}:${x.key}`
|
|
32
|
+
),
|
|
33
|
+
filters: (payload.search.filters || []).map((x) => `${encodeURIComponent(x)}`).join(" AND ")
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
});
|
|
37
|
+
const input = remote.results[0];
|
|
38
|
+
const identifier = AlgoliaSearchIdentifierSchema.parse({
|
|
39
|
+
...payload.search,
|
|
40
|
+
index: input.index,
|
|
41
|
+
key: input.queryID
|
|
42
|
+
});
|
|
43
|
+
const result = this.parsePaginatedResult(input, reqCtx);
|
|
44
|
+
result.identifier = identifier;
|
|
45
|
+
for (const selectedFacet of payload.search.facets) {
|
|
46
|
+
const facet = result.facets.find((f) => f.identifier.key === selectedFacet.facet.key);
|
|
47
|
+
if (facet) {
|
|
48
|
+
const value = facet.values.find((v) => v.identifier.key === selectedFacet.key);
|
|
49
|
+
if (value) {
|
|
50
|
+
value.active = true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
result.meta = {
|
|
55
|
+
cache: { hit: false, key: "" },
|
|
56
|
+
placeholder: false
|
|
57
|
+
};
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
parseSingle(body, reqCtx) {
|
|
61
|
+
const product = this.newModel();
|
|
62
|
+
product.identifier = { key: body.objectID };
|
|
63
|
+
product.name = body.name || body.objectID;
|
|
64
|
+
product.slug = body.slug || body.objectID;
|
|
65
|
+
product.variants = [...body.variants || []].map((variant) => this.parseVariant(variant, body, reqCtx));
|
|
66
|
+
return this.assert(product);
|
|
67
|
+
}
|
|
68
|
+
parseVariant(variant, product, reqCtx) {
|
|
69
|
+
const result = ProductSearchResultItemVariantSchema.parse({
|
|
70
|
+
variant: {
|
|
71
|
+
sku: variant.variantID
|
|
72
|
+
},
|
|
73
|
+
image: ImageSchema.parse({
|
|
74
|
+
sourceUrl: variant.image,
|
|
75
|
+
altText: product.name || ""
|
|
76
|
+
})
|
|
77
|
+
});
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
parsePaginatedResult(body, reqCtx) {
|
|
81
|
+
const items = body.hits.map((hit) => this.parseSingle(hit, reqCtx));
|
|
82
|
+
const facets = [];
|
|
83
|
+
for (const id in body.facets) {
|
|
84
|
+
const f = body.facets[id];
|
|
85
|
+
const facetId = FacetIdentifierSchema.parse({
|
|
86
|
+
key: id
|
|
87
|
+
});
|
|
88
|
+
const facet = this.parseFacet(facetId, f, reqCtx);
|
|
89
|
+
facets.push(facet);
|
|
90
|
+
}
|
|
91
|
+
const result = createPaginatedResponseSchema(this.schema).parse({
|
|
92
|
+
meta: {
|
|
93
|
+
cache: { hit: false, key: "unknown" },
|
|
94
|
+
placeholder: false
|
|
95
|
+
},
|
|
96
|
+
pageNumber: (body.page || 0) + 1,
|
|
97
|
+
pageSize: body.hitsPerPage,
|
|
98
|
+
totalCount: body.nbHits,
|
|
99
|
+
totalPages: body.nbPages,
|
|
100
|
+
items
|
|
101
|
+
});
|
|
102
|
+
result.facets = facets;
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
parseFacet(facetIdentifier, facetValues, reqCtx) {
|
|
106
|
+
const result = ProductSearchResultFacetSchema.parse({
|
|
107
|
+
identifier: facetIdentifier,
|
|
108
|
+
name: facetIdentifier.key,
|
|
109
|
+
values: []
|
|
110
|
+
});
|
|
111
|
+
for (const vid in facetValues) {
|
|
112
|
+
const fv = facetValues[vid];
|
|
113
|
+
const facetValueIdentifier = FacetValueIdentifierSchema.parse({
|
|
114
|
+
facet: facetIdentifier,
|
|
115
|
+
key: vid
|
|
116
|
+
});
|
|
117
|
+
result.values.push(this.parseFacetValue(facetValueIdentifier, vid, fv, reqCtx));
|
|
118
|
+
}
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
parseFacetValue(facetValueIdentifier, label, count, reqCtx) {
|
|
122
|
+
return ProductSearchResultFacetValueSchema.parse({
|
|
123
|
+
identifier: facetValueIdentifier,
|
|
124
|
+
name: label,
|
|
125
|
+
count,
|
|
126
|
+
active: false
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
export {
|
|
131
|
+
AlgoliaSearchProvider
|
|
132
|
+
};
|
package/schema/index.js
ADDED
package/schema/search.schema.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ProductSearchIdentifierSchema, ProductSearchResultSchema } from "@reactionary/core";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
const AlgoliaSearchIdentifierSchema =
|
|
3
|
+
const AlgoliaSearchIdentifierSchema = ProductSearchIdentifierSchema.extend({
|
|
4
4
|
key: z.string().default(""),
|
|
5
5
|
index: z.string().default("")
|
|
6
6
|
});
|
|
7
|
-
const AlgoliaSearchResultSchema =
|
|
7
|
+
const AlgoliaSearchResultSchema = ProductSearchResultSchema.extend({
|
|
8
8
|
identifier: AlgoliaSearchIdentifierSchema.default(() => AlgoliaSearchIdentifierSchema.parse({}))
|
|
9
9
|
});
|
|
10
10
|
export {
|
package/src/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from './core/initialize.js';
|
|
2
2
|
export * from './providers/product.provider.js';
|
|
3
|
-
export * from './providers/search.provider.js';
|
|
3
|
+
export * from './providers/product-search.provider.js';
|
|
4
4
|
export * from './schema/configuration.schema.js';
|
|
5
5
|
export * from './schema/capabilities.schema.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type Cache, type FacetIdentifier, type FacetValueIdentifier, ProductSearchProvider, type ProductSearchQueryByTerm, type ProductSearchResult, type ProductSearchResultFacet, type ProductSearchResultFacetValue, type ProductSearchResultItem, type ProductSearchResultItemVariant, type RequestContext } from '@reactionary/core';
|
|
2
|
+
import { type SearchResponse } from 'algoliasearch';
|
|
3
|
+
import type { z } from 'zod';
|
|
4
|
+
import type { AlgoliaConfiguration } from '../schema/configuration.schema.js';
|
|
5
|
+
interface AlgoliaNativeVariant {
|
|
6
|
+
variantID: string;
|
|
7
|
+
image: string;
|
|
8
|
+
}
|
|
9
|
+
interface AlgoliaNativeRecord {
|
|
10
|
+
objectID: string;
|
|
11
|
+
slug?: string;
|
|
12
|
+
name?: string;
|
|
13
|
+
variants: Array<AlgoliaNativeVariant>;
|
|
14
|
+
}
|
|
15
|
+
export declare class AlgoliaSearchProvider<T extends ProductSearchResultItem = ProductSearchResultItem> extends ProductSearchProvider<T> {
|
|
16
|
+
protected config: AlgoliaConfiguration;
|
|
17
|
+
constructor(config: AlgoliaConfiguration, schema: z.ZodType<T>, cache: Cache);
|
|
18
|
+
queryByTerm(payload: ProductSearchQueryByTerm, reqCtx: RequestContext): Promise<ProductSearchResult>;
|
|
19
|
+
protected parseSingle(body: AlgoliaNativeRecord, reqCtx: RequestContext): T;
|
|
20
|
+
protected parseVariant(variant: AlgoliaNativeVariant, product: AlgoliaNativeRecord, reqCtx: RequestContext): ProductSearchResultItemVariant;
|
|
21
|
+
protected parsePaginatedResult(body: SearchResponse<AlgoliaNativeRecord>, reqCtx: RequestContext): {
|
|
22
|
+
meta: {
|
|
23
|
+
[x: string]: unknown;
|
|
24
|
+
cache: {
|
|
25
|
+
[x: string]: unknown;
|
|
26
|
+
hit: boolean;
|
|
27
|
+
key: string;
|
|
28
|
+
};
|
|
29
|
+
placeholder: boolean;
|
|
30
|
+
};
|
|
31
|
+
pageNumber: number;
|
|
32
|
+
pageSize: number;
|
|
33
|
+
totalCount: number;
|
|
34
|
+
totalPages: number;
|
|
35
|
+
items: T[];
|
|
36
|
+
};
|
|
37
|
+
protected parseFacet(facetIdentifier: FacetIdentifier, facetValues: Record<string, number>, reqCtx: RequestContext): ProductSearchResultFacet;
|
|
38
|
+
protected parseFacetValue(facetValueIdentifier: FacetValueIdentifier, label: string, count: number, reqCtx: RequestContext): ProductSearchResultFacetValue;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
@@ -2,6 +2,6 @@ import type { z } from 'zod';
|
|
|
2
2
|
export declare const AlgoliaCapabilitiesSchema: z.ZodObject<{
|
|
3
3
|
product: z.ZodOptional<z.ZodBoolean>;
|
|
4
4
|
analytics: z.ZodOptional<z.ZodBoolean>;
|
|
5
|
-
|
|
5
|
+
productSearch: z.ZodOptional<z.ZodBoolean>;
|
|
6
6
|
}, z.core.$loose>;
|
|
7
7
|
export type AlgoliaCapabilities = z.infer<typeof AlgoliaCapabilitiesSchema>;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export declare const AlgoliaSearchIdentifierSchema: z.ZodObject<{
|
|
3
3
|
term: z.ZodDefault<z.ZodString>;
|
|
4
|
-
page: z.ZodDefault<z.ZodNumber>;
|
|
5
|
-
pageSize: z.ZodDefault<z.ZodNumber>;
|
|
6
4
|
facets: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
7
5
|
facet: z.ZodNonOptional<z.ZodDefault<z.ZodObject<{
|
|
8
6
|
key: z.ZodNonOptional<z.ZodDefault<z.ZodString>>;
|
|
9
7
|
}, z.core.$loose>>>;
|
|
10
8
|
key: z.ZodNonOptional<z.ZodDefault<z.ZodString>>;
|
|
11
|
-
}, z.core.$
|
|
9
|
+
}, z.core.$strip>>>;
|
|
10
|
+
filters: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
11
|
+
paginationOptions: z.ZodDefault<z.ZodObject<{
|
|
12
|
+
pageNumber: z.ZodDefault<z.ZodNumber>;
|
|
13
|
+
pageSize: z.ZodDefault<z.ZodNumber>;
|
|
14
|
+
}, z.core.$loose>>;
|
|
12
15
|
key: z.ZodDefault<z.ZodString>;
|
|
13
16
|
index: z.ZodDefault<z.ZodString>;
|
|
14
17
|
}, z.core.$loose>;
|
|
@@ -20,15 +23,50 @@ export declare const AlgoliaSearchResultSchema: z.ZodObject<{
|
|
|
20
23
|
}, z.core.$loose>>;
|
|
21
24
|
placeholder: z.ZodDefault<z.ZodBoolean>;
|
|
22
25
|
}, z.core.$loose>>;
|
|
23
|
-
|
|
26
|
+
pageNumber: z.ZodNumber;
|
|
27
|
+
pageSize: z.ZodNumber;
|
|
28
|
+
totalCount: z.ZodNumber;
|
|
29
|
+
totalPages: z.ZodNumber;
|
|
30
|
+
items: z.ZodArray<z.ZodObject<{
|
|
31
|
+
meta: z.ZodDefault<z.ZodObject<{
|
|
32
|
+
cache: z.ZodDefault<z.ZodObject<{
|
|
33
|
+
hit: z.ZodDefault<z.ZodBoolean>;
|
|
34
|
+
key: z.ZodDefault<z.ZodString>;
|
|
35
|
+
}, z.core.$loose>>;
|
|
36
|
+
placeholder: z.ZodDefault<z.ZodBoolean>;
|
|
37
|
+
}, z.core.$loose>>;
|
|
24
38
|
identifier: z.ZodDefault<z.ZodObject<{
|
|
25
39
|
key: z.ZodDefault<z.ZodString>;
|
|
26
40
|
}, z.core.$loose>>;
|
|
27
41
|
name: z.ZodDefault<z.ZodString>;
|
|
28
|
-
image: z.ZodDefault<z.ZodString>;
|
|
29
42
|
slug: z.ZodDefault<z.ZodString>;
|
|
30
|
-
|
|
31
|
-
|
|
43
|
+
variants: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
44
|
+
variant: z.ZodDefault<z.ZodObject<{
|
|
45
|
+
sku: z.ZodNonOptional<z.ZodDefault<z.ZodString>>;
|
|
46
|
+
}, z.core.$loose>>;
|
|
47
|
+
image: z.ZodDefault<z.ZodObject<{
|
|
48
|
+
sourceUrl: z.ZodDefault<z.ZodString>;
|
|
49
|
+
altText: z.ZodDefault<z.ZodString>;
|
|
50
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
51
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
52
|
+
}, z.core.$loose>>;
|
|
53
|
+
options: z.ZodOptional<z.ZodObject<{
|
|
54
|
+
identifier: z.ZodDefault<z.ZodObject<{
|
|
55
|
+
key: z.ZodDefault<z.ZodString>;
|
|
56
|
+
}, z.core.$loose>>;
|
|
57
|
+
name: z.ZodString;
|
|
58
|
+
value: z.ZodDefault<z.ZodObject<{
|
|
59
|
+
identifier: z.ZodDefault<z.ZodObject<{
|
|
60
|
+
option: z.ZodDefault<z.ZodObject<{
|
|
61
|
+
key: z.ZodDefault<z.ZodString>;
|
|
62
|
+
}, z.core.$loose>>;
|
|
63
|
+
key: z.ZodDefault<z.ZodString>;
|
|
64
|
+
}, z.core.$loose>>;
|
|
65
|
+
label: z.ZodString;
|
|
66
|
+
}, z.core.$loose>>;
|
|
67
|
+
}, z.core.$loose>>;
|
|
68
|
+
}, z.core.$loose>>>;
|
|
69
|
+
}, z.core.$loose>>;
|
|
32
70
|
facets: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
33
71
|
identifier: z.ZodDefault<z.ZodObject<{
|
|
34
72
|
key: z.ZodNonOptional<z.ZodDefault<z.ZodString>>;
|
|
@@ -40,7 +78,7 @@ export declare const AlgoliaSearchResultSchema: z.ZodObject<{
|
|
|
40
78
|
key: z.ZodNonOptional<z.ZodDefault<z.ZodString>>;
|
|
41
79
|
}, z.core.$loose>>;
|
|
42
80
|
key: z.ZodDefault<z.ZodString>;
|
|
43
|
-
}, z.core.$
|
|
81
|
+
}, z.core.$strip>>;
|
|
44
82
|
name: z.ZodDefault<z.ZodString>;
|
|
45
83
|
count: z.ZodDefault<z.ZodNumber>;
|
|
46
84
|
active: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -48,17 +86,20 @@ export declare const AlgoliaSearchResultSchema: z.ZodObject<{
|
|
|
48
86
|
}, z.core.$loose>>>;
|
|
49
87
|
identifier: z.ZodDefault<z.ZodObject<{
|
|
50
88
|
term: z.ZodDefault<z.ZodString>;
|
|
51
|
-
page: z.ZodDefault<z.ZodNumber>;
|
|
52
|
-
pageSize: z.ZodDefault<z.ZodNumber>;
|
|
53
89
|
facets: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
54
90
|
facet: z.ZodNonOptional<z.ZodDefault<z.ZodObject<{
|
|
55
91
|
key: z.ZodNonOptional<z.ZodDefault<z.ZodString>>;
|
|
56
92
|
}, z.core.$loose>>>;
|
|
57
93
|
key: z.ZodNonOptional<z.ZodDefault<z.ZodString>>;
|
|
58
|
-
}, z.core.$
|
|
94
|
+
}, z.core.$strip>>>;
|
|
95
|
+
filters: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
96
|
+
paginationOptions: z.ZodDefault<z.ZodObject<{
|
|
97
|
+
pageNumber: z.ZodDefault<z.ZodNumber>;
|
|
98
|
+
pageSize: z.ZodDefault<z.ZodNumber>;
|
|
99
|
+
}, z.core.$loose>>;
|
|
59
100
|
key: z.ZodDefault<z.ZodString>;
|
|
60
101
|
index: z.ZodDefault<z.ZodString>;
|
|
61
102
|
}, z.core.$loose>>;
|
|
62
|
-
}, z.core.$
|
|
103
|
+
}, z.core.$strip>;
|
|
63
104
|
export type AlgoliaSearchResult = z.infer<typeof AlgoliaSearchResultSchema>;
|
|
64
105
|
export type AlgoliaSearchIdentifier = z.infer<typeof AlgoliaSearchIdentifierSchema>;
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
SearchProvider
|
|
3
|
-
} from "@reactionary/core";
|
|
4
|
-
import { algoliasearch } from "algoliasearch";
|
|
5
|
-
class AlgoliaSearchProvider extends SearchProvider {
|
|
6
|
-
constructor(config, schema, cache) {
|
|
7
|
-
super(schema, cache);
|
|
8
|
-
this.config = config;
|
|
9
|
-
}
|
|
10
|
-
async queryByTerm(payload, _reqCtx) {
|
|
11
|
-
const client = algoliasearch(this.config.appId, this.config.apiKey);
|
|
12
|
-
const remote = await client.search({
|
|
13
|
-
requests: [
|
|
14
|
-
{
|
|
15
|
-
indexName: this.config.indexName,
|
|
16
|
-
query: payload.search.term,
|
|
17
|
-
page: payload.search.page,
|
|
18
|
-
hitsPerPage: payload.search.pageSize,
|
|
19
|
-
facets: ["*"],
|
|
20
|
-
analytics: true,
|
|
21
|
-
clickAnalytics: true,
|
|
22
|
-
facetFilters: payload.search.facets.map(
|
|
23
|
-
(x) => `${encodeURIComponent(x.facet.key)}:${x.key}`
|
|
24
|
-
)
|
|
25
|
-
}
|
|
26
|
-
]
|
|
27
|
-
});
|
|
28
|
-
return this.parseSearchResult(remote, payload);
|
|
29
|
-
}
|
|
30
|
-
parseSearchResult(remote, payload) {
|
|
31
|
-
const result = this.newModel();
|
|
32
|
-
const remoteData = remote;
|
|
33
|
-
const remoteProducts = remoteData.results[0];
|
|
34
|
-
for (const id in remoteProducts.facets) {
|
|
35
|
-
const f = remoteProducts.facets[id];
|
|
36
|
-
const facet = {
|
|
37
|
-
identifier: { key: id },
|
|
38
|
-
name: id,
|
|
39
|
-
values: []
|
|
40
|
-
};
|
|
41
|
-
for (const vid in f) {
|
|
42
|
-
const fv = f[vid];
|
|
43
|
-
const isActive = payload.search.facets.find(
|
|
44
|
-
(x) => x.facet.key === id && x.key === vid
|
|
45
|
-
);
|
|
46
|
-
facet.values.push({
|
|
47
|
-
identifier: { key: vid, facet: { key: id } },
|
|
48
|
-
count: fv,
|
|
49
|
-
name: vid,
|
|
50
|
-
active: !!isActive
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
result.facets.push(facet);
|
|
54
|
-
}
|
|
55
|
-
for (const p of remoteProducts.hits) {
|
|
56
|
-
result.products.push({
|
|
57
|
-
identifier: { key: p.objectID },
|
|
58
|
-
slug: p.slug,
|
|
59
|
-
name: p.name,
|
|
60
|
-
image: p.image
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
result.identifier = {
|
|
64
|
-
...payload.search,
|
|
65
|
-
index: remoteProducts.index,
|
|
66
|
-
key: remoteProducts.queryID
|
|
67
|
-
};
|
|
68
|
-
result.pages = remoteProducts.nbPages;
|
|
69
|
-
result.meta = {
|
|
70
|
-
cache: { hit: false, key: payload.search.term },
|
|
71
|
-
placeholder: false
|
|
72
|
-
};
|
|
73
|
-
return this.assert(result);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
export {
|
|
77
|
-
AlgoliaSearchProvider
|
|
78
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { type SearchQueryByTerm, type SearchResult, type RequestContext, type Cache, SearchProvider } from '@reactionary/core';
|
|
2
|
-
import type { z } from 'zod';
|
|
3
|
-
import type { AlgoliaConfiguration } from '../schema/configuration.schema.js';
|
|
4
|
-
export declare class AlgoliaSearchProvider<T extends SearchResult = SearchResult> extends SearchProvider<T> {
|
|
5
|
-
protected config: AlgoliaConfiguration;
|
|
6
|
-
constructor(config: AlgoliaConfiguration, schema: z.ZodType<T>, cache: Cache);
|
|
7
|
-
queryByTerm(payload: SearchQueryByTerm, _reqCtx: RequestContext): Promise<SearchResult>;
|
|
8
|
-
protected parseSearchResult(remote: unknown, payload: SearchQueryByTerm): T;
|
|
9
|
-
}
|