@laioutr/app-shopware 0.14.4
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/LICENSE.md +21 -0
- package/README.md +146 -0
- package/dist/module.d.mts +88 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +60 -0
- package/dist/runtime/app/components/ShopwareEmbedFrame.d.vue.ts +14 -0
- package/dist/runtime/app/components/ShopwareEmbedFrame.vue +57 -0
- package/dist/runtime/app/components/ShopwareEmbedFrame.vue.d.ts +14 -0
- package/dist/runtime/app/composables/useShopwareEmbedBridge.d.ts +24 -0
- package/dist/runtime/app/composables/useShopwareEmbedBridge.js +22 -0
- package/dist/runtime/app/const/bridge.d.ts +63 -0
- package/dist/runtime/app/const/bridge.js +9 -0
- package/dist/runtime/app/image/providers/shopware.d.ts +7 -0
- package/dist/runtime/app/image/providers/shopware.js +44 -0
- package/dist/runtime/app/lib/createBridgeHandler.d.ts +44 -0
- package/dist/runtime/app/lib/createBridgeHandler.js +40 -0
- package/dist/runtime/app/lib/isTrustedOrigin.d.ts +9 -0
- package/dist/runtime/app/lib/isTrustedOrigin.js +8 -0
- package/dist/runtime/app/lib/parseBridgeMessage.d.ts +11 -0
- package/dist/runtime/app/lib/parseBridgeMessage.js +34 -0
- package/dist/runtime/app/plugins/pagetypes.d.ts +7 -0
- package/dist/runtime/app/plugins/pagetypes.js +6 -0
- package/dist/runtime/app/public/app-shopware/image-placeholder.svg +7 -0
- package/dist/runtime/app/public/app-shopware/shopware-logo.svg +10 -0
- package/dist/runtime/app/sections/SectionShopwareCheckout.d.vue.ts +0 -0
- package/dist/runtime/app/sections/SectionShopwareCheckout.vue +44 -0
- package/dist/runtime/app/sections/SectionShopwareCheckout.vue.d.ts +0 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/server/client/shopwareAdminClientFactory.d.ts +4 -0
- package/dist/runtime/server/client/shopwareAdminClientFactory.js +13 -0
- package/dist/runtime/server/client/shopwareClientFactory.d.ts +3 -0
- package/dist/runtime/server/client/shopwareClientFactory.js +18 -0
- package/dist/runtime/server/composable/useGetProductParentId.d.ts +4 -0
- package/dist/runtime/server/composable/useGetProductParentId.js +41 -0
- package/dist/runtime/server/const/checkout.d.ts +7 -0
- package/dist/runtime/server/const/checkout.js +2 -0
- package/dist/runtime/server/const/cookieKeys.d.ts +1 -0
- package/dist/runtime/server/const/cookieKeys.js +1 -0
- package/dist/runtime/server/const/fallbacks.d.ts +5 -0
- package/dist/runtime/server/const/fallbacks.js +14 -0
- package/dist/runtime/server/const/includes.d.ts +1 -0
- package/dist/runtime/server/const/includes.js +1 -0
- package/dist/runtime/server/const/passthroughTokens.d.ts +14 -0
- package/dist/runtime/server/const/passthroughTokens.js +10 -0
- package/dist/runtime/server/media-libraries/shopware.d.ts +20 -0
- package/dist/runtime/server/media-libraries/shopware.js +90 -0
- package/dist/runtime/server/middleware/defineShopware.d.ts +7 -0
- package/dist/runtime/server/middleware/defineShopware.js +33 -0
- package/dist/runtime/server/orchestr/auth/login.action.d.ts +2 -0
- package/dist/runtime/server/orchestr/auth/login.action.js +17 -0
- package/dist/runtime/server/orchestr/cart/add-item.action.d.ts +2 -0
- package/dist/runtime/server/orchestr/cart/add-item.action.js +46 -0
- package/dist/runtime/server/orchestr/cart/base.resolver.d.ts +2 -0
- package/dist/runtime/server/orchestr/cart/base.resolver.js +28 -0
- package/dist/runtime/server/orchestr/cart/cart-items.link.d.ts +2 -0
- package/dist/runtime/server/orchestr/cart/cart-items.link.js +10 -0
- package/dist/runtime/server/orchestr/cart/get-checkout-url.action.d.ts +10 -0
- package/dist/runtime/server/orchestr/cart/get-checkout-url.action.js +6 -0
- package/dist/runtime/server/orchestr/cart/get-current.query.d.ts +2 -0
- package/dist/runtime/server/orchestr/cart/get-current.query.js +9 -0
- package/dist/runtime/server/orchestr/cart/remove-items.action.d.ts +2 -0
- package/dist/runtime/server/orchestr/cart/remove-items.action.js +14 -0
- package/dist/runtime/server/orchestr/cart/update-items.action.d.ts +2 -0
- package/dist/runtime/server/orchestr/cart/update-items.action.js +16 -0
- package/dist/runtime/server/orchestr/cart-item/base.resolver.d.ts +2 -0
- package/dist/runtime/server/orchestr/cart-item/base.resolver.js +33 -0
- package/dist/runtime/server/orchestr/category/all.query.d.ts +2 -0
- package/dist/runtime/server/orchestr/category/all.query.js +15 -0
- package/dist/runtime/server/orchestr/category/base.resolver.d.ts +2 -0
- package/dist/runtime/server/orchestr/category/base.resolver.js +47 -0
- package/dist/runtime/server/orchestr/category/bySlug.query.d.ts +2 -0
- package/dist/runtime/server/orchestr/category/bySlug.query.js +12 -0
- package/dist/runtime/server/orchestr/category/child-categories.link.d.ts +2 -0
- package/dist/runtime/server/orchestr/category/child-categories.link.js +36 -0
- package/dist/runtime/server/orchestr/category/listing-page.page-index.d.ts +2 -0
- package/dist/runtime/server/orchestr/category/listing-page.page-index.js +79 -0
- package/dist/runtime/server/orchestr/category/menu-item.link.d.ts +2 -0
- package/dist/runtime/server/orchestr/category/menu-item.link.js +10 -0
- package/dist/runtime/server/orchestr/menu/base.resolver.d.ts +2 -0
- package/dist/runtime/server/orchestr/menu/base.resolver.js +63 -0
- package/dist/runtime/server/orchestr/menu/byAlias.query.d.ts +2 -0
- package/dist/runtime/server/orchestr/menu/byAlias.query.js +29 -0
- package/dist/runtime/server/orchestr/menu/byAlias.template.d.ts +2 -0
- package/dist/runtime/server/orchestr/menu/byAlias.template.js +25 -0
- package/dist/runtime/server/orchestr/newsletter/subscribe.action.d.ts +2 -0
- package/dist/runtime/server/orchestr/newsletter/subscribe.action.js +27 -0
- package/dist/runtime/server/orchestr/product/base.resolver.d.ts +2 -0
- package/dist/runtime/server/orchestr/product/base.resolver.js +119 -0
- package/dist/runtime/server/orchestr/product/breadcrumb.link.d.ts +2 -0
- package/dist/runtime/server/orchestr/product/breadcrumb.link.js +57 -0
- package/dist/runtime/server/orchestr/product/byCategoryId.query.d.ts +2 -0
- package/dist/runtime/server/orchestr/product/byCategoryId.query.js +47 -0
- package/dist/runtime/server/orchestr/product/byCategorySlug.query.d.ts +2 -0
- package/dist/runtime/server/orchestr/product/byCategorySlug.query.js +59 -0
- package/dist/runtime/server/orchestr/product/byCategorySlug.template.d.ts +2 -0
- package/dist/runtime/server/orchestr/product/byCategorySlug.template.js +40 -0
- package/dist/runtime/server/orchestr/product/bySlug.query.d.ts +2 -0
- package/dist/runtime/server/orchestr/product/bySlug.query.js +19 -0
- package/dist/runtime/server/orchestr/product/detail-page.page-index.d.ts +3 -0
- package/dist/runtime/server/orchestr/product/detail-page.page-index.js +58 -0
- package/dist/runtime/server/orchestr/product/reviews.link.d.ts +2 -0
- package/dist/runtime/server/orchestr/product/reviews.link.js +27 -0
- package/dist/runtime/server/orchestr/product/search.query.d.ts +2 -0
- package/dist/runtime/server/orchestr/product/search.query.js +43 -0
- package/dist/runtime/server/orchestr/product/variants.link.d.ts +2 -0
- package/dist/runtime/server/orchestr/product/variants.link.js +18 -0
- package/dist/runtime/server/orchestr/product-variant/base.resolver.d.ts +2 -0
- package/dist/runtime/server/orchestr/product-variant/base.resolver.js +129 -0
- package/dist/runtime/server/orchestr/review/base.resolver.d.ts +2 -0
- package/dist/runtime/server/orchestr/review/base.resolver.js +38 -0
- package/dist/runtime/server/orchestr/review/create-review.action.d.ts +2 -0
- package/dist/runtime/server/orchestr/review/create-review.action.js +14 -0
- package/dist/runtime/server/orchestr/suggested-search/suggested-search-entry.link.d.ts +2 -0
- package/dist/runtime/server/orchestr/suggested-search/suggested-search-entry.link.js +14 -0
- package/dist/runtime/server/orchestr/suggested-search/suggested-search.query.d.ts +2 -0
- package/dist/runtime/server/orchestr/suggested-search/suggested-search.query.js +54 -0
- package/dist/runtime/server/orchestr/suggested-search-entry/base.resolver.d.ts +2 -0
- package/dist/runtime/server/orchestr/suggested-search-entry/base.resolver.js +22 -0
- package/dist/runtime/server/orchestr-helper/isLinkSingle.d.ts +2 -0
- package/dist/runtime/server/orchestr-helper/isLinkSingle.js +1 -0
- package/dist/runtime/server/orchestr-helper/matchAndMap.d.ts +1 -0
- package/dist/runtime/server/orchestr-helper/matchAndMap.js +15 -0
- package/dist/runtime/server/orchestr-helper/requestedFields.d.ts +18 -0
- package/dist/runtime/server/orchestr-helper/requestedFields.js +145 -0
- package/dist/runtime/server/routes/adopt-session.post.d.ts +8 -0
- package/dist/runtime/server/routes/adopt-session.post.js +16 -0
- package/dist/runtime/server/routes/checkout.d.ts +16 -0
- package/dist/runtime/server/routes/checkout.js +31 -0
- package/dist/runtime/server/shopware-helper/adoptSession.d.ts +18 -0
- package/dist/runtime/server/shopware-helper/adoptSession.js +23 -0
- package/dist/runtime/server/shopware-helper/bootstrapContextToken.d.ts +18 -0
- package/dist/runtime/server/shopware-helper/bootstrapContextToken.js +22 -0
- package/dist/runtime/server/shopware-helper/cartErrors.d.ts +11 -0
- package/dist/runtime/server/shopware-helper/cartErrors.js +21 -0
- package/dist/runtime/server/shopware-helper/cartMapper.d.ts +14 -0
- package/dist/runtime/server/shopware-helper/cartMapper.js +83 -0
- package/dist/runtime/server/shopware-helper/categoryFlattener.d.ts +75 -0
- package/dist/runtime/server/shopware-helper/categoryFlattener.js +11 -0
- package/dist/runtime/server/shopware-helper/checkoutUrl.d.ts +12 -0
- package/dist/runtime/server/shopware-helper/checkoutUrl.js +5 -0
- package/dist/runtime/server/shopware-helper/contextTokenCookie.d.ts +11 -0
- package/dist/runtime/server/shopware-helper/contextTokenCookie.js +7 -0
- package/dist/runtime/server/shopware-helper/facetMapper.d.ts +38 -0
- package/dist/runtime/server/shopware-helper/facetMapper.js +79 -0
- package/dist/runtime/server/shopware-helper/fetchAllProductVariants.d.ts +137 -0
- package/dist/runtime/server/shopware-helper/fetchAllProductVariants.js +16 -0
- package/dist/runtime/server/shopware-helper/getCart.d.ts +10 -0
- package/dist/runtime/server/shopware-helper/getCart.js +4 -0
- package/dist/runtime/server/shopware-helper/isShopwareId.d.ts +4 -0
- package/dist/runtime/server/shopware-helper/isShopwareId.js +2 -0
- package/dist/runtime/server/shopware-helper/mappers/slugMapper.d.ts +10 -0
- package/dist/runtime/server/shopware-helper/mappers/slugMapper.js +9 -0
- package/dist/runtime/server/shopware-helper/mediaMapper.d.ts +8 -0
- package/dist/runtime/server/shopware-helper/mediaMapper.js +42 -0
- package/dist/runtime/server/shopware-helper/pageIndexEntries.d.ts +20 -0
- package/dist/runtime/server/shopware-helper/pageIndexEntries.js +22 -0
- package/dist/runtime/server/shopware-helper/persistContextToken.d.ts +13 -0
- package/dist/runtime/server/shopware-helper/persistContextToken.js +12 -0
- package/dist/runtime/server/shopware-helper/productLocate.d.ts +14 -0
- package/dist/runtime/server/shopware-helper/productLocate.js +9 -0
- package/dist/runtime/server/shopware-helper/readCategoryPageMeta.d.ts +10 -0
- package/dist/runtime/server/shopware-helper/readCategoryPageMeta.js +19 -0
- package/dist/runtime/server/shopware-helper/readProductPageMeta.d.ts +10 -0
- package/dist/runtime/server/shopware-helper/readProductPageMeta.js +20 -0
- package/dist/runtime/server/shopware-helper/resolveAdoptSession.d.ts +23 -0
- package/dist/runtime/server/shopware-helper/resolveAdoptSession.js +13 -0
- package/dist/runtime/server/shopware-helper/resolveCheckout.d.ts +39 -0
- package/dist/runtime/server/shopware-helper/resolveCheckout.js +24 -0
- package/dist/runtime/server/shopware-helper/sessionHandoff.d.ts +27 -0
- package/dist/runtime/server/shopware-helper/sessionHandoff.js +29 -0
- package/dist/runtime/server/shopware-helper/sortingMapper.d.ts +3 -0
- package/dist/runtime/server/shopware-helper/sortingMapper.js +7 -0
- package/dist/runtime/server/shopware-helper/storeApiPageFetcher.d.ts +20 -0
- package/dist/runtime/server/shopware-helper/storeApiPageFetcher.js +10 -0
- package/dist/runtime/server/shopware-helper/swTranslated.d.ts +7 -0
- package/dist/runtime/server/shopware-helper/swTranslated.js +4 -0
- package/dist/runtime/server/shopware-helper/system/getCurrentSystemEntities.d.ts +20 -0
- package/dist/runtime/server/shopware-helper/system/getCurrentSystemEntities.js +39 -0
- package/dist/runtime/server/shopware-helper/system/getSystemEntities.d.ts +31 -0
- package/dist/runtime/server/shopware-helper/system/getSystemEntities.js +47 -0
- package/dist/runtime/server/shopware-helper/useSeoResolver.d.ts +11 -0
- package/dist/runtime/server/shopware-helper/useSeoResolver.js +70 -0
- package/dist/runtime/server/tsconfig.json +3 -0
- package/dist/runtime/server/types/shopware.d.ts +29 -0
- package/dist/runtime/server/types/shopware.js +0 -0
- package/dist/runtime/server/types/storeApiTypes.d.ts +5677 -0
- package/dist/runtime/shared/const/checkout.d.ts +18 -0
- package/dist/runtime/shared/const/checkout.js +2 -0
- package/dist/runtime/shared/pageTypes/checkout.pagetype.d.ts +21 -0
- package/dist/runtime/shared/pageTypes/checkout.pagetype.js +12 -0
- package/dist/types.d.mts +3 -0
- package/package.json +96 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { isTrustedOrigin } from "./isTrustedOrigin.js";
|
|
2
|
+
import { parseBridgeMessage } from "./parseBridgeMessage.js";
|
|
3
|
+
export const createBridgeHandler = (options) => {
|
|
4
|
+
const sendInit = () => {
|
|
5
|
+
const frameWindow = options.getFrameWindow();
|
|
6
|
+
if (frameWindow && options.storefrontOrigin) {
|
|
7
|
+
options.postInit(frameWindow, options.storefrontOrigin);
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
const handleMessage = (event) => {
|
|
11
|
+
const frameWindow = options.getFrameWindow();
|
|
12
|
+
if (!frameWindow || event.source !== frameWindow) return;
|
|
13
|
+
if (!isTrustedOrigin(event.origin, options.storefrontOrigin)) return;
|
|
14
|
+
const message = parseBridgeMessage(event.data);
|
|
15
|
+
if (!message) return;
|
|
16
|
+
switch (message.type) {
|
|
17
|
+
case "laioutr:ready":
|
|
18
|
+
options.postInit(frameWindow, event.origin);
|
|
19
|
+
return;
|
|
20
|
+
case "laioutr:resize":
|
|
21
|
+
options.onResize?.(message.payload.height);
|
|
22
|
+
return;
|
|
23
|
+
case "laioutr:page-loaded":
|
|
24
|
+
options.onPageLoaded?.(message.payload);
|
|
25
|
+
return;
|
|
26
|
+
case "laioutr:checkout-finish":
|
|
27
|
+
options.onCheckoutFinish?.(message.payload.orderId);
|
|
28
|
+
return;
|
|
29
|
+
case "laioutr:pw-recovery":
|
|
30
|
+
options.onPwRecovery?.();
|
|
31
|
+
return;
|
|
32
|
+
case "laioutr:auth-changed":
|
|
33
|
+
options.onAuthChanged?.(message.payload);
|
|
34
|
+
return;
|
|
35
|
+
default:
|
|
36
|
+
message;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
return { handleMessage, sendInit };
|
|
40
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a `MessageEvent.origin` may be trusted as the embedded storefront.
|
|
3
|
+
*
|
|
4
|
+
* The parent frame only ever talks to the one storefront it embedded, so trust is an
|
|
5
|
+
* exact origin match against the configured storefront origin. An unset
|
|
6
|
+
* `storefrontOrigin` (misconfigured app) trusts nothing; an unparseable event origin
|
|
7
|
+
* (e.g. `"null"` from a sandboxed frame) is rejected.
|
|
8
|
+
*/
|
|
9
|
+
export declare const isTrustedOrigin: (eventOrigin: string, storefrontOrigin: string) => boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type BridgeInboundMessage } from '../const/bridge.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validate a raw `MessageEvent.data` against the bridge envelope and return a typed
|
|
4
|
+
* inbound message, or `null` for anything that isn't a well-formed message we handle.
|
|
5
|
+
*
|
|
6
|
+
* Rejects a wrong `source`/`version`, unknown `type`, and payloads missing their
|
|
7
|
+
* required fields (a `resize` without a numeric `height`, a `checkout-finish` without a
|
|
8
|
+
* string `orderId`). Contentless messages (`ready`, `pw-recovery`) always normalise to an
|
|
9
|
+
* empty payload.
|
|
10
|
+
*/
|
|
11
|
+
export declare const parseBridgeMessage: (data: unknown) => BridgeInboundMessage | null;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BRIDGE_SOURCE, BRIDGE_VERSION } from "../const/bridge.js";
|
|
2
|
+
const isObject = (value) => typeof value === "object" && value !== null;
|
|
3
|
+
export const parseBridgeMessage = (data) => {
|
|
4
|
+
if (!isObject(data)) return null;
|
|
5
|
+
if (data.source !== BRIDGE_SOURCE || data.version !== BRIDGE_VERSION) return null;
|
|
6
|
+
const payload = isObject(data.payload) ? data.payload : {};
|
|
7
|
+
switch (data.type) {
|
|
8
|
+
case "laioutr:ready":
|
|
9
|
+
return { type: "laioutr:ready", payload: {} };
|
|
10
|
+
case "laioutr:pw-recovery":
|
|
11
|
+
return { type: "laioutr:pw-recovery", payload: {} };
|
|
12
|
+
case "laioutr:resize":
|
|
13
|
+
return typeof payload.height === "number" ? { type: "laioutr:resize", payload: { height: payload.height } } : null;
|
|
14
|
+
case "laioutr:checkout-finish":
|
|
15
|
+
return typeof payload.orderId === "string" ? { type: "laioutr:checkout-finish", payload: { orderId: payload.orderId } } : null;
|
|
16
|
+
case "laioutr:page-loaded":
|
|
17
|
+
return typeof payload.path === "string" ? {
|
|
18
|
+
type: "laioutr:page-loaded",
|
|
19
|
+
payload: {
|
|
20
|
+
path: payload.path,
|
|
21
|
+
route: typeof payload.route === "string" ? payload.route : null,
|
|
22
|
+
navigationId: typeof payload.navigationId === "string" ? payload.navigationId : null,
|
|
23
|
+
salesChannelId: typeof payload.salesChannelId === "string" ? payload.salesChannelId : null
|
|
24
|
+
}
|
|
25
|
+
} : null;
|
|
26
|
+
case "laioutr:auth-changed":
|
|
27
|
+
return typeof payload.from === "string" ? {
|
|
28
|
+
type: "laioutr:auth-changed",
|
|
29
|
+
payload: typeof payload.code === "string" ? { from: payload.from, code: payload.code } : { from: payload.from }
|
|
30
|
+
} : null;
|
|
31
|
+
default:
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registers the app's page types so Studio offers them when an editor creates a page.
|
|
3
|
+
* `getMetadata` forces the token modules to load (registration is their import side
|
|
4
|
+
* effect); the reflect cache reads `pageTypeTokenRegistry.all()`.
|
|
5
|
+
*/
|
|
6
|
+
declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { defineNuxtPlugin } from "#app";
|
|
2
|
+
import { pageTypeTokenRegistry } from "@laioutr-core/core-types/frontend";
|
|
3
|
+
import { Checkout } from "../../shared/pageTypes/checkout.pagetype.js";
|
|
4
|
+
export default defineNuxtPlugin(() => {
|
|
5
|
+
[Checkout].forEach((token) => pageTypeTokenRegistry.getMetadata(token));
|
|
6
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="200" height="200" fill="#EFF0F3"/>
|
|
3
|
+
<path d="M129.167 62.5H70.8333C66.231 62.5 62.5 66.231 62.5 70.8333V129.167C62.5 133.769 66.231 137.5 70.8333 137.5H129.167C133.769 137.5 137.5 133.769 137.5 129.167V70.8333C137.5 66.231 133.769 62.5 129.167 62.5Z" stroke="#62636C" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
+
<path d="M87.5 95.8333C92.1024 95.8333 95.8333 92.1024 95.8333 87.5C95.8333 82.8976 92.1024 79.1667 87.5 79.1667C82.8976 79.1667 79.1667 82.8976 79.1667 87.5C79.1667 92.1024 82.8976 95.8333 87.5 95.8333Z" stroke="#62636C" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
5
|
+
<path d="M137.5 112.5L124.642 99.6417C123.079 98.0794 120.96 97.2018 118.75 97.2018C116.54 97.2018 114.421 98.0794 112.858 99.6417L75 137.5" stroke="#62636C" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
6
|
+
</svg>
|
|
7
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg width="111px" height="111px" viewBox="0 0 111 111" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
3
|
+
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
4
|
+
<g id="Artboard" transform="translate(1.000000, 1.000000)" fill="#189EFF" fill-rule="nonzero">
|
|
5
|
+
<g id="logo" transform="translate(-0.490000, -0.480000)">
|
|
6
|
+
<path d="M55.04,0 C68.64,0 81.7,5 91.8,14.09 C92.06,14.32 92.14,14.69 91.99,15.01 C91.85,15.32 91.52,15.51 91.17,15.46 C87.25,14.92 83.02,14.65 78.59,14.65 C62.56,14.65 49.54,18.23 40.95,24.99 C33.29,31.02 29.24,39.36 29.24,49.12 C29.24,59.99 33.41,68.59 41.97,75.41 C49.53,81.42 59.6,85.33 68.48,88.77 C75.94,91.66 82.99,94.4 87.77,98 C87.97,98.15 88.08,98.39 88.08,98.64 C88.08,98.89 87.96,99.12 87.76,99.27 C78.23,106.32 66.92,110.05 55.04,110.05 C40.33,110.05 26.51,104.32 16.12,93.93 C5.72,83.54 0,69.72 0,55.02 C0,40.33 5.73,26.51 16.12,16.12 C26.52,5.72 40.34,0 55.04,0 Z M77.49,35.98 C88.78,35.98 98.07,39.87 109.55,49.4 C109.71,49.53 109.81,49.73 109.83,49.94 C109.99,51.69 110.06,53.4 110.07,55.02 C110.07,61.93 108.8,68.68 106.3,75.08 C106.22,75.3 106.04,75.46 105.83,75.54 C105.74,75.57 105.65,75.59 105.56,75.59 C105.43,75.59 105.3,75.56 105.18,75.49 C98.64,71.86 91.51,69.2 84.62,66.63 C71.24,61.64 59.69,57.33 59.69,47.88 C59.69,44.51 61.1,41.63 63.77,39.57 C66.85,37.19 71.47,35.98 77.49,35.98 Z" id="Combined-Shape"></path>
|
|
7
|
+
</g>
|
|
8
|
+
</g>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const definition = defineSection({
|
|
3
|
+
component: "SectionShopwareCheckout",
|
|
4
|
+
studio: {
|
|
5
|
+
label: "Shopware Checkout",
|
|
6
|
+
description: "Embeds the Shopware storefront checkout on this page.",
|
|
7
|
+
tags: ["Checkout & Cart"]
|
|
8
|
+
},
|
|
9
|
+
slots: [],
|
|
10
|
+
schema: [
|
|
11
|
+
{
|
|
12
|
+
label: "Content",
|
|
13
|
+
fields: [
|
|
14
|
+
{
|
|
15
|
+
type: "link",
|
|
16
|
+
name: "finishLink",
|
|
17
|
+
label: "Order Confirmation Page",
|
|
18
|
+
description: "If set, the customer is redirected here after completing an order, with the order id appended as ?order=. If left empty, Shopware\u2019s own order confirmation page is shown inside the checkout frame instead."
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
});
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<script setup>
|
|
27
|
+
import { defineSection, definitionToProps, linkResolver, navigateTo, refreshNuxtData } from "#imports";
|
|
28
|
+
import { ADOPT_SESSION_ENDPOINT_PATH } from "../../shared/const/checkout";
|
|
29
|
+
import ShopwareEmbedFrame from "../components/ShopwareEmbedFrame.vue";
|
|
30
|
+
const props = defineProps(definitionToProps(definition));
|
|
31
|
+
const onCheckoutFinish = async (orderId) => {
|
|
32
|
+
if (!props.finishLink) return;
|
|
33
|
+
const path = linkResolver.resolve(props.finishLink);
|
|
34
|
+
await navigateTo({ path, query: { order: orderId } });
|
|
35
|
+
};
|
|
36
|
+
const onAuthChanged = async (payload) => {
|
|
37
|
+
await $fetch(ADOPT_SESSION_ENDPOINT_PATH, { method: "POST", body: { code: payload.code } });
|
|
38
|
+
await refreshNuxtData();
|
|
39
|
+
};
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<template>
|
|
43
|
+
<ShopwareEmbedFrame @checkout-finish="onCheckoutFinish" @auth-changed="onAuthChanged" />
|
|
44
|
+
</template>
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createAdminAPIClient } from "@shopware/api-client";
|
|
2
|
+
import { useRuntimeConfig } from "#imports";
|
|
3
|
+
export const shopwareAdminClientFactory = () => {
|
|
4
|
+
const { adminClientId, adminClientSecret, adminEndpoint } = useRuntimeConfig()["@laioutr/app-shopware"];
|
|
5
|
+
return createAdminAPIClient({
|
|
6
|
+
baseURL: adminEndpoint,
|
|
7
|
+
credentials: {
|
|
8
|
+
grant_type: "client_credentials",
|
|
9
|
+
client_id: adminClientId,
|
|
10
|
+
client_secret: adminClientSecret
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createAPIClient } from "@shopware/api-client";
|
|
2
|
+
import { getCookie, useNitroApp, useRuntimeConfig } from "#imports";
|
|
3
|
+
import { CONTEXT_TOKEN_COOKIE } from "../const/cookieKeys.js";
|
|
4
|
+
export const shopwareClientFactory = async (event) => {
|
|
5
|
+
const config = useRuntimeConfig()["@laioutr/app-shopware"];
|
|
6
|
+
const resolved = {};
|
|
7
|
+
await useNitroApp().hooks.callHook("shopware:context-token:resolve", { event, result: resolved });
|
|
8
|
+
const contextToken = resolved.token ?? getCookie(event, CONTEXT_TOKEN_COOKIE);
|
|
9
|
+
const client = createAPIClient({
|
|
10
|
+
baseURL: config.endpoint,
|
|
11
|
+
accessToken: config.accessToken,
|
|
12
|
+
contextToken
|
|
13
|
+
});
|
|
14
|
+
client.defaultHeaders.apply({
|
|
15
|
+
"sw-include-seo-urls": "true"
|
|
16
|
+
});
|
|
17
|
+
return client;
|
|
18
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { StorefrontClient } from '../types/shopware.js';
|
|
2
|
+
export declare const useGetProductParentId: (storefrontClient: StorefrontClient) => (id: string) => Promise<any>;
|
|
3
|
+
/** Store parent-ids in the cache. */
|
|
4
|
+
export declare const cacheProductParentIds: (productIdsToParentIds: [productId: string, parentId: string][]) => void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useEvent, useUserlandCache } from "#imports";
|
|
2
|
+
const useProductParentIdCache = () => useUserlandCache("shopware/product-parent-id");
|
|
3
|
+
const PRODUCT_PARENT_ID_CACHE_TTL = 60 * 60 * 24 * 7;
|
|
4
|
+
export const useGetProductParentId = (storefrontClient) => {
|
|
5
|
+
const cache = useProductParentIdCache();
|
|
6
|
+
return async (id) => {
|
|
7
|
+
const cachedParentId = await cache.getItem(id);
|
|
8
|
+
if (cachedParentId) {
|
|
9
|
+
return cachedParentId;
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
const response = await storefrontClient.invoke("readProduct post /product", {
|
|
13
|
+
body: {
|
|
14
|
+
ids: [id],
|
|
15
|
+
includes: { product: ["id", "parentId"] }
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
const parentId = response.data.elements?.[0]?.parentId;
|
|
19
|
+
if (parentId) {
|
|
20
|
+
cache.setItem(id, parentId, { ttl: PRODUCT_PARENT_ID_CACHE_TTL });
|
|
21
|
+
return parentId;
|
|
22
|
+
}
|
|
23
|
+
return void 0;
|
|
24
|
+
} catch {
|
|
25
|
+
return void 0;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export const cacheProductParentIds = (productIdsToParentIds) => {
|
|
30
|
+
const event = useEvent();
|
|
31
|
+
const cache = useProductParentIdCache();
|
|
32
|
+
event.waitUntil(
|
|
33
|
+
cache.setItems(
|
|
34
|
+
productIdsToParentIds.map(([productId, parentId]) => ({
|
|
35
|
+
key: productId,
|
|
36
|
+
value: parentId
|
|
37
|
+
})),
|
|
38
|
+
{ ttl: PRODUCT_PARENT_ID_CACHE_TTL }
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { ADOPT_SESSION_ENDPOINT_PATH, CHECKOUT_ENDPOINT_PATH } from '../../shared/const/checkout.js';
|
|
2
|
+
/**
|
|
3
|
+
* Internal Shopware route the handoff lands on after the storefront session adopts
|
|
4
|
+
* the cart context. Resolved server-side by the `LaioutrConnector` plugin's
|
|
5
|
+
* `connect-session` route.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CHECKOUT_REDIRECT_ROUTE = "frontend.checkout.confirm.page";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const CONTEXT_TOKEN_COOKIE = "sw-context-token";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CONTEXT_TOKEN_COOKIE = "sw-context-token";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { MediaImage } from '@laioutr-core/core-types/common';
|
|
2
|
+
export declare const FALLBACK_IMAGE_URL = "/app-shopware/image-placeholder.svg";
|
|
3
|
+
export declare const FALLBACK_IMAGE: MediaImage;
|
|
4
|
+
export declare const FALLBACK_CURRENCY_CODE = "EUR";
|
|
5
|
+
export declare const FALLBACK_CURRENCY_DECIMAL_DIGITS = 2;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const FALLBACK_IMAGE_URL = "/app-shopware/image-placeholder.svg";
|
|
2
|
+
export const FALLBACK_IMAGE = {
|
|
3
|
+
type: "image",
|
|
4
|
+
sources: [
|
|
5
|
+
{
|
|
6
|
+
provider: "none",
|
|
7
|
+
width: 200,
|
|
8
|
+
height: 200,
|
|
9
|
+
src: FALLBACK_IMAGE_URL
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
};
|
|
13
|
+
export const FALLBACK_CURRENCY_CODE = "EUR";
|
|
14
|
+
export const FALLBACK_CURRENCY_DECIMAL_DIGITS = 2;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const MediaIncludes: string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const MediaIncludes = ["id", "url", "thumbnails", "mimeType", "alt", "metaData", "customFields"];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const currentProductIdsToken: any;
|
|
2
|
+
export declare const categoriesToken: any;
|
|
3
|
+
/**
|
|
4
|
+
* Product ids returned by the storefront api may actually be variant-ids.
|
|
5
|
+
* In order for the Product.variants link to work, we need to know the parent-id of the products.
|
|
6
|
+
* If no parent-id is given here, assume that the product-id is the parent-id.
|
|
7
|
+
*
|
|
8
|
+
* We cannot let the product-queries return the parent-ids, because the parents contain no data.
|
|
9
|
+
*/
|
|
10
|
+
export declare const parentIdToDefaultVariantIdToken: any;
|
|
11
|
+
export declare const productsFragmentToken: any;
|
|
12
|
+
export declare const productVariantsToken: any;
|
|
13
|
+
export declare const suggestionResultsFragmentToken: any;
|
|
14
|
+
export declare const cartFragmentToken: any;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createPassthroughToken } from "#imports";
|
|
2
|
+
export const currentProductIdsToken = createPassthroughToken("@laioutr/app-shopware/currentProductIdsFragment");
|
|
3
|
+
export const categoriesToken = createPassthroughToken("@laioutr/app-shopware/categories");
|
|
4
|
+
export const parentIdToDefaultVariantIdToken = createPassthroughToken(
|
|
5
|
+
"@laioutr/app-shopware/parentIdToDefaultVariantId"
|
|
6
|
+
);
|
|
7
|
+
export const productsFragmentToken = createPassthroughToken("@laioutr/app-shopware/productsFragment");
|
|
8
|
+
export const productVariantsToken = createPassthroughToken("@laioutr/app-shopware/productVariants");
|
|
9
|
+
export const suggestionResultsFragmentToken = createPassthroughToken("@laioutr/app-shopware/completionResults");
|
|
10
|
+
export const cartFragmentToken = createPassthroughToken("@laioutr/app-shopware/cartFragment");
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MediaQuery } from '@laioutr-core/core-types/media-library';
|
|
2
|
+
/** Maps our `'<field>:<dir>'` sort key to a Shopware Criteria sort array. */
|
|
3
|
+
export declare const shopwareSortCriteria: (sorting?: string) => {
|
|
4
|
+
field: string;
|
|
5
|
+
order: string;
|
|
6
|
+
}[];
|
|
7
|
+
/** Scopes a browse to one folder level: a folder's id, or `null` for unfiled root assets (design §4.4). */
|
|
8
|
+
export declare const shopwareFolderFilter: (folderId: string | undefined) => {
|
|
9
|
+
type: "equals";
|
|
10
|
+
field: string;
|
|
11
|
+
value: string | null;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Compiles a `MediaQuery` into Shopware Criteria filters. `scope: 'all'` searches
|
|
15
|
+
* the whole library — no folder filter — because `folderId: undefined` means the
|
|
16
|
+
* root level, which in Shopware holds only unfiled assets (design §4.4).
|
|
17
|
+
*/
|
|
18
|
+
export declare const buildShopwareMediaFilters: (query: MediaQuery) => unknown[];
|
|
19
|
+
declare const _default: any;
|
|
20
|
+
export default _default;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { defineShopware } from "../middleware/defineShopware.js";
|
|
2
|
+
import { mapMedia } from "../shopware-helper/mediaMapper.js";
|
|
3
|
+
const SORTS = [
|
|
4
|
+
{ key: "uploadedAt:desc", label: "Newest first" },
|
|
5
|
+
{ key: "uploadedAt:asc", label: "Oldest first" },
|
|
6
|
+
{ key: "fileName:asc", label: "Name (A\u2013Z)" },
|
|
7
|
+
{ key: "fileName:desc", label: "Name (Z\u2013A)" },
|
|
8
|
+
{ key: "fileSize:desc", label: "Largest first" },
|
|
9
|
+
{ key: "fileSize:asc", label: "Smallest first" }
|
|
10
|
+
];
|
|
11
|
+
const generateSearchFilter = (search) => [
|
|
12
|
+
{ score: 500, query: { type: "contains", field: "media.fileName", value: search } },
|
|
13
|
+
{ score: 250, query: { type: "contains", field: "media.alt", value: search } },
|
|
14
|
+
{ score: 500, query: { type: "contains", field: "media.title", value: search } },
|
|
15
|
+
{ score: 500, query: { type: "contains", field: "media.tags.name", value: search } },
|
|
16
|
+
{ score: 500, query: { type: "contains", field: "media.mediaFolder.name", value: search } }
|
|
17
|
+
];
|
|
18
|
+
export const shopwareSortCriteria = (sorting) => {
|
|
19
|
+
const [field, dir] = (sorting ?? "uploadedAt:desc").split(":");
|
|
20
|
+
return [{ field, order: dir === "asc" ? "ASC" : "DESC" }];
|
|
21
|
+
};
|
|
22
|
+
export const shopwareFolderFilter = (folderId) => ({
|
|
23
|
+
type: "equals",
|
|
24
|
+
field: "mediaFolderId",
|
|
25
|
+
value: folderId ?? null
|
|
26
|
+
});
|
|
27
|
+
const SHOPWARE_MEDIA_TYPE = { image: "IMAGE", video: "VIDEO", audio: "AUDIO" };
|
|
28
|
+
export const buildShopwareMediaFilters = (query) => {
|
|
29
|
+
const filters = [];
|
|
30
|
+
if (query.scope !== "all") {
|
|
31
|
+
filters.push(shopwareFolderFilter(query.folderId));
|
|
32
|
+
}
|
|
33
|
+
if (query.type?.length) {
|
|
34
|
+
filters.push({ type: "equalsAny", field: "mediaType.name", value: query.type.map((t) => SHOPWARE_MEDIA_TYPE[t]) });
|
|
35
|
+
}
|
|
36
|
+
if (query.tags?.length) {
|
|
37
|
+
filters.push({ type: "equalsAny", field: "tags.name", value: query.tags });
|
|
38
|
+
}
|
|
39
|
+
return filters;
|
|
40
|
+
};
|
|
41
|
+
const fetchChildFolders = async (api, parentId) => {
|
|
42
|
+
const response = await api.invoke("searchMediaFolder post /search/media-folder", {
|
|
43
|
+
body: {
|
|
44
|
+
limit: 500,
|
|
45
|
+
filter: [{ type: "equals", field: "parentId", value: parentId ?? null }],
|
|
46
|
+
sort: [{ field: "name", order: "ASC" }]
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return response.data.data?.map((folder) => ({
|
|
50
|
+
id: folder.id,
|
|
51
|
+
name: folder.name,
|
|
52
|
+
parentId: folder.parentId ?? void 0,
|
|
53
|
+
childCount: folder.childCount ?? void 0
|
|
54
|
+
})) ?? [];
|
|
55
|
+
};
|
|
56
|
+
export default defineShopware.mediaLibrary({
|
|
57
|
+
capabilities: { search: true, tags: true, folders: true, sorts: SORTS },
|
|
58
|
+
list: async (query, ctx) => {
|
|
59
|
+
const api = ctx.adminClient;
|
|
60
|
+
const page = query.cursor ? Number(query.cursor) : 1;
|
|
61
|
+
const filters = buildShopwareMediaFilters(query);
|
|
62
|
+
const response = await api.invoke("searchMedia post /search/media", {
|
|
63
|
+
body: {
|
|
64
|
+
limit: query.limit,
|
|
65
|
+
page,
|
|
66
|
+
"total-count-mode": "exact",
|
|
67
|
+
sort: shopwareSortCriteria(query.sorting),
|
|
68
|
+
...filters.length ? { filter: filters } : {},
|
|
69
|
+
...query.term ? { query: generateSearchFilter(query.term) } : {}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const folders = query.cursor || query.scope === "all" || query.term ? void 0 : await fetchChildFolders(api, query.folderId);
|
|
73
|
+
const items = response.data.data?.map((media) => ({
|
|
74
|
+
media: mapMedia(media),
|
|
75
|
+
previewUrl: media.thumbnails?.[0]?.url ?? media.url ?? "",
|
|
76
|
+
externalId: media.id,
|
|
77
|
+
// Shopware stores the base name and extension separately; recompose the
|
|
78
|
+
// display filename (e.g. `swag_paypal_paypal` + `svg` → `swag_paypal_paypal.svg`).
|
|
79
|
+
fileName: media.fileName ? `${media.fileName}${media.fileExtension ? `.${media.fileExtension}` : ""}` : void 0
|
|
80
|
+
})) ?? [];
|
|
81
|
+
const total = response.data.total;
|
|
82
|
+
const seen = (page - 1) * query.limit + items.length;
|
|
83
|
+
return {
|
|
84
|
+
items,
|
|
85
|
+
...folders ? { folders } : {},
|
|
86
|
+
total,
|
|
87
|
+
nextCursor: items.length > 0 && total !== void 0 && seen < total ? String(page + 1) : void 0
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const defineShopware: any;
|
|
2
|
+
export declare const defineShopwareAction: any;
|
|
3
|
+
export declare const defineShopwareQuery: any;
|
|
4
|
+
export declare const defineShopwareLink: any;
|
|
5
|
+
export declare const defineShopwareComponentResolver: any;
|
|
6
|
+
export declare const defineShopwareQueryTemplateProvider: any;
|
|
7
|
+
export declare const defineShopwarePageIndex: any;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { defineOrchestr } from "#imports";
|
|
2
|
+
import { shopwareAdminClientFactory } from "../client/shopwareAdminClientFactory.js";
|
|
3
|
+
import { shopwareClientFactory } from "../client/shopwareClientFactory.js";
|
|
4
|
+
import { getCurrentSystemEntities } from "../shopware-helper/system/getCurrentSystemEntities.js";
|
|
5
|
+
import { getCachedSystemEntities } from "../shopware-helper/system/getSystemEntities.js";
|
|
6
|
+
export const defineShopware = defineOrchestr.meta({
|
|
7
|
+
app: "@laioutr-core/shopware",
|
|
8
|
+
logoUrl: "/app-shopware/shopware-logo.svg",
|
|
9
|
+
label: "Shopware"
|
|
10
|
+
}).extendRequest(async (args) => {
|
|
11
|
+
const storefrontClient = await shopwareClientFactory(args.event);
|
|
12
|
+
const adminClient = shopwareAdminClientFactory();
|
|
13
|
+
const systemEntities = await getCachedSystemEntities(storefrontClient);
|
|
14
|
+
const currentSystemEntities = getCurrentSystemEntities(systemEntities, args.clientEnv);
|
|
15
|
+
storefrontClient.defaultHeaders["sw-currency-id"] = currentSystemEntities.currency.id;
|
|
16
|
+
storefrontClient.defaultHeaders["sw-language-id"] = currentSystemEntities.locale.languageId;
|
|
17
|
+
return {
|
|
18
|
+
context: {
|
|
19
|
+
storefrontClient,
|
|
20
|
+
adminClient,
|
|
21
|
+
systemEntities,
|
|
22
|
+
currentSystemEntities,
|
|
23
|
+
/** The systems current currency iso code */
|
|
24
|
+
swCurrency: currentSystemEntities.currency.iso
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
export const defineShopwareAction = defineShopware.actionHandler;
|
|
29
|
+
export const defineShopwareQuery = defineShopware.queryHandler;
|
|
30
|
+
export const defineShopwareLink = defineShopware.linkHandler;
|
|
31
|
+
export const defineShopwareComponentResolver = defineShopware.componentResolver;
|
|
32
|
+
export const defineShopwareQueryTemplateProvider = defineShopware.queryTemplateProvider;
|
|
33
|
+
export const defineShopwarePageIndex = defineShopware.pageIndex;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AuthLoginAction } from "@laioutr-core/canonical-types/ecommerce";
|
|
2
|
+
import { defineShopwareAction } from "../../middleware/defineShopware.js";
|
|
3
|
+
import { persistContextToken } from "../../shopware-helper/persistContextToken.js";
|
|
4
|
+
export default defineShopwareAction(AuthLoginAction, async ({ context, input, event }) => {
|
|
5
|
+
try {
|
|
6
|
+
context.storefrontClient.hook("onContextChanged", (newContextToken) => {
|
|
7
|
+
persistContextToken(event, newContextToken).catch(() => {
|
|
8
|
+
});
|
|
9
|
+
});
|
|
10
|
+
const res = await context.storefrontClient.invoke("loginCustomer post /account/login", {
|
|
11
|
+
body: { username: input.email, password: input.password }
|
|
12
|
+
});
|
|
13
|
+
return { success: res.status === 200 };
|
|
14
|
+
} catch (err) {
|
|
15
|
+
return { success: false, message: err.message };
|
|
16
|
+
}
|
|
17
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { CartAddItemsAction } from "@laioutr-core/canonical-types/ecommerce";
|
|
2
|
+
import { defineShopwareAction } from "../../middleware/defineShopware.js";
|
|
3
|
+
import { handleCartMutationErrors } from "../../shopware-helper/cartErrors.js";
|
|
4
|
+
import { persistContextToken } from "../../shopware-helper/persistContextToken.js";
|
|
5
|
+
export default defineShopwareAction(CartAddItemsAction, async ({ event, context, input }) => {
|
|
6
|
+
const { storefrontClient } = context;
|
|
7
|
+
const products = input.filter((i) => i.type === "product");
|
|
8
|
+
const skuItems = input.filter((i) => i.type === "sku");
|
|
9
|
+
if (products.length > 0) {
|
|
10
|
+
const cart = await storefrontClient.invoke("addLineItem post /checkout/cart/line-item", {
|
|
11
|
+
body: {
|
|
12
|
+
items: products.map((product) => ({
|
|
13
|
+
children: {},
|
|
14
|
+
deliveryInformation: { apiAlias: "cart_delivery_information" },
|
|
15
|
+
id: product.variantId ?? product.productId,
|
|
16
|
+
payload: {
|
|
17
|
+
type: product.type,
|
|
18
|
+
id: product.variantId ?? product.productId
|
|
19
|
+
},
|
|
20
|
+
quantity: product.quantity,
|
|
21
|
+
states: ["is-physical"],
|
|
22
|
+
type: product.type
|
|
23
|
+
}))
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
await persistContextToken(event, cart.data.token);
|
|
27
|
+
handleCartMutationErrors(cart.data.errors);
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
items: [
|
|
31
|
+
...products.map((product) => ({
|
|
32
|
+
status: "added",
|
|
33
|
+
productId: product.productId,
|
|
34
|
+
variantId: product.variantId,
|
|
35
|
+
quantity: product.quantity
|
|
36
|
+
})),
|
|
37
|
+
// SKU resolution is not implemented for Shopware yet — report the rows
|
|
38
|
+
// as rejected instead of dropping them silently.
|
|
39
|
+
...skuItems.map((item) => ({
|
|
40
|
+
status: "rejected",
|
|
41
|
+
sku: item.sku,
|
|
42
|
+
reason: "not-supported"
|
|
43
|
+
}))
|
|
44
|
+
]
|
|
45
|
+
};
|
|
46
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useRuntimeConfig } from "#imports";
|
|
2
|
+
import { CartBase, CartCost } from "@laioutr-core/canonical-types/entity/cart";
|
|
3
|
+
import { Checkout } from "../../../shared/pageTypes/checkout.pagetype.js";
|
|
4
|
+
import { cartFragmentToken } from "../../const/passthroughTokens.js";
|
|
5
|
+
import { defineShopwareComponentResolver } from "../../middleware/defineShopware.js";
|
|
6
|
+
import { mapCartCost } from "../../shopware-helper/cartMapper.js";
|
|
7
|
+
import { getCart } from "../../shopware-helper/getCart.js";
|
|
8
|
+
export default defineShopwareComponentResolver({
|
|
9
|
+
entityType: "Cart",
|
|
10
|
+
label: "Shopware Cart Component Resolver",
|
|
11
|
+
provides: [CartBase, CartCost],
|
|
12
|
+
resolve: async ({ context, $entity, passthrough }) => {
|
|
13
|
+
const cart = passthrough.get(cartFragmentToken) ?? await getCart(context.storefrontClient);
|
|
14
|
+
passthrough.set(cartFragmentToken, cart);
|
|
15
|
+
const config = useRuntimeConfig()["@laioutr/app-shopware"];
|
|
16
|
+
const totalQuantity = (cart.lineItems ?? []).reduce((sum, li) => sum + (li.quantity ?? 0), 0);
|
|
17
|
+
const checkoutLink = config.storefrontUrl ? { type: "pageType", pageType: Checkout } : void 0;
|
|
18
|
+
return {
|
|
19
|
+
entities: [
|
|
20
|
+
$entity({
|
|
21
|
+
id: cart.token ?? "",
|
|
22
|
+
base: () => ({ totalQuantity, checkoutLink }),
|
|
23
|
+
cost: () => mapCartCost(cart, context.swCurrency)
|
|
24
|
+
})
|
|
25
|
+
]
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
});
|