/
types.ts
215 lines (200 loc) · 7.47 KB
/
types.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
import { SearchInput as GeneratedSearchInput } from '@vendure/common/lib/generated-types';
import { ID, JsonCompatible } from '@vendure/common/lib/shared-types';
import { SerializedRequestContext } from '../../api/common/request-context';
import { Asset } from '../../entity/asset/asset.entity';
import { SearchStrategy } from './search-strategy/search-strategy';
/**
* @description
* Options which configure the behaviour of the DefaultSearchPlugin
*
* @docsCategory DefaultSearchPlugin
*/
export interface DefaultSearchPluginInitOptions {
/**
* @description
* If set to `true`, the stock status of a ProductVariant (inStock: Boolean) will
* be exposed in the `search` query results. Enabling this option on an existing
* Vendure installation will require a DB migration/synchronization.
*
* @default false.
*/
indexStockStatus?: boolean;
/**
* @description
* If set to `true`, updates to Products, ProductVariants and Collections will not immediately
* trigger an update to the search index. Instead, all these changes will be buffered and will
* only be run via a call to the `runPendingSearchIndexUpdates` mutation in the Admin API.
*
* This is very useful for installations with a large number of ProductVariants and/or
* Collections, as the buffering allows better control over when these expensive jobs are run,
* and also performs optimizations to minimize the amount of work that needs to be performed by
* the worker.
*
* @since 1.3.0
* @default false
*/
bufferUpdates?: boolean;
/**
* @description
* Set a custom search strategy that implements {@link SearchStrategy} or extends an existing search strategy
* such as {@link MysqlSearchStrategy}, {@link PostgresSearchStrategy} or {@link SqliteSearchStrategy}.
*
* @example
* ```ts
* export class MySearchStrategy implements SearchStrategy {
* private readonly minTermLength = 2;
* private connection: TransactionalConnection;
* private options: DefaultSearchPluginInitOptions;
*
* async init(injector: Injector) {
* this.connection = injector.get(TransactionalConnection);
* this.options = injector.get(PLUGIN_INIT_OPTIONS);
* }
*
* async getFacetValueIds(
* ctx: RequestContext,
* input: SearchInput,
* enabledOnly: boolean,
* ): Promise<Map<ID, number>> {
* // ...
* return createFacetIdCountMap(facetValuesResult);
* }
*
* async getCollectionIds(
* ctx: RequestContext,
* input: SearchInput,
* enabledOnly: boolean,
* ): Promise<Map<ID, number>> {
* // ...
* return createCollectionIdCountMap(collectionsResult);
* }
*
* async getSearchResults(
* ctx: RequestContext,
* input: SearchInput,
* enabledOnly: boolean,
* ): Promise<SearchResult[]> {
* const take = input.take || 25;
* const skip = input.skip || 0;
* const sort = input.sort;
* const qb = this.connection
* .getRepository(SearchIndexItem)
* .createQueryBuilder('si')
* .select(this.createMysqlSelect(!!input.groupByProduct));
* // ...
*
* return qb
* .take(take)
* .skip(skip)
* .getRawMany()
* .then(res => res.map(r => mapToSearchResult(r, ctx.channel.currencyCode)));
* }
*
* async getTotalCount(ctx: RequestContext, input: SearchInput, enabledOnly: boolean): Promise<number> {
* const innerQb = this.applyTermAndFilters(
* ctx,
* this.connection
* .getRepository(SearchIndexItem)
* .createQueryBuilder('si')
* .select(this.createMysqlSelect(!!input.groupByProduct)),
* input,
* );
* if (enabledOnly) {
* innerQb.andWhere('si.enabled = :enabled', { enabled: true });
* }
*
* const totalItemsQb = this.connection.rawConnection
* .createQueryBuilder()
* .select('COUNT(*) as total')
* .from(`(${innerQb.getQuery()})`, 'inner')
* .setParameters(innerQb.getParameters());
* return totalItemsQb.getRawOne().then(res => res.total);
* }
* }
* ```
*
* @since 1.6.0
* @default undefined
*/
searchStrategy?: SearchStrategy;
}
/**
* Because the `inStock` field is opt-in based on the `indexStockStatus` option,
* it is not included by default in the generated types. Thus we manually augment
* the generated type here.
*/
export interface SearchInput extends GeneratedSearchInput {
inStock?: boolean;
}
export type ReindexMessageResponse = {
total: number;
completed: number;
duration: number;
};
export type ReindexMessageData = {
ctx: SerializedRequestContext;
};
export type UpdateProductMessageData = {
ctx: SerializedRequestContext;
productId: ID;
};
export type UpdateVariantMessageData = {
ctx: SerializedRequestContext;
variantIds: ID[];
};
export type UpdateVariantsByIdMessageData = {
ctx: SerializedRequestContext;
ids: ID[];
};
export type UpdateAssetMessageData = {
ctx: SerializedRequestContext;
asset: JsonCompatible<Required<Asset>>;
};
export type ProductChannelMessageData = {
ctx: SerializedRequestContext;
productId: ID;
channelId: ID;
};
export type VariantChannelMessageData = {
ctx: SerializedRequestContext;
productVariantId: ID;
channelId: ID;
};
type NamedJobData<Type extends string, MessageData> = { type: Type } & MessageData;
export type ReindexJobData = NamedJobData<'reindex', ReindexMessageData>;
export type UpdateProductJobData = NamedJobData<'update-product', UpdateProductMessageData>;
export type UpdateVariantsJobData = NamedJobData<'update-variants', UpdateVariantMessageData>;
export type DeleteProductJobData = NamedJobData<'delete-product', UpdateProductMessageData>;
export type DeleteVariantJobData = NamedJobData<'delete-variant', UpdateVariantMessageData>;
export type UpdateVariantsByIdJobData = NamedJobData<'update-variants-by-id', UpdateVariantsByIdMessageData>;
export type UpdateAssetJobData = NamedJobData<'update-asset', UpdateAssetMessageData>;
export type DeleteAssetJobData = NamedJobData<'delete-asset', UpdateAssetMessageData>;
export type AssignProductToChannelJobData = NamedJobData<
'assign-product-to-channel',
ProductChannelMessageData
>;
export type RemoveProductFromChannelJobData = NamedJobData<
'remove-product-from-channel',
ProductChannelMessageData
>;
export type AssignVariantToChannelJobData = NamedJobData<
'assign-variant-to-channel',
VariantChannelMessageData
>;
export type RemoveVariantFromChannelJobData = NamedJobData<
'remove-variant-from-channel',
VariantChannelMessageData
>;
export type UpdateIndexQueueJobData =
| ReindexJobData
| UpdateProductJobData
| UpdateVariantsJobData
| DeleteProductJobData
| DeleteVariantJobData
| UpdateVariantsByIdJobData
| UpdateAssetJobData
| DeleteAssetJobData
| AssignProductToChannelJobData
| RemoveProductFromChannelJobData
| AssignVariantToChannelJobData
| RemoveVariantFromChannelJobData;