Skip to content

Commit

Permalink
Merge pull request #17 from deco-cx/feat/shopify-proxy
Browse files Browse the repository at this point in the history
Feat/shopify proxy
  • Loading branch information
tlgimenes authored Sep 1, 2023
2 parents 62d50d7 + 21b7e91 commit 77efcf9
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 27 deletions.
6 changes: 1 addition & 5 deletions shopify/hooks/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,7 @@ const enqueue = (
};

const load = async (signal: AbortSignal) => {
const { cart } = await Runtime.invoke({
cart: {
key: "shopify/loaders/cart.ts",
},
}, { signal });
const cart = await Runtime.shopify.loaders.cart({}, {signal})

return {
cart,
Expand Down
16 changes: 15 additions & 1 deletion shopify/hooks/useCart.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import type { AnalyticsItem } from "../../commerce/types.ts";
import { Runtime } from "../runtime.ts";
import { Cart } from "../utils/types.ts";
import { Cart, Item } from "../utils/types.ts";
import { state as storeState } from "./context.ts";

export const itemToAnalyticsItem = (
item: Item & { quantity: number },
index: number,
): AnalyticsItem => ({
item_id: item.id,
item_name: item.merchandise.product.title,
discount: item.cost.compareAtAmountPerQuantity ? item.cost.compareAtAmountPerQuantity.amount - item.cost.amountPerQuantity?.amount : 0,
item_variant: item.merchandise.title,
price: item.cost.amountPerQuantity.amount,
index,
quantity: item.quantity,
});

const { cart, loading } = storeState;

const wrap =
Expand Down
104 changes: 104 additions & 0 deletions shopify/loaders/proxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { Route } from "../../website/flags/audience.ts";
import { AppContext } from "../mod.ts";

const PATHS_TO_PROXY = [
"/checkouts/*",
"/cart/*",
"/account",
"/account/*",
"/password",
"/password/*",
"/challenge",
"/challenge/*",
];
const decoSiteMapUrl = "/sitemap/deco.xml";

const buildProxyRoutes = (
{ storeName, extraPaths, includeSiteMap, generateDecoSiteMap }: {
storeName?: string;
extraPaths: string[];
includeSiteMap?: string[];
generateDecoSiteMap?: boolean;
},
) => {
const publicUrl = new URL(`https://${storeName}.myshopify.com`);

try {
const hostname = publicUrl.hostname;

// Rejects TLD mystore.com, keep this if Shopify doesn't support
if (!hostname || hostname.split(".").length <= 2) {
throw new Error(`Invalid hostname from '${publicUrl}'`);
}

// TODO @lucis: Fix the proxy, MITM

const urlToProxy = `https://${hostname}`;
const hostToUse = hostname;

const routeFromPath = (pathTemplate: string): Route => ({
pathTemplate,
handler: {
value: {
__resolveType: "website/handlers/proxy.ts",
url: urlToProxy,
host: hostToUse,
},
},
});
const routesFromPaths = [...PATHS_TO_PROXY, ...extraPaths].map(
routeFromPath,
);

const [_include, routes] = generateDecoSiteMap
? [[...(includeSiteMap ?? []), decoSiteMapUrl], [{
pathTemplate: decoSiteMapUrl,
handler: {
value: {
__resolveType: "website/handlers/sitemap.ts",
},
},
}]]
: [includeSiteMap, []];

return [
...routes,
...routesFromPaths,
];
} catch (e) {
console.log("Error parsing publicUrl from Shopify");
console.error(e);
return [];
}
};

export interface Props {
extraPathsToProxy?: string[];
/**
* @title Other site maps to include
*/
includeSiteMap?: string[];
/**
* @title If deco site map should be exposed at /deco-sitemap.xml
*/
generateDecoSiteMap?: boolean;
}

/**
* @title Shopify Proxy Routes
*/
function loader(
{ extraPathsToProxy = [], includeSiteMap = [], generateDecoSiteMap = true }:
Props,
_req: Request,
ctx: AppContext,
): Route[] {
return buildProxyRoutes({
generateDecoSiteMap,
includeSiteMap,
storeName: ctx.storeName,
extraPaths: extraPathsToProxy,
});
}

export default loader;
6 changes: 4 additions & 2 deletions shopify/manifest.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@
import * as $$$0 from "./loaders/ProductList.ts";
import * as $$$1 from "./loaders/ProductDetailsPage.ts";
import * as $$$2 from "./loaders/ProductListingPage.ts";
import * as $$$3 from "./loaders/cart.ts";
import * as $$$3 from "./loaders/proxy.ts";
import * as $$$4 from "./loaders/cart.ts";
import * as $$$$$$$$$0 from "./actions/cart/updateCoupons.ts";
import * as $$$$$$$$$1 from "./actions/cart/updateItems.ts";
import * as $$$$$$$$$2 from "./actions/cart/addItems.ts";

const manifest = {
"loaders": {
"shopify/loaders/cart.ts": $$$3,
"shopify/loaders/cart.ts": $$$4,
"shopify/loaders/ProductDetailsPage.ts": $$$1,
"shopify/loaders/ProductList.ts": $$$0,
"shopify/loaders/ProductListingPage.ts": $$$2,
"shopify/loaders/proxy.ts": $$$3,
},
"actions": {
"shopify/actions/cart/addItems.ts": $$$$$$$$$2,
Expand Down
40 changes: 21 additions & 19 deletions shopify/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,28 +140,30 @@ export interface Image {
altText: string;
}

export interface Item{
id: string;
quantity: number;
merchandise: {
id: string;
title: string;
product: {
title: string;
};
image: Image;
price: Money;
};
cost: {
totalAmount: Money;
subtotalAmount: Money;
amountPerQuantity: Money;
compareAtAmountPerQuantity: Money;
};
}

export interface CartData {
id: string;
lines?: {
nodes: {
id: string;
quantity: number;
merchandise: {
id: string;
title: string;
product: {
title: string;
};
image: Image;
price: Money;
};
cost: {
totalAmount: Money;
subtotalAmount: Money;
amountPerQuantity: Money;
compareAtAmountPerQuantity: Money;
};
}[];
nodes: Item[];
};
checkoutUrl?: string;
cost?: {
Expand Down

0 comments on commit 77efcf9

Please sign in to comment.