@ikas/code-components-mcp 1.4.0-beta.165 → 1.4.0-beta.167
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/data/framework.json +6 -2
- package/data/section-templates/add-to-cart/utils/cartLimits.ts +4 -3
- package/data/section-templates/cart-section/sub-components/CartItem/index.tsx +27 -0
- package/data/section-templates/cart-section/utils/cartLimits.ts +24 -0
- package/data/section-templates/cart-section/utils/cartLineLimits.ts +82 -0
- package/data/section-templates/header-section/sub-components/CartItem/index.tsx +27 -0
- package/data/section-templates/header-section/utils/cartLimits.ts +24 -0
- package/data/section-templates/header-section/utils/cartLineLimits.ts +82 -0
- package/data/section-templates/navigation/sub-components/CartItem/index.tsx +27 -0
- package/data/section-templates/navigation/utils/cartLimits.ts +24 -0
- package/data/section-templates/navigation/utils/cartLineLimits.ts +82 -0
- package/data/section-templates/product-detail-section/utils/cartLimits.ts +4 -3
- package/data/storefront-api.json +43 -9
- package/data/storefront-types.json +1 -1
- package/dist/index.js +40 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/data/storefront-api.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-08-
|
|
2
|
+
"generatedAt": "2026-08-19T12:18:27.436Z",
|
|
3
3
|
"functions": [
|
|
4
4
|
{
|
|
5
5
|
"name": "apiListProductBrand",
|
|
@@ -12589,11 +12589,27 @@
|
|
|
12589
12589
|
"name": "bs_searchProductById",
|
|
12590
12590
|
"displayName": "searchProductById",
|
|
12591
12591
|
"signature": "async function bs_searchProductById(baseStore: BaseStore, params: { productId: string }): Promise<{\n isSuccess: boolean;\n product: IkasProduct | null;\n}>",
|
|
12592
|
-
"description": "",
|
|
12593
|
-
"params": [
|
|
12592
|
+
"description": "Fetches a single product by id and returns it as a full `IkasProduct`.\n\nUse this when a lightweight reference (e.g. a cart line's `IkasOrderLineVariant`, which carries\nneither `salesChannels` nor `stock`) needs product-level data: the returned product includes\n`salesChannels` filtered to the active sales channel (with `minQuantityPerCart` /\n`maxQuantityPerCart`) and per-variant `stock` (summed over the sales channel's configured\nstock locations). `selectedVariantValues` is seeded from the first active variant (or the\nfirst variant when none is active). For multiple ids, prefer `bs_searchProductsById` — one\nbatched request.",
|
|
12593
|
+
"params": [
|
|
12594
|
+
{
|
|
12595
|
+
"name": "baseStore",
|
|
12596
|
+
"description": "- The base store instance"
|
|
12597
|
+
},
|
|
12598
|
+
{
|
|
12599
|
+
"name": "params",
|
|
12600
|
+
"description": "- `{ productId }` — id of the product to fetch"
|
|
12601
|
+
}
|
|
12602
|
+
],
|
|
12603
|
+
"returns": "`{ isSuccess, product }` — `product` is null when not found or on failure",
|
|
12594
12604
|
"returnType": "Promise<{\n isSuccess: boolean;\n product: IkasProduct | null;\n}>",
|
|
12595
|
-
"
|
|
12596
|
-
"
|
|
12605
|
+
"example": "```tsx\nimport { baseStore, bs_searchProductById, IkasStorefrontConfig } from \"@ikas/bp-storefront\";\n\nconst { isSuccess, product } = await bs_searchProductById(baseStore, { productId });\nif (isSuccess && product) {\n const channel = product.salesChannels?.find(sc => sc.id === IkasStorefrontConfig.salesChannelId);\n console.log(channel?.maxQuantityPerCart);\n}\n```",
|
|
12606
|
+
"categories": [
|
|
12607
|
+
"Product",
|
|
12608
|
+
"Search"
|
|
12609
|
+
],
|
|
12610
|
+
"related": [
|
|
12611
|
+
"bs_searchProductsById"
|
|
12612
|
+
],
|
|
12597
12613
|
"isAsync": true,
|
|
12598
12614
|
"isClass": false,
|
|
12599
12615
|
"parameterTypes": [
|
|
@@ -12604,11 +12620,29 @@
|
|
|
12604
12620
|
"name": "bs_searchProductsById",
|
|
12605
12621
|
"displayName": "searchProductsById",
|
|
12606
12622
|
"signature": "async function bs_searchProductsById(baseStore: BaseStore, params: { productIds: string[] }): Promise<{\n isSuccess: boolean;\n products: IkasProduct[] | null;\n}>",
|
|
12607
|
-
"description": "",
|
|
12608
|
-
"params": [
|
|
12623
|
+
"description": "Batch-fetches products by id in a single request and returns them as full `IkasProduct` objects.\n\nThe go-to function when cart lines (or any lightweight reference) need product-level data they\ndo not carry: `IkasOrderLineVariant` has neither `salesChannels` nor `stock`, while the products\nreturned here include `salesChannels` filtered to the active sales channel (with\n`minQuantityPerCart` / `maxQuantityPerCart`) and per-variant `stock` (summed over the sales\nchannel's configured stock locations). Collect the distinct `productId`s of the lines and\nfetch them in ONE call instead of one request per line. Called with an empty `productIds`,\nit returns `{ isSuccess: true, products: [] }` without a network request.",
|
|
12624
|
+
"params": [
|
|
12625
|
+
{
|
|
12626
|
+
"name": "baseStore",
|
|
12627
|
+
"description": "- The base store instance"
|
|
12628
|
+
},
|
|
12629
|
+
{
|
|
12630
|
+
"name": "params",
|
|
12631
|
+
"description": "- `{ productIds }` — product ids to fetch (deduplicate before calling)"
|
|
12632
|
+
}
|
|
12633
|
+
],
|
|
12634
|
+
"returns": "`{ isSuccess, products }` — `products` is null on failure",
|
|
12609
12635
|
"returnType": "Promise<{\n isSuccess: boolean;\n products: IkasProduct[] | null;\n}>",
|
|
12610
|
-
"
|
|
12611
|
-
"
|
|
12636
|
+
"example": "```tsx\nimport { baseStore, bs_searchProductsById, cartStore, IkasStorefrontConfig } from \"@ikas/bp-storefront\";\n\n// Enforce per-cart quantity limits on cart lines:\nconst productIds = [\n ...new Set(\n (cartStore.cart?.orderLineItems ?? [])\n .map(item => item.variant.productId)\n .filter((id): id is string => !!id)\n ),\n];\nconst { products } = await bs_searchProductsById(baseStore, { productIds });\nconst maxByProductId = new Map<string, number | null>();\nfor (const p of products ?? []) {\n const channel = p.salesChannels?.find(sc => sc.id === IkasStorefrontConfig.salesChannelId);\n maxByProductId.set(p.id, channel?.maxQuantityPerCart ?? null);\n}\n```",
|
|
12637
|
+
"categories": [
|
|
12638
|
+
"Product",
|
|
12639
|
+
"Cart",
|
|
12640
|
+
"Search"
|
|
12641
|
+
],
|
|
12642
|
+
"related": [
|
|
12643
|
+
"bs_searchProductById",
|
|
12644
|
+
"changeItemQuantity"
|
|
12645
|
+
],
|
|
12612
12646
|
"isAsync": true,
|
|
12613
12647
|
"isClass": false,
|
|
12614
12648
|
"parameterTypes": [
|
package/dist/index.js
CHANGED
|
@@ -1682,6 +1682,44 @@ function suggestClosestNames(input, candidates, opts) {
|
|
|
1682
1682
|
.sort((a, b) => a.d - b.d);
|
|
1683
1683
|
return edits.slice(0, max).map((s) => s.name);
|
|
1684
1684
|
}
|
|
1685
|
+
/**
|
|
1686
|
+
* Formatted ` — matching sections: ...` suffix naming the guide sections that match the query,
|
|
1687
|
+
* so a hit buried mid-guide (e.g. "Quantity Limits" inside cart-patterns) is visible without
|
|
1688
|
+
* opening the full guide. Section bodies are scored on purpose: a query for an identifier that
|
|
1689
|
+
* appears only inside a section (an error code, a prop name) must still surface that section's
|
|
1690
|
+
* heading. Returns "" when the query matches most of the guide's sections — matchScore is
|
|
1691
|
+
* presence-based, so a broad query ("cart" against cart-patterns) ties every section and a
|
|
1692
|
+
* top-3 would just echo document order, hinting nothing.
|
|
1693
|
+
*/
|
|
1694
|
+
function sectionHint(content, query) {
|
|
1695
|
+
// Line walk instead of a heading-regex split: a `## ` line inside a fenced code block must
|
|
1696
|
+
// not become a pseudo-section (it would surface a heading that doesn't exist in the guide
|
|
1697
|
+
// and swallow the rest of the real section's body).
|
|
1698
|
+
const sections = [];
|
|
1699
|
+
let fenceOpen = false;
|
|
1700
|
+
for (const line of content.split("\n")) {
|
|
1701
|
+
if (/^\s*```/.test(line))
|
|
1702
|
+
fenceOpen = !fenceOpen;
|
|
1703
|
+
const headingMatch = fenceOpen ? null : line.match(/^#{2,4} (.+)/);
|
|
1704
|
+
if (headingMatch)
|
|
1705
|
+
sections.push({ heading: headingMatch[1].trim(), body: "" });
|
|
1706
|
+
else if (sections.length > 0)
|
|
1707
|
+
sections[sections.length - 1].body += line + "\n";
|
|
1708
|
+
}
|
|
1709
|
+
const scored = [];
|
|
1710
|
+
for (const { heading, body } of sections) {
|
|
1711
|
+
// Heading hits weigh double. The floor of 3 drops sections whose only signal is a single
|
|
1712
|
+
// squashed-identifier body match (worth 2) — a literal word hit (3) or any heading match
|
|
1713
|
+
// clears it.
|
|
1714
|
+
const score = matchScore(heading, query) * 2 + matchScore(body, query);
|
|
1715
|
+
if (score >= 3)
|
|
1716
|
+
scored.push({ heading, score });
|
|
1717
|
+
}
|
|
1718
|
+
if (scored.length === 0 || scored.length > sections.length / 2)
|
|
1719
|
+
return "";
|
|
1720
|
+
const top = scored.sort((a, b) => b.score - a.score).slice(0, 3);
|
|
1721
|
+
return ` — matching sections: ${top.map((s) => `"${s.heading}"`).join(", ")}`;
|
|
1722
|
+
}
|
|
1685
1723
|
function searchFunctions(query) {
|
|
1686
1724
|
const scored = storefrontData.functions
|
|
1687
1725
|
.map((fn) => {
|
|
@@ -1919,7 +1957,7 @@ server.tool("search_docs", "Search across all ikas storefront API docs, framewor
|
|
|
1919
1957
|
if (topics.length > 0) {
|
|
1920
1958
|
parts.push("\n## Matching Framework Topics\n");
|
|
1921
1959
|
for (const item of topics) {
|
|
1922
|
-
parts.push(`- **${item.topic.title}** (key: \`${item.key}\`) - ${item.topic.description}`);
|
|
1960
|
+
parts.push(`- **${item.topic.title}** (key: \`${item.key}\`) - ${item.topic.description}${sectionHint(item.topic.content, query)}`);
|
|
1923
1961
|
}
|
|
1924
1962
|
parts.push("");
|
|
1925
1963
|
parts.push("Use `get_framework_guide(topic)` to get full content for any topic.");
|
|
@@ -1935,7 +1973,7 @@ server.tool("search_docs", "Search across all ikas storefront API docs, framewor
|
|
|
1935
1973
|
if (migrationTopics.length > 0) {
|
|
1936
1974
|
parts.push("\n## Matching Migration Topics\n");
|
|
1937
1975
|
for (const item of migrationTopics) {
|
|
1938
|
-
parts.push(`- [migration] **${item.topic.title}** (key: \`${item.key}\`) - ${item.topic.description}`);
|
|
1976
|
+
parts.push(`- [migration] **${item.topic.title}** (key: \`${item.key}\`) - ${item.topic.description}${sectionHint(item.topic.content, query)}`);
|
|
1939
1977
|
}
|
|
1940
1978
|
parts.push("");
|
|
1941
1979
|
parts.push("Use `get_migration_guide(topic)` to get full content for any migration topic.");
|