cloudcommerce 2.5.1 → 2.6.1
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/.vscode/settings.json +4 -1
- package/CHANGELOG.md +27 -0
- package/ecomplus-stores/barradoce/.devcontainer/devcontainer.json +10 -4
- package/ecomplus-stores/barradoce/.vscode/settings.json +3 -0
- package/ecomplus-stores/barradoce/functions/many/package.json +3 -3
- package/ecomplus-stores/barradoce/functions/ssr/package.json +6 -6
- package/ecomplus-stores/barradoce/functions/ssr/src/components/CartSidebar.vue +29 -9
- package/ecomplus-stores/barradoce/functions/ssr/src/components/HeroSlider.vue +1 -3
- package/ecomplus-stores/barradoce/functions/ssr/src/components/ProductDetails.vue +30 -12
- package/ecomplus-stores/barradoce/functions/ssr/src/components/SearchModal.vue +9 -6
- package/ecomplus-stores/barradoce/functions/ssr/src/components/SearchShowcase.vue +19 -17
- package/ecomplus-stores/barradoce/functions/ssr/src/components/ShippingCalculator.vue +100 -0
- package/ecomplus-stores/barradoce/functions/ssr/src/main/content/Sections.astro +3 -0
- package/ecomplus-stores/barradoce/functions/ssr/src/state/midd-search-engine.ts +19 -0
- package/ecomplus-stores/barradoce/functions/with-apps/package.json +3 -3
- package/ecomplus-stores/barradoce/package.json +2 -2
- package/ecomplus-stores/barradoce/tailwind.config.cjs +5 -3
- package/package.json +2 -2
- package/packages/api/package.json +1 -1
- package/packages/apps/affiliate-program/package.json +1 -1
- package/packages/apps/correios/package.json +1 -1
- package/packages/apps/custom-payment/package.json +1 -1
- package/packages/apps/custom-shipping/package.json +1 -1
- package/packages/apps/datafrete/package.json +1 -1
- package/packages/apps/discounts/package.json +1 -1
- package/packages/apps/emails/package.json +1 -1
- package/packages/apps/fb-conversions/package.json +1 -1
- package/packages/apps/flash-courier/package.json +1 -1
- package/packages/apps/frenet/package.json +1 -1
- package/packages/apps/galaxpay/package.json +1 -1
- package/packages/apps/google-analytics/package.json +1 -1
- package/packages/apps/jadlog/package.json +1 -1
- package/packages/apps/loyalty-points/package.json +1 -1
- package/packages/apps/mandae/package.json +1 -1
- package/packages/apps/melhor-envio/package.json +1 -1
- package/packages/apps/mercadopago/package.json +1 -1
- package/packages/apps/pagarme/package.json +1 -1
- package/packages/apps/pagarme-v5/package.json +1 -1
- package/packages/apps/paghiper/package.json +1 -1
- package/packages/apps/pix/package.json +1 -1
- package/packages/apps/tiny-erp/package.json +1 -1
- package/packages/apps/webhooks/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/config/package.json +1 -1
- package/packages/emails/package.json +1 -1
- package/packages/eslint/package.json +1 -1
- package/packages/eslint/storefront.eslintrc.cjs +1 -0
- package/packages/events/package.json +1 -1
- package/packages/feeds/package.json +1 -1
- package/packages/firebase/package.json +1 -1
- package/packages/i18n/package.json +1 -1
- package/packages/modules/package.json +1 -1
- package/packages/passport/package.json +1 -1
- package/packages/ssr/package.json +3 -3
- package/packages/storefront/package.json +4 -3
- package/packages/storefront/src/__fixtures__/calculate_shipping.json +161 -0
- package/packages/storefront/src/helpers/afetch.ts +1 -0
- package/packages/storefront/src/lib/components/Spinner.vue +16 -0
- package/packages/storefront/src/lib/components/globals/Skeleton.vue +25 -7
- package/packages/storefront/src/lib/composables/use-search-modal.ts +3 -1
- package/packages/storefront/src/lib/composables/use-search-showcase.ts +2 -1
- package/packages/storefront/src/lib/composables/use-shipping-calculator.ts +90 -31
- package/packages/storefront/src/lib/layouts/BaseHead.astro +2 -1
- package/packages/storefront/src/lib/layouts/use-page-main.ts +9 -5
- package/packages/storefront/src/lib/ssr-context.ts +9 -0
- package/packages/storefront/src/lib/state/search-engine.ts +21 -11
- package/packages/test-base/package.json +1 -1
- package/packages/types/package.json +1 -1
|
@@ -4,10 +4,13 @@ import { computed } from 'vue';
|
|
|
4
4
|
export interface Props {
|
|
5
5
|
isBold?: boolean;
|
|
6
6
|
isLarge?: boolean;
|
|
7
|
+
numRows?: number;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
const props = defineProps<Props>()
|
|
10
|
-
|
|
10
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
11
|
+
numRows: 6,
|
|
12
|
+
});
|
|
13
|
+
const rowClassName = 'bg-base-200 rounded-md';
|
|
11
14
|
const firstRowClassName = computed(() => {
|
|
12
15
|
return `${rowClassName} ${(props.isBold ? 'h-8 mb-6' : 'h-2.5 mb-4')}`;
|
|
13
16
|
});
|
|
@@ -19,11 +22,26 @@ const nextRowsClassName = computed(() => {
|
|
|
19
22
|
<template>
|
|
20
23
|
<div role="status" class="animate-pulse" :class="isLarge ? 'max-w-4xl' : 'max-w-sm'">
|
|
21
24
|
<div :class="[firstRowClassName, isLarge ? 'w-96' : 'w-48']"></div>
|
|
22
|
-
<div
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
<div
|
|
25
|
+
<div
|
|
26
|
+
v-if="numRows > 1"
|
|
27
|
+
:class="[nextRowsClassName, isLarge ? 'max-w-[680px]' : 'max-w-[340px]']"
|
|
28
|
+
></div>
|
|
29
|
+
<div
|
|
30
|
+
v-if="numRows > 2"
|
|
31
|
+
:class="nextRowsClassName"
|
|
32
|
+
></div>
|
|
33
|
+
<div
|
|
34
|
+
v-if="numRows > 3"
|
|
35
|
+
:class="[nextRowsClassName, isLarge ? 'max-w-[660px]' : 'max-w-[330px]']"
|
|
36
|
+
></div>
|
|
37
|
+
<div
|
|
38
|
+
v-if="numRows > 4"
|
|
39
|
+
:class="[nextRowsClassName, isLarge ? 'max-w-[600px]' : 'max-w-[300px]']"
|
|
40
|
+
></div>
|
|
41
|
+
<div
|
|
42
|
+
v-for="n in (numRows - 5)" :key="n"
|
|
43
|
+
:class="[nextRowsClassName, isLarge ? 'max-w-[720px]' : 'max-w-[360px]']"
|
|
44
|
+
></div>
|
|
27
45
|
<span class="sr-only">Loading...</span>
|
|
28
46
|
</div>
|
|
29
47
|
</template>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Categories } from '@cloudcommerce/api/types';
|
|
2
|
+
import type { SearchEngineInstance } from '@@sf/state/search-engine';
|
|
2
3
|
import { ref, watch, toRef } from 'vue';
|
|
3
4
|
import Wade from 'wade';
|
|
4
5
|
import { clearAccents } from '@@sf/sf-lib';
|
|
@@ -8,6 +9,7 @@ export interface Props {
|
|
|
8
9
|
term: string;
|
|
9
10
|
fetchDebounce?: number;
|
|
10
11
|
productsLimit?: number;
|
|
12
|
+
searchEngine?: SearchEngineInstance;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
const wadeDocs: Array<{
|
|
@@ -39,7 +41,7 @@ if (wadeDocs.length) {
|
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
export const useSearchModal = (props: Props) => {
|
|
42
|
-
const searchEngine = new SearchEngine({
|
|
44
|
+
const searchEngine = props.searchEngine || new SearchEngine({
|
|
43
45
|
debounce: props.fetchDebounce || 300,
|
|
44
46
|
});
|
|
45
47
|
searchEngine.pageSize.value = props.productsLimit || 12;
|
|
@@ -30,6 +30,7 @@ export interface Props {
|
|
|
30
30
|
ssrError?: string | null;
|
|
31
31
|
canUseUrlParams?: boolean;
|
|
32
32
|
showcase?: Ref<HTMLElement | null>;
|
|
33
|
+
searchEngine?: SearchEngineInstance;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
const useSearchShowcase = (props: Props) => {
|
|
@@ -43,7 +44,7 @@ const useSearchShowcase = (props: Props) => {
|
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
const products = shallowReactive<SearchItem[]>(props.products || []);
|
|
46
|
-
const searchEngine = new SearchEngine({ debounce: 50 });
|
|
47
|
+
const searchEngine = props.searchEngine || new SearchEngine({ debounce: 50 });
|
|
47
48
|
if (term === undefined && !import.meta.env.SSR) {
|
|
48
49
|
term = new URLSearchParams(window.location.search).get('q') || null;
|
|
49
50
|
}
|
|
@@ -14,24 +14,34 @@ import {
|
|
|
14
14
|
toRef,
|
|
15
15
|
} from 'vue';
|
|
16
16
|
import { useDebounceFn, watchOnce } from '@vueuse/core';
|
|
17
|
-
import { price as getPrice } from '@ecomplus/utils';
|
|
17
|
+
import { price as getPrice, formatMoney } from '@ecomplus/utils';
|
|
18
18
|
import config from '@cloudcommerce/config';
|
|
19
|
+
import {
|
|
20
|
+
i19days,
|
|
21
|
+
i19free,
|
|
22
|
+
i19freeShipping,
|
|
23
|
+
i19pickUpToday,
|
|
24
|
+
i19receiveToday,
|
|
25
|
+
i19untilTomorrow,
|
|
26
|
+
i19upTo,
|
|
27
|
+
i19workingDays,
|
|
28
|
+
} from '@@i18n';
|
|
19
29
|
import { fetchModule } from '@@sf/state/modules-info';
|
|
20
30
|
|
|
21
31
|
export type ShippedItem = Exclude<CalculateShippingParams['items'], undefined>[0];
|
|
22
32
|
|
|
23
33
|
export type ShippingService = CalculateShippingResponse['shipping_services'][0];
|
|
24
34
|
|
|
25
|
-
type CartOrProductItem = Carts['items'][0]
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
type CartOrProductItem = Carts['items'][0]
|
|
36
|
+
| (Partial<Products>
|
|
37
|
+
& { price: number, quantity: number }
|
|
38
|
+
& ({ product_id: string & { length: 24 } } | { _id: string & { length: 24 } })
|
|
39
|
+
);
|
|
30
40
|
|
|
31
41
|
export interface Props {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
canSelectService?: boolean;
|
|
42
|
+
zipCode?: Ref<string>;
|
|
43
|
+
canAutoSubmit?: boolean;
|
|
44
|
+
// canSelectService?: boolean;
|
|
35
45
|
countryCode?: string;
|
|
36
46
|
shippedItems?: (ShippedItem | CartOrProductItem)[];
|
|
37
47
|
shippingResult?: ModuleApiResult<'calculate_shipping'>['result'];
|
|
@@ -62,6 +72,9 @@ const sortApps = (results: any, order: number[]) => {
|
|
|
62
72
|
});
|
|
63
73
|
};
|
|
64
74
|
const reduceItemBody = (itemOrProduct: Record<string, any>) => {
|
|
75
|
+
if (!itemOrProduct.product_id) {
|
|
76
|
+
itemOrProduct.product_id = itemOrProduct._id;
|
|
77
|
+
}
|
|
65
78
|
const shippedItem = {};
|
|
66
79
|
const fields: (keyof ShippedItem)[] = [
|
|
67
80
|
'product_id',
|
|
@@ -86,12 +99,11 @@ const reduceItemBody = (itemOrProduct: Record<string, any>) => {
|
|
|
86
99
|
};
|
|
87
100
|
|
|
88
101
|
export const useShippingCalculator = (props: Props) => {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
if (!localZipCode.value && localStorage) {
|
|
102
|
+
const zipCode = props.zipCode || ref('');
|
|
103
|
+
if (!zipCode.value && localStorage) {
|
|
92
104
|
const storedZip = localStorage.getItem(ZIP_STORAGE_KEY);
|
|
93
105
|
if (storedZip) {
|
|
94
|
-
|
|
106
|
+
zipCode.value = storedZip;
|
|
95
107
|
}
|
|
96
108
|
}
|
|
97
109
|
const countryCode = props.countryCode || config.get().countryCode;
|
|
@@ -117,7 +129,7 @@ export const useShippingCalculator = (props: Props) => {
|
|
|
117
129
|
...props.baseParams,
|
|
118
130
|
to: {
|
|
119
131
|
...props.baseParams?.to,
|
|
120
|
-
zip:
|
|
132
|
+
zip: zipCode.value,
|
|
121
133
|
},
|
|
122
134
|
};
|
|
123
135
|
if (shippedItems.value.length) {
|
|
@@ -125,6 +137,17 @@ export const useShippingCalculator = (props: Props) => {
|
|
|
125
137
|
body.subtotal = amountSubtotal.value;
|
|
126
138
|
}
|
|
127
139
|
isFetching.value = true;
|
|
140
|
+
if (import.meta.env.DEV) {
|
|
141
|
+
// eslint-disable-next-line
|
|
142
|
+
return import('../../__fixtures__/calculate_shipping.json')
|
|
143
|
+
.then(({ default: data }) => {
|
|
144
|
+
setTimeout(() => {
|
|
145
|
+
isFetching.value = false;
|
|
146
|
+
// eslint-disable-next-line no-use-before-define
|
|
147
|
+
parseShippingResult(data.result as any, isRetry);
|
|
148
|
+
}, 1500);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
128
151
|
fetchModule('calculate_shipping', {
|
|
129
152
|
method: 'POST',
|
|
130
153
|
params: {
|
|
@@ -133,6 +156,7 @@ export const useShippingCalculator = (props: Props) => {
|
|
|
133
156
|
body,
|
|
134
157
|
})
|
|
135
158
|
.then(async (response) => {
|
|
159
|
+
if (response.status === 501) return;
|
|
136
160
|
const data = await response.json();
|
|
137
161
|
// eslint-disable-next-line no-use-before-define
|
|
138
162
|
parseShippingResult(data.result, isRetry);
|
|
@@ -220,43 +244,74 @@ export const useShippingCalculator = (props: Props) => {
|
|
|
220
244
|
};
|
|
221
245
|
|
|
222
246
|
const submitZipCode = () => {
|
|
223
|
-
const _zipCode =
|
|
247
|
+
const _zipCode = zipCode.value;
|
|
224
248
|
if (countryCode === 'BR') {
|
|
225
249
|
if (_zipCode?.replace(/\D/g, '').length !== 8) return;
|
|
226
250
|
} else if (!_zipCode) {
|
|
227
251
|
return;
|
|
228
252
|
}
|
|
229
|
-
zipCode.value = _zipCode;
|
|
230
253
|
if (localStorage) {
|
|
231
|
-
localStorage.setItem(ZIP_STORAGE_KEY,
|
|
254
|
+
localStorage.setItem(ZIP_STORAGE_KEY, _zipCode);
|
|
232
255
|
}
|
|
233
256
|
fetchShippingServices();
|
|
234
257
|
};
|
|
235
|
-
watch(
|
|
258
|
+
watch(zipCode, (value) => {
|
|
259
|
+
if (value.length) {
|
|
260
|
+
if (countryCode === 'BR') {
|
|
261
|
+
const fmt = value.replace(/\D/g, '');
|
|
262
|
+
if (fmt.length > 5) {
|
|
263
|
+
zipCode.value = fmt.substring(0, 5) + '-' + fmt.substring(5, 8);
|
|
264
|
+
if (props.canAutoSubmit) submitZipCode();
|
|
265
|
+
}
|
|
266
|
+
} else {
|
|
267
|
+
zipCode.value = value.substring(0, 30);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}, {
|
|
236
271
|
immediate: !props.shippingResult,
|
|
237
272
|
});
|
|
238
273
|
watch(toRef(props, 'shippingResult'), (shippingResult) => {
|
|
239
274
|
if (!shippingResult?.length) return;
|
|
240
|
-
if (localZipCode.value) zipCode.value = localZipCode.value;
|
|
241
275
|
parseShippingResult(shippingResult);
|
|
242
276
|
}, {
|
|
243
277
|
immediate: true,
|
|
244
278
|
});
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if (
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
zipInput.innerHTML = value.substring(0, 30);
|
|
279
|
+
|
|
280
|
+
const productionDeadline = computed(() => {
|
|
281
|
+
let maxDeadline = 0;
|
|
282
|
+
_shippedItems.value?.forEach((item: Partial<Products>) => {
|
|
283
|
+
if (item.quantity && item.production_time) {
|
|
284
|
+
const { days, cumulative } = item.production_time;
|
|
285
|
+
const itemDeadline = cumulative ? days * item.quantity : days;
|
|
286
|
+
if (itemDeadline > maxDeadline) {
|
|
287
|
+
maxDeadline = itemDeadline;
|
|
255
288
|
}
|
|
256
289
|
}
|
|
257
|
-
localZipCode.value = value;
|
|
258
290
|
});
|
|
259
|
-
|
|
291
|
+
return maxDeadline;
|
|
292
|
+
});
|
|
293
|
+
const getShippingDeadline = (shipping: ShippingService['shipping_line']) => {
|
|
294
|
+
const isWorkingDays = Boolean(shipping.posting_deadline?.working_days
|
|
295
|
+
|| shipping.delivery_time?.working_days);
|
|
296
|
+
let days = shipping.posting_deadline?.days || 0;
|
|
297
|
+
if (shipping.delivery_time) {
|
|
298
|
+
days += shipping.delivery_time.days;
|
|
299
|
+
}
|
|
300
|
+
days += productionDeadline.value;
|
|
301
|
+
if (days > 1) {
|
|
302
|
+
return `${i19upTo} ${days} `
|
|
303
|
+
+ (isWorkingDays ? i19workingDays : i19days).toLowerCase();
|
|
304
|
+
}
|
|
305
|
+
if (days === 1) return i19untilTomorrow;
|
|
306
|
+
return shipping.pick_up ? i19pickUpToday : i19receiveToday;
|
|
307
|
+
};
|
|
308
|
+
const getShippingPrice = (shipping: ShippingService['shipping_line']) => {
|
|
309
|
+
const freight = typeof shipping.total_price === 'number'
|
|
310
|
+
? shipping.total_price
|
|
311
|
+
: shipping.price;
|
|
312
|
+
if (freight) return formatMoney(freight);
|
|
313
|
+
return shipping.pick_up ? i19free : i19freeShipping;
|
|
314
|
+
};
|
|
260
315
|
|
|
261
316
|
return {
|
|
262
317
|
zipCode,
|
|
@@ -264,9 +319,13 @@ export const useShippingCalculator = (props: Props) => {
|
|
|
264
319
|
amountSubtotal,
|
|
265
320
|
submitZipCode,
|
|
266
321
|
fetchShippingServices,
|
|
322
|
+
isFetching,
|
|
267
323
|
freeFromValue,
|
|
268
324
|
shippingServices,
|
|
269
325
|
parseShippingResult,
|
|
326
|
+
productionDeadline,
|
|
327
|
+
getShippingDeadline,
|
|
328
|
+
getShippingPrice,
|
|
270
329
|
};
|
|
271
330
|
};
|
|
272
331
|
|
|
@@ -168,6 +168,7 @@ const inlineJSONLd = JSON.stringify({
|
|
|
168
168
|
url: `https://${domain}/`,
|
|
169
169
|
logo: `https://${domain}${settings.logo}`,
|
|
170
170
|
});
|
|
171
|
+
const generator = `e-com.plus @cloudcommerce/storefront, ${Astro.generator}`;
|
|
171
172
|
---
|
|
172
173
|
|
|
173
174
|
<meta charset="UTF-8">
|
|
@@ -179,7 +180,7 @@ const inlineJSONLd = JSON.stringify({
|
|
|
179
180
|
{title && <title>{title}</title>}
|
|
180
181
|
{description && <meta name="description" content={description}>}
|
|
181
182
|
<meta name="author" content={settings.name}>
|
|
182
|
-
<meta name="generator" content={
|
|
183
|
+
<meta name="generator" content={generator}>
|
|
183
184
|
<link rel="canonical" href={canonicalUrl} />
|
|
184
185
|
{shortcutIcon && <link rel="apple-touch-icon" href={shortcutIcon} />}
|
|
185
186
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
@@ -12,6 +12,7 @@ export interface Props {
|
|
|
12
12
|
routeContext: RouteContext;
|
|
13
13
|
handleCustomSection?: (type: `${string}:${string}`, content: Record<string, any>) =>
|
|
14
14
|
Promise<{ props: Record<string, any> }>;
|
|
15
|
+
searchEngine?: UseSearchShowcaseProps['searchEngine'];
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
type PageContentHero = Exclude<PageContent['hero'], undefined>;
|
|
@@ -48,7 +49,7 @@ type CustomSection = { type: `${string}:${string}`, props: any };
|
|
|
48
49
|
type ProductDetailsProps = { hasDescription?: boolean, hasSpecifications?: boolean };
|
|
49
50
|
|
|
50
51
|
export const usePageSections = async <T extends CustomSection = CustomSection>
|
|
51
|
-
({ routeContext, handleCustomSection }: Props) => {
|
|
52
|
+
({ routeContext, handleCustomSection, searchEngine }: Props) => {
|
|
52
53
|
const { cmsContent } = routeContext;
|
|
53
54
|
let sectionsContent = cmsContent?.sections;
|
|
54
55
|
if (
|
|
@@ -181,11 +182,14 @@ export const usePageSections = async <T extends CustomSection = CustomSection>
|
|
|
181
182
|
props.term = routeContext.searchPageTerm || null;
|
|
182
183
|
}
|
|
183
184
|
if (props.term !== undefined || props.fixedParams) {
|
|
184
|
-
const {
|
|
185
|
+
const {
|
|
186
|
+
searchEngine: resultSearchEngine,
|
|
187
|
+
fetching,
|
|
188
|
+
} = useSearchShowcase({ ...props, searchEngine });
|
|
185
189
|
await fetching;
|
|
186
|
-
props.products =
|
|
187
|
-
props.resultMeta =
|
|
188
|
-
props.ssrError =
|
|
190
|
+
props.products = resultSearchEngine.products;
|
|
191
|
+
props.resultMeta = resultSearchEngine.meta;
|
|
192
|
+
props.ssrError = resultSearchEngine.fetchError.value?.message;
|
|
189
193
|
}
|
|
190
194
|
sections[index] = { type, props };
|
|
191
195
|
return;
|
|
@@ -296,6 +296,15 @@ const loadRouteContext = async (
|
|
|
296
296
|
} else {
|
|
297
297
|
setResponseCache(Astro, 120, 180);
|
|
298
298
|
}
|
|
299
|
+
if (
|
|
300
|
+
Astro.url.searchParams.get('webcontainer') !== null
|
|
301
|
+
|| urlPath.startsWith('/admin/ide')
|
|
302
|
+
) {
|
|
303
|
+
// https://webcontainers.io/guides/quickstart#cross-origin-isolation
|
|
304
|
+
Astro.response.headers.set('Cross-Origin-Embedder-Policy', 'require-corp');
|
|
305
|
+
Astro.response.headers.set('Cross-Origin-Opener-Policy', 'same-origin');
|
|
306
|
+
Astro.response.headers.set('Cross-Origin-Resource-Policy', 'cross-origin');
|
|
307
|
+
}
|
|
299
308
|
const routeContext = {
|
|
300
309
|
...config,
|
|
301
310
|
isHomepage,
|
|
@@ -68,6 +68,8 @@ export const search = async ({
|
|
|
68
68
|
return response;
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
type SearchOptions = Parameters<typeof search>[0];
|
|
72
|
+
|
|
71
73
|
export class SearchEngine {
|
|
72
74
|
fields?: readonly string[];
|
|
73
75
|
term = ref<string | null>(null);
|
|
@@ -76,6 +78,7 @@ export class SearchEngine {
|
|
|
76
78
|
params = reactive<Exclude<ApiConfig['params'], string | undefined>>({});
|
|
77
79
|
pageSize = ref(24);
|
|
78
80
|
pageNumber = ref(1);
|
|
81
|
+
#middlewares: Array<(opt: SearchOptions) => void> = [];
|
|
79
82
|
#isFetching = ref(false);
|
|
80
83
|
isFetching = computed(() => this.#isFetching.value);
|
|
81
84
|
#wasFetched = ref(false);
|
|
@@ -130,18 +133,22 @@ export class SearchEngine {
|
|
|
130
133
|
});
|
|
131
134
|
}
|
|
132
135
|
let response: Awaited<ReturnType<typeof search>> | null | undefined;
|
|
136
|
+
const searchOptions = {
|
|
137
|
+
term: this.term.value,
|
|
138
|
+
params: {
|
|
139
|
+
...this.params,
|
|
140
|
+
limit,
|
|
141
|
+
offset,
|
|
142
|
+
count: this.isWithCount.value || undefined,
|
|
143
|
+
buckets: this.isWithBuckets.value || undefined,
|
|
144
|
+
},
|
|
145
|
+
fields: this.fields,
|
|
146
|
+
};
|
|
133
147
|
try {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
limit,
|
|
139
|
-
offset,
|
|
140
|
-
count: this.isWithCount.value || undefined,
|
|
141
|
-
buckets: this.isWithBuckets.value || undefined,
|
|
142
|
-
},
|
|
143
|
-
fields: this.fields,
|
|
144
|
-
});
|
|
148
|
+
for (let i = 0; i < this.#middlewares.length; i++) {
|
|
149
|
+
this.#middlewares[i](searchOptions);
|
|
150
|
+
}
|
|
151
|
+
response = await this.#search(searchOptions);
|
|
145
152
|
} catch (err: any) {
|
|
146
153
|
if (this.#fulfillFetching) {
|
|
147
154
|
this.#fetchError.value = err;
|
|
@@ -162,6 +169,9 @@ export class SearchEngine {
|
|
|
162
169
|
}
|
|
163
170
|
}
|
|
164
171
|
|
|
172
|
+
addMiddleware(cb: (options: SearchOptions) => void) {
|
|
173
|
+
this.#middlewares.push(cb);
|
|
174
|
+
}
|
|
165
175
|
setResult(data: Partial<SearchResult<'v1'>>) {
|
|
166
176
|
if (data.meta) {
|
|
167
177
|
Object.assign(this.meta, data.meta);
|