@scayle/storefront-product-listing 1.5.0 → 1.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/CHANGELOG.md +13 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +8 -2
- package/dist/runtime/composables/index.d.ts +1 -0
- package/dist/runtime/composables/index.js +1 -0
- package/dist/runtime/composables/useAllShopCategoriesForId.d.ts +4 -0
- package/dist/runtime/composables/useAllShopCategoriesForId.js +8 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/rpc/methods/categories.d.ts +25 -0
- package/dist/runtime/rpc/methods/categories.js +34 -0
- package/dist/runtime/utils/filters.d.ts +1 -1
- package/dist/runtime/utils/seo.d.ts +19 -0
- package/dist/runtime/utils/seo.js +24 -0
- package/package.json +12 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @scayle/storefront-product-listing
|
|
2
2
|
|
|
3
|
+
## 1.6.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Added missing exports for `useAllShopCategoriesForId` composable and SEO utils.
|
|
8
|
+
|
|
9
|
+
## 1.6.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- **\[PLP\]** Added `generateCategoryHreflangLinks` utils to generate hreflang links for a category for all shops.
|
|
14
|
+
- **\[PLP\]** Added RPC method `getAllShopCategoriesForId` and the composable `useAllShopCategoriesForId` for product listing page to fetch category for all shops. This is used to generate hreflang links for the category for all shops.
|
|
15
|
+
|
|
3
16
|
## 1.5.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { defineNuxtModule, createResolver, addImportsDir } from '@nuxt/kit';
|
|
1
|
+
import { defineNuxtModule, createResolver, resolvePath, addImportsDir } from '@nuxt/kit';
|
|
2
2
|
|
|
3
3
|
const PACKAGE_NAME = "@scayle/storefront-product-listing";
|
|
4
|
-
const PACKAGE_VERSION = "1.
|
|
4
|
+
const PACKAGE_VERSION = "1.6.1";
|
|
5
5
|
const module = defineNuxtModule({
|
|
6
6
|
meta: {
|
|
7
7
|
name: PACKAGE_NAME,
|
|
@@ -17,6 +17,12 @@ const module = defineNuxtModule({
|
|
|
17
17
|
const { resolve } = createResolver(import.meta.url);
|
|
18
18
|
nuxt.options.alias["#storefront-product-listing"] = resolve("./runtime");
|
|
19
19
|
nuxt.options.build.transpile.push("#storefront-product-listing/runtime");
|
|
20
|
+
nuxt.hook("storefront:custom-rpc:extend", async (customRpcs) => {
|
|
21
|
+
customRpcs.push({
|
|
22
|
+
source: await resolvePath("./runtime/rpc/methods/categories"),
|
|
23
|
+
names: ["getAllShopCategoriesForId"]
|
|
24
|
+
});
|
|
25
|
+
});
|
|
20
26
|
if (options.autoImports) {
|
|
21
27
|
addImportsDir(resolve("./runtime/composables"));
|
|
22
28
|
addImportsDir(resolve("./runtime/utils"));
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { KeysOf, NormalizedRpcResponse, UseRpcReturn } from '@scayle/storefront-nuxt/composables';
|
|
2
|
+
import type { MaybeRefOrGetter } from 'vue';
|
|
3
|
+
import type { RpcMethodParameters } from '@scayle/storefront-core';
|
|
4
|
+
export declare function useAllShopCategoriesForId<DataT = NormalizedRpcResponse<'getAllShopCategoriesForId'>, PickKeys extends KeysOf<DataT> = KeysOf<DataT>, DefaultT = null>(params: MaybeRefOrGetter<RpcMethodParameters<'getAllShopCategoriesForId'>>, key?: string): UseRpcReturn<'getAllShopCategoriesForId', DataT, PickKeys, DefaultT>;
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from './composables/useAllShopCategoriesForId.js';
|
|
1
2
|
export * from './composables/useProductListSort.js';
|
|
2
3
|
export * from './composables/useAppliedFilters.js';
|
|
3
4
|
export * from './composables/useFiltersForListing.js';
|
|
@@ -5,3 +6,4 @@ export * from './composables/useProductListingSeoData.js';
|
|
|
5
6
|
export * from './composables/useProductsForListing.js';
|
|
6
7
|
export * from './utils/filters.js';
|
|
7
8
|
export * from './utils/category.js';
|
|
9
|
+
export * from './utils/seo.js';
|
package/dist/runtime/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from "./composables/useAllShopCategoriesForId.js";
|
|
1
2
|
export * from "./composables/useProductListSort.js";
|
|
2
3
|
export * from "./composables/useAppliedFilters.js";
|
|
3
4
|
export * from "./composables/useFiltersForListing.js";
|
|
@@ -5,3 +6,4 @@ export * from "./composables/useProductListingSeoData.js";
|
|
|
5
6
|
export * from "./composables/useProductsForListing.js";
|
|
6
7
|
export * from "./utils/filters.js";
|
|
7
8
|
export * from "./utils/category.js";
|
|
9
|
+
export * from "./utils/seo.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ProductCategoryPropertyWith, RpcHandler, ShopConfig, Category } from '@scayle/storefront-nuxt';
|
|
2
|
+
type ShopCategory = Pick<ShopConfig, 'locale' | 'path'> & {
|
|
3
|
+
category: Category;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Fetches all shop categories for a given category ID.
|
|
7
|
+
*
|
|
8
|
+
* This function retrieves all categories from all shops in the runtime configuration.
|
|
9
|
+
* It uses the SAPI client to fetch the category details for each shop.
|
|
10
|
+
*
|
|
11
|
+
* @param options - The parameters for fetching the category.
|
|
12
|
+
* @param options.id - The ID of the category to fetch.
|
|
13
|
+
* @param options.children - The number of children to fetch.
|
|
14
|
+
* @param options.includeHidden - Whether to include hidden categories.
|
|
15
|
+
* @param options.properties - The properties to fetch.
|
|
16
|
+
*
|
|
17
|
+
* @param context - The context object containing runtime configuration, SAPI client, and logging.
|
|
18
|
+
*
|
|
19
|
+
* @returns An array of objects containing the category for each shop.
|
|
20
|
+
*/
|
|
21
|
+
export declare const getAllShopCategoriesForId: RpcHandler<{
|
|
22
|
+
id: number;
|
|
23
|
+
properties?: ProductCategoryPropertyWith;
|
|
24
|
+
}, ShopCategory[]>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const getAllShopCategoriesForId = async function getAllShopCategoriesForId2({ id, properties }, context) {
|
|
2
|
+
const { runtimeConfiguration, sapiClient, log, cached } = context;
|
|
3
|
+
const fetchAllCategories = async () => {
|
|
4
|
+
const categories = [];
|
|
5
|
+
const shops = Object.values(
|
|
6
|
+
runtimeConfiguration.storefront.shops
|
|
7
|
+
);
|
|
8
|
+
await Promise.all(
|
|
9
|
+
shops.map(async (shop) => {
|
|
10
|
+
try {
|
|
11
|
+
const category = await sapiClient.clone({ shopId: shop.shopId }).categories.getById(id, {
|
|
12
|
+
with: {
|
|
13
|
+
properties
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
categories.push({
|
|
17
|
+
locale: shop.locale,
|
|
18
|
+
path: Array.isArray(shop.path) ? shop.path[0] : shop.path,
|
|
19
|
+
category
|
|
20
|
+
});
|
|
21
|
+
} catch (error) {
|
|
22
|
+
log.error(error instanceof Error ? error : String(error));
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
);
|
|
26
|
+
return categories;
|
|
27
|
+
};
|
|
28
|
+
const result = await cached(fetchAllCategories, {
|
|
29
|
+
cacheKeyPrefix: `getAllShopCategoriesForId-${id}`,
|
|
30
|
+
ttl: 12 * 60 * 60
|
|
31
|
+
// 12 hours
|
|
32
|
+
})();
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { LocationQuery, RouteLocationNormalizedLoadedGeneric } from 'vue-router';
|
|
2
2
|
import type { CategoryFilter, ProductSearchQuery } from '@scayle/storefront-nuxt';
|
|
3
|
-
import type { RangeTuple } from '
|
|
3
|
+
import type { RangeTuple } from '../..//index.js';
|
|
4
4
|
/**
|
|
5
5
|
* Parses filter data from a Vue Router route object.
|
|
6
6
|
*
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ShopConfig } from '@scayle/storefront-nuxt';
|
|
2
|
+
import type { MaybeRefOrGetter } from 'vue';
|
|
3
|
+
type ShopCategoryHref = Pick<ShopConfig, 'locale' | 'path'> & {
|
|
4
|
+
categoryHref: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Generates hreflang links for a product listing.
|
|
8
|
+
*
|
|
9
|
+
* @param _categoriesForAllShops - A list of category links for all shops.
|
|
10
|
+
* @param defaultLocale - The default locale of the store.
|
|
11
|
+
*
|
|
12
|
+
* @returns An array of hreflang links.
|
|
13
|
+
*/
|
|
14
|
+
export declare const generateProductListingHreflangLinks: (_categoriesForAllShops: MaybeRefOrGetter<ShopCategoryHref[]>, defaultLocale: string) => {
|
|
15
|
+
rel: string;
|
|
16
|
+
hreflang: string;
|
|
17
|
+
href: string;
|
|
18
|
+
}[];
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { toValue } from "vue";
|
|
2
|
+
export const generateProductListingHreflangLinks = (_categoriesForAllShops, defaultLocale) => {
|
|
3
|
+
const categoriesForAllShops = toValue(_categoriesForAllShops);
|
|
4
|
+
if (!categoriesForAllShops) {
|
|
5
|
+
return [];
|
|
6
|
+
}
|
|
7
|
+
return categoriesForAllShops.flatMap(({ categoryHref, path, locale }) => {
|
|
8
|
+
const links = [
|
|
9
|
+
{
|
|
10
|
+
rel: "alternate",
|
|
11
|
+
hreflang: locale,
|
|
12
|
+
href: categoryHref
|
|
13
|
+
}
|
|
14
|
+
];
|
|
15
|
+
if (path === defaultLocale) {
|
|
16
|
+
links.push({
|
|
17
|
+
rel: "alternate",
|
|
18
|
+
hreflang: "x-default",
|
|
19
|
+
href: categoryHref
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return links;
|
|
23
|
+
});
|
|
24
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scayle/storefront-product-listing",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "Collection of essential composables and utilities to work with product listing",
|
|
5
5
|
"author": "SCAYLE Commerce Engine",
|
|
6
6
|
"license": "MIT",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"lint:fix": "eslint . --fix",
|
|
42
42
|
"format": "dprint check",
|
|
43
43
|
"format:fix": "dprint fmt",
|
|
44
|
-
"test": "vitest --run
|
|
45
|
-
"test:watch": "vitest
|
|
46
|
-
"test:ci": "vitest --run --
|
|
44
|
+
"test": "vitest --run",
|
|
45
|
+
"test:watch": "vitest",
|
|
46
|
+
"test:ci": "vitest --run --coverage --reporter=default --reporter=junit --outputFile=./coverage/junit.xml",
|
|
47
47
|
"typecheck": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
|
|
48
48
|
"package:lint": "publint",
|
|
49
49
|
"verify-packaging": "attw --pack . --profile esm-only"
|
|
@@ -65,14 +65,14 @@
|
|
|
65
65
|
"@nuxt/schema": "3.16.2",
|
|
66
66
|
"@nuxt/test-utils": "3.18.0",
|
|
67
67
|
"@scayle/eslint-config-storefront": "4.5.2",
|
|
68
|
-
"@scayle/storefront-api": "18.
|
|
69
|
-
"@scayle/storefront-nuxt": "8.
|
|
70
|
-
"@types/node": "22.15.
|
|
68
|
+
"@scayle/storefront-api": "18.7.0",
|
|
69
|
+
"@scayle/storefront-nuxt": "8.27.0",
|
|
70
|
+
"@types/node": "22.15.21",
|
|
71
71
|
"@vue/test-utils": "2.4.6",
|
|
72
|
-
"@vueuse/core": "13.
|
|
73
|
-
"dprint": "0.
|
|
72
|
+
"@vueuse/core": "13.2.0",
|
|
73
|
+
"dprint": "0.50.0",
|
|
74
74
|
"eslint-formatter-gitlab": "6.0.0",
|
|
75
|
-
"eslint": "9.
|
|
75
|
+
"eslint": "9.27.0",
|
|
76
76
|
"fishery": "2.3.1",
|
|
77
77
|
"happy-dom": "17.4.7",
|
|
78
78
|
"nuxt": "3.16.2",
|
|
@@ -80,9 +80,9 @@
|
|
|
80
80
|
"schema-dts": "1.1.5",
|
|
81
81
|
"typescript": "5.8.3",
|
|
82
82
|
"unbuild": "3.5.0",
|
|
83
|
-
"vitest": "3.1.
|
|
83
|
+
"vitest": "3.1.4",
|
|
84
84
|
"vue-router": "4.5.1",
|
|
85
85
|
"vue-tsc": "2.2.10",
|
|
86
|
-
"vue": "3.5.
|
|
86
|
+
"vue": "3.5.14"
|
|
87
87
|
}
|
|
88
88
|
}
|