@decocms/apps-shopify 8.1.0-next.0 → 8.1.0-next.2

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.
Files changed (54) hide show
  1. package/dist/client.d.ts +36 -0
  2. package/dist/client.d.ts.map +1 -0
  3. package/dist/client.js +82 -0
  4. package/dist/client.js.map +1 -0
  5. package/dist/graphqlOperationName.d.ts +36 -0
  6. package/dist/graphqlOperationName.d.ts.map +1 -0
  7. package/dist/graphqlOperationName.js +59 -0
  8. package/dist/graphqlOperationName.js.map +1 -0
  9. package/dist/index.d.ts +6 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +6 -0
  12. package/dist/index.js.map +1 -0
  13. package/package.json +16 -29
  14. package/src/client.ts +113 -47
  15. package/src/index.ts +9 -51
  16. package/src/actions/cart/addItems.ts +0 -36
  17. package/src/actions/cart/updateCoupons.ts +0 -31
  18. package/src/actions/cart/updateItems.ts +0 -31
  19. package/src/actions/user/signIn.ts +0 -40
  20. package/src/actions/user/signUp.ts +0 -31
  21. package/src/init.ts +0 -39
  22. package/src/loaders/ProductDetailsPage.ts +0 -31
  23. package/src/loaders/ProductList.ts +0 -102
  24. package/src/loaders/ProductListingPage.ts +0 -172
  25. package/src/loaders/RelatedProducts.ts +0 -42
  26. package/src/loaders/cart.ts +0 -74
  27. package/src/loaders/shop.ts +0 -35
  28. package/src/loaders/user.ts +0 -39
  29. package/src/manifest.gen.ts +0 -39
  30. package/src/mod.ts +0 -67
  31. package/src/registry.ts +0 -9
  32. package/src/utils/__tests__/instrumentedFetch.test.ts +0 -84
  33. package/src/utils/__tests__/operationRouter.test.ts +0 -56
  34. package/src/utils/__tests__/transform.test.ts +0 -216
  35. package/src/utils/admin/admin.ts +0 -57
  36. package/src/utils/admin/queries.ts +0 -29
  37. package/src/utils/cart.ts +0 -32
  38. package/src/utils/cookies.ts +0 -82
  39. package/src/utils/enums.ts +0 -438
  40. package/src/utils/graphql.ts +0 -70
  41. package/src/utils/graphqlOperationName.ts +0 -2
  42. package/src/utils/instrumentedFetch.ts +0 -56
  43. package/src/utils/operationRouter.ts +0 -70
  44. package/src/utils/storefront/queries.ts +0 -525
  45. package/src/utils/storefront/storefront.graphql.gen.ts +0 -129
  46. package/src/utils/transform.ts +0 -430
  47. package/src/utils/types.ts +0 -191
  48. package/src/utils/user.ts +0 -23
  49. package/src/utils/utils.ts +0 -159
  50. package/src/v8/client.test.ts +0 -136
  51. package/src/v8/client.ts +0 -125
  52. package/src/v8/graphqlOperationName.test.ts +0 -80
  53. package/tsconfig.json +0 -7
  54. /package/src/{v8/graphqlOperationName.ts → graphqlOperationName.ts} +0 -0
@@ -1,31 +0,0 @@
1
- import { getShopifyClient } from "../../client";
2
- import type { ShopifyCart } from "../../loaders/cart";
3
- import { getCartCookie, setCartCookie } from "../../utils/cart";
4
- import { UpdateItems } from "../../utils/storefront/queries";
5
-
6
- export interface UpdateItemsProps {
7
- lines: Array<{ id: string; quantity: number }>;
8
- requestHeaders: Headers;
9
- responseHeaders?: Headers;
10
- }
11
-
12
- export default async function updateItems({
13
- lines,
14
- requestHeaders,
15
- responseHeaders,
16
- }: UpdateItemsProps): Promise<ShopifyCart | null> {
17
- const client = getShopifyClient();
18
- const cartId = getCartCookie(requestHeaders);
19
-
20
- if (!cartId) throw new Error("Missing cart cookie");
21
-
22
- const data = await client.query<{
23
- payload?: { cart?: ShopifyCart };
24
- }>(UpdateItems, { cartId, lines });
25
-
26
- if (responseHeaders) {
27
- setCartCookie(responseHeaders, cartId);
28
- }
29
-
30
- return data.payload?.cart ?? null;
31
- }
@@ -1,40 +0,0 @@
1
- import { getShopifyClient } from "../../client";
2
- import { SignInWithEmailAndPassword } from "../../utils/storefront/queries";
3
- import { getUserCookie, setUserCookie } from "../../utils/user";
4
-
5
- export interface SignInProps {
6
- email: string;
7
- password: string;
8
- requestHeaders: Headers;
9
- responseHeaders?: Headers;
10
- }
11
-
12
- export interface SignInResult {
13
- customerAccessTokenCreate: {
14
- customerAccessToken?: { accessToken: string; expiresAt: string } | null;
15
- customerUserErrors?: Array<{ code?: string; message: string }>;
16
- };
17
- }
18
-
19
- export default async function signIn(props: SignInProps): Promise<SignInResult | null> {
20
- const client = getShopifyClient();
21
- const { email, password, requestHeaders, responseHeaders } = props;
22
-
23
- const existingToken = getUserCookie(requestHeaders);
24
- if (existingToken) return null;
25
-
26
- try {
27
- const data = await client.query<SignInResult>(SignInWithEmailAndPassword, { email, password });
28
-
29
- if (data.customerAccessTokenCreate.customerAccessToken && responseHeaders) {
30
- setUserCookie(
31
- responseHeaders,
32
- data.customerAccessTokenCreate.customerAccessToken.accessToken,
33
- );
34
- }
35
-
36
- return data;
37
- } catch {
38
- return null;
39
- }
40
- }
@@ -1,31 +0,0 @@
1
- import { getShopifyClient } from "../../client";
2
- import { RegisterAccount } from "../../utils/storefront/queries";
3
-
4
- export interface SignUpProps {
5
- email: string;
6
- password: string;
7
- firstName?: string;
8
- lastName?: string;
9
- acceptsMarketing?: boolean;
10
- }
11
-
12
- export interface SignUpResult {
13
- customerCreate: {
14
- customer?: { id: string } | null;
15
- customerUserErrors?: Array<{ code?: string; message: string }>;
16
- };
17
- }
18
-
19
- export default async function signUp(props: SignUpProps): Promise<SignUpResult> {
20
- const client = getShopifyClient();
21
-
22
- const data = await client.query<SignUpResult>(RegisterAccount, {
23
- email: props.email,
24
- password: props.password,
25
- firstName: props.firstName,
26
- lastName: props.lastName,
27
- acceptsMarketing: props.acceptsMarketing,
28
- });
29
-
30
- return data;
31
- }
package/src/init.ts DELETED
@@ -1,39 +0,0 @@
1
- import { configureShopify } from "./client";
2
-
3
- let initialized = false;
4
-
5
- /**
6
- * Initialize Shopify from raw block data.
7
- * The site is responsible for reading the blocks and passing the config here.
8
- */
9
- export function initShopify(config: { storeName: string; storefrontAccessToken: string }) {
10
- if (initialized) return;
11
-
12
- if (!config.storeName || !config.storefrontAccessToken) {
13
- console.warn("[Shopify] Missing storeName or storefrontAccessToken.");
14
- return;
15
- }
16
-
17
- console.log(`[Shopify] Initializing: ${config.storeName}.myshopify.com`);
18
- configureShopify(config);
19
- initialized = true;
20
- }
21
-
22
- /**
23
- * Initialize Shopify from a blocks map (convenience wrapper).
24
- * Looks for the "deco-shopify" block and extracts credentials.
25
- */
26
- export function initShopifyFromBlocks(blocks: Record<string, unknown>) {
27
- const shopifyBlock = blocks["deco-shopify"] as
28
- | { storeName: string; storefrontAccessToken: string }
29
- | undefined;
30
- if (!shopifyBlock) {
31
- console.warn("[Shopify] No deco-shopify block found.");
32
- return;
33
- }
34
-
35
- initShopify({
36
- storeName: shopifyBlock.storeName,
37
- storefrontAccessToken: shopifyBlock.storefrontAccessToken,
38
- });
39
- }
@@ -1,31 +0,0 @@
1
- import type { ProductDetailsPage } from "@decocms/apps-commerce/types";
2
- import { getShopifyClient } from "../client";
3
- import { GetProduct } from "../utils/storefront/queries";
4
- import { type ProductShopify, toProductPage } from "../utils/transform";
5
- import type { Metafield } from "../utils/types";
6
-
7
- export interface Props {
8
- slug: string;
9
- metafields?: Metafield[];
10
- }
11
-
12
- export default async function productDetailsPageLoader(
13
- props: Props,
14
- url?: URL,
15
- ): Promise<ProductDetailsPage | null> {
16
- const client = getShopifyClient();
17
- const { slug, metafields = [] } = props;
18
-
19
- const splitted = slug?.split("-") ?? [];
20
- const maybeSkuId = Number(splitted[splitted.length - 1]);
21
- const handle = splitted.slice(0, maybeSkuId ? -1 : undefined).join("-");
22
-
23
- const data = await client.query<{ product?: ProductShopify }>(GetProduct, {
24
- handle,
25
- identifiers: metafields,
26
- });
27
-
28
- if (!data?.product) return null;
29
-
30
- return toProductPage(data.product, url ?? new URL("https://localhost"), maybeSkuId || undefined);
31
- }
@@ -1,102 +0,0 @@
1
- import type { Product } from "@decocms/apps-commerce/types";
2
- import { getShopifyClient } from "../client";
3
- import { ProductsByCollection, SearchProducts } from "../utils/storefront/queries";
4
- import { type ProductShopify, toProduct } from "../utils/transform";
5
- import type { Metafield } from "../utils/types";
6
- import {
7
- type CollectionSortKeys,
8
- type SearchSortKeys,
9
- searchSortShopify,
10
- sortShopify,
11
- } from "../utils/utils";
12
-
13
- export interface QueryProps {
14
- query: string;
15
- count: number;
16
- sort?: SearchSortKeys;
17
- }
18
-
19
- export interface CollectionProps {
20
- collection: string;
21
- count: number;
22
- sort?: CollectionSortKeys;
23
- }
24
-
25
- export interface FilterProps {
26
- tags?: string[];
27
- productTypes?: string[];
28
- productVendors?: string[];
29
- priceMin?: number;
30
- priceMax?: number;
31
- variantOptions?: { name: string; value: string }[];
32
- }
33
-
34
- export type Props = {
35
- props: QueryProps | CollectionProps;
36
- filters?: FilterProps;
37
- metafields?: Metafield[];
38
- };
39
-
40
- const isQueryList = (p: QueryProps | CollectionProps): p is QueryProps =>
41
- "query" in p && typeof p.query === "string" && typeof p.count === "number";
42
-
43
- export default async function productListLoader(
44
- expandedProps: Props,
45
- url?: URL,
46
- ): Promise<Product[] | null> {
47
- const client = getShopifyClient();
48
-
49
- const props = expandedProps.props ?? (expandedProps as unknown as Props["props"]);
50
-
51
- const count = props.count ?? 12;
52
- const metafields = expandedProps.metafields || [];
53
- const sort = props.sort ?? "";
54
-
55
- const filters: Record<string, unknown>[] = [];
56
- for (const tag of expandedProps.filters?.tags ?? []) {
57
- filters.push({ tag });
58
- }
59
- for (const productType of expandedProps.filters?.productTypes ?? []) {
60
- filters.push({ productType });
61
- }
62
- for (const productVendor of expandedProps.filters?.productVendors ?? []) {
63
- filters.push({ productVendor });
64
- }
65
- if (expandedProps.filters?.priceMin != null)
66
- filters.push({ price: { min: expandedProps.filters.priceMin } });
67
- if (expandedProps.filters?.priceMax != null)
68
- filters.push({ price: { max: expandedProps.filters.priceMax } });
69
- for (const variantOption of expandedProps.filters?.variantOptions ?? []) {
70
- filters.push({ variantOption });
71
- }
72
-
73
- let shopifyProducts: { nodes: ProductShopify[] } | undefined;
74
-
75
- if (isQueryList(props)) {
76
- const data = await client.query<{ search: { nodes: ProductShopify[] } }>(SearchProducts, {
77
- first: count,
78
- query: props.query,
79
- productFilters: filters,
80
- identifiers: metafields,
81
- ...searchSortShopify[sort],
82
- });
83
- shopifyProducts = data.search;
84
- } else {
85
- const data = await client.query<{
86
- collection?: { products: { nodes: ProductShopify[] } };
87
- }>(ProductsByCollection, {
88
- first: count,
89
- handle: (props as CollectionProps).collection,
90
- filters,
91
- identifiers: metafields,
92
- ...sortShopify[sort],
93
- });
94
- shopifyProducts = data.collection?.products;
95
- }
96
-
97
- const baseUrl = url ?? new URL("https://localhost");
98
-
99
- const products = shopifyProducts?.nodes.map((p) => toProduct(p, p.variants.nodes[0], baseUrl));
100
-
101
- return products ?? [];
102
- }
@@ -1,172 +0,0 @@
1
- import type { ProductListingPage } from "@decocms/apps-commerce/types";
2
- import { getShopifyClient } from "../client";
3
- import { ProductsByCollection, SearchProducts } from "../utils/storefront/queries";
4
- import { type ProductShopify, toFilter, toProduct } from "../utils/transform";
5
- import type { Metafield } from "../utils/types";
6
- import {
7
- getFiltersByUrl,
8
- searchSortOptions,
9
- searchSortShopify,
10
- sortOptions,
11
- sortShopify,
12
- } from "../utils/utils";
13
-
14
- interface PageInfo {
15
- hasNextPage: boolean;
16
- hasPreviousPage: boolean;
17
- endCursor?: string;
18
- startCursor?: string;
19
- }
20
-
21
- interface FilterNode {
22
- id: string;
23
- label: string;
24
- type: string;
25
- values: Array<{ id: string; label: string; count: number; input: string }>;
26
- }
27
-
28
- interface ProductConnection {
29
- nodes: ProductShopify[];
30
- pageInfo: PageInfo;
31
- filters?: FilterNode[];
32
- }
33
-
34
- export interface Props {
35
- query?: string;
36
- collectionName?: string;
37
- count: number;
38
- metafields?: Metafield[];
39
- pageOffset?: number;
40
- page?: number;
41
- startCursor?: string;
42
- endCursor?: string;
43
- pageHref?: string;
44
- }
45
-
46
- export default async function productListingPageLoader(
47
- props: Props,
48
- url?: URL,
49
- ): Promise<ProductListingPage | null> {
50
- const pageUrl = url ?? new URL(props.pageHref || "https://localhost");
51
- const client = getShopifyClient();
52
-
53
- const count = props.count ?? 12;
54
- const query = props.query || pageUrl.searchParams.get("q") || "";
55
- const currentPageoffset = props.pageOffset ?? 1;
56
- const pageParam = pageUrl.searchParams.get("page")
57
- ? Number(pageUrl.searchParams.get("page")) - currentPageoffset
58
- : 0;
59
- const page = props.page || pageParam;
60
- const endCursor = props.endCursor || pageUrl.searchParams.get("endCursor") || "";
61
- const startCursor = props.startCursor || pageUrl.searchParams.get("startCursor") || "";
62
- const metafields = props.metafields || [];
63
-
64
- const isSearch = Boolean(query);
65
- let hasNextPage = false;
66
- let hasPreviousPage = false;
67
- let shopifyProducts: ProductConnection | undefined;
68
- let shopifyFilters: FilterNode[] | undefined;
69
- let records: number | undefined;
70
- let collectionTitle: string | undefined;
71
- let collectionDescription: string | undefined;
72
-
73
- const sort = pageUrl.searchParams.get("sort") ?? "";
74
-
75
- if (isSearch) {
76
- const data = await client.query<{
77
- search: ProductConnection & { totalCount?: number; productFilters?: FilterNode[] };
78
- }>(SearchProducts, {
79
- ...(!endCursor && { first: count }),
80
- ...(endCursor && { last: count }),
81
- ...(startCursor && { after: startCursor }),
82
- ...(endCursor && { before: endCursor }),
83
- query,
84
- productFilters: getFiltersByUrl(pageUrl),
85
- identifiers: metafields,
86
- ...searchSortShopify[sort],
87
- });
88
-
89
- shopifyProducts = data.search;
90
- shopifyFilters = data.search?.productFilters;
91
- records = data.search?.totalCount;
92
- hasNextPage = Boolean(data.search?.pageInfo.hasNextPage);
93
- hasPreviousPage = Boolean(data.search?.pageInfo.hasPreviousPage);
94
- } else {
95
- const pathname = props.collectionName || pageUrl.pathname.split("/")[1];
96
-
97
- const data = await client.query<{
98
- collection?: {
99
- title?: string;
100
- description?: string;
101
- products: ProductConnection;
102
- };
103
- }>(ProductsByCollection, {
104
- ...(!endCursor && { first: count }),
105
- ...(endCursor && { last: count }),
106
- ...(startCursor && { after: startCursor }),
107
- ...(endCursor && { before: endCursor }),
108
- identifiers: metafields,
109
- handle: pathname,
110
- filters: getFiltersByUrl(pageUrl),
111
- ...sortShopify[sort],
112
- });
113
-
114
- shopifyProducts = data.collection?.products;
115
- shopifyFilters = data.collection?.products?.filters;
116
- hasNextPage = Boolean(data.collection?.products.pageInfo.hasNextPage);
117
- hasPreviousPage = Boolean(data.collection?.products.pageInfo.hasPreviousPage);
118
- collectionTitle = data.collection?.title;
119
- collectionDescription = data.collection?.description;
120
- }
121
-
122
- const products = shopifyProducts?.nodes?.map((p) => toProduct(p, p.variants.nodes[0], pageUrl));
123
-
124
- const nextPage = new URLSearchParams(pageUrl.searchParams);
125
- const previousPage = new URLSearchParams(pageUrl.searchParams);
126
-
127
- if (hasNextPage) {
128
- nextPage.set("page", (page + currentPageoffset + 1).toString());
129
- nextPage.set("startCursor", shopifyProducts?.pageInfo.endCursor ?? "");
130
- nextPage.delete("endCursor");
131
- }
132
-
133
- if (hasPreviousPage) {
134
- previousPage.set("page", (page + currentPageoffset - 1).toString());
135
- previousPage.set("endCursor", shopifyProducts?.pageInfo.startCursor ?? "");
136
- previousPage.delete("startCursor");
137
- }
138
-
139
- const filters = shopifyFilters?.map((filter) => toFilter(filter, pageUrl));
140
- const currentPage = page + currentPageoffset;
141
-
142
- return {
143
- "@type": "ProductListingPage",
144
- breadcrumb: {
145
- "@type": "BreadcrumbList",
146
- itemListElement: [
147
- {
148
- "@type": "ListItem" as const,
149
- name: isSearch ? query : pageUrl.pathname.split("/")[1],
150
- item: isSearch ? pageUrl.href : pageUrl.pathname,
151
- position: 2,
152
- },
153
- ],
154
- numberOfItems: 1,
155
- },
156
- filters: filters ?? [],
157
- products: products ?? [],
158
- pageInfo: {
159
- nextPage: hasNextPage ? `?${nextPage}` : undefined,
160
- previousPage: hasPreviousPage ? `?${previousPage}` : undefined,
161
- currentPage,
162
- records,
163
- recordPerPage: count,
164
- },
165
- sortOptions: isSearch ? searchSortOptions : sortOptions,
166
- seo: {
167
- title: collectionTitle || "",
168
- description: collectionDescription || "",
169
- canonical: `${pageUrl.origin}${pageUrl.pathname}${page >= 1 ? `?page=${page}` : ""}`,
170
- },
171
- };
172
- }
@@ -1,42 +0,0 @@
1
- import type { Product } from "@decocms/apps-commerce/types";
2
- import { getShopifyClient } from "../client";
3
- import { GetProduct, ProductRecommendations } from "../utils/storefront/queries";
4
- import { type ProductShopify, toProduct } from "../utils/transform";
5
- import type { Metafield } from "../utils/types";
6
-
7
- export interface Props {
8
- slug: string;
9
- count?: number;
10
- metafields?: Metafield[];
11
- }
12
-
13
- export default async function relatedProductsLoader(
14
- props: Props,
15
- url?: URL,
16
- ): Promise<Product[] | null> {
17
- const client = getShopifyClient();
18
- const { slug, count = 10, metafields = [] } = props;
19
-
20
- const splitted = slug?.split("-") ?? [];
21
- const maybeSkuId = Number(splitted[splitted.length - 1]);
22
- const handle = splitted.slice(0, maybeSkuId ? -1 : undefined).join("-");
23
-
24
- const productData = await client.query<{ product?: ProductShopify }>(GetProduct, {
25
- handle,
26
- identifiers: metafields,
27
- });
28
-
29
- if (!productData?.product) return [];
30
-
31
- const data = await client.query<{
32
- productRecommendations?: ProductShopify[];
33
- }>(ProductRecommendations, { productId: productData.product.id, identifiers: metafields });
34
-
35
- if (!data?.productRecommendations) return [];
36
-
37
- const baseUrl = url ?? new URL("https://localhost");
38
-
39
- return data.productRecommendations
40
- .map((p) => toProduct(p, p.variants.nodes[0], baseUrl))
41
- .slice(0, count);
42
- }
@@ -1,74 +0,0 @@
1
- import { getShopifyClient } from "../client";
2
- import { getCartCookie, setCartCookie } from "../utils/cart";
3
- import { CreateCart, GetCart } from "../utils/storefront/queries";
4
-
5
- export interface CartLine {
6
- id: string;
7
- quantity: number;
8
- merchandise: {
9
- id: string;
10
- title: string;
11
- image?: { url: string; altText?: string | null } | null;
12
- product: { title: string; handle: string; onlineStoreUrl?: string | null };
13
- price: { amount: string; currencyCode: string };
14
- };
15
- discountAllocations?: Array<{
16
- code?: string;
17
- discountedAmount?: { amount: string; currencyCode: string };
18
- }>;
19
- cost?: {
20
- totalAmount: { amount: string; currencyCode: string };
21
- subtotalAmount: { amount: string; currencyCode: string };
22
- amountPerQuantity?: { amount: string; currencyCode: string };
23
- compareAtAmountPerQuantity?: { amount: string; currencyCode: string } | null;
24
- };
25
- }
26
-
27
- export interface ShopifyCart {
28
- id: string;
29
- checkoutUrl: string;
30
- totalQuantity: number;
31
- lines: { nodes: CartLine[] };
32
- cost: {
33
- totalTaxAmount?: { amount: string; currencyCode: string };
34
- subtotalAmount: { amount: string; currencyCode: string };
35
- totalAmount: { amount: string; currencyCode: string };
36
- checkoutChargeAmount?: { amount: string; currencyCode: string };
37
- };
38
- discountCodes?: Array<{ applicable: boolean; code: string }>;
39
- discountAllocations?: Array<{
40
- discountedAmount: { amount: string; currencyCode: string };
41
- }>;
42
- }
43
-
44
- export async function getCart(
45
- requestHeaders: Headers,
46
- responseHeaders?: Headers,
47
- ): Promise<ShopifyCart | null> {
48
- const client = getShopifyClient();
49
- const maybeCartId = getCartCookie(requestHeaders);
50
-
51
- const cartId =
52
- maybeCartId ??
53
- (await client
54
- .query<{ payload?: { cart?: { id: string } } }>(CreateCart)
55
- .then((data) => data.payload?.cart?.id));
56
-
57
- if (!cartId) throw new Error("Missing cart id");
58
-
59
- const cart = await client
60
- .query<{ cart?: ShopifyCart }>(GetCart, { id: decodeURIComponent(cartId) })
61
- .then((data) => data.cart ?? null);
62
-
63
- if (responseHeaders) {
64
- setCartCookie(responseHeaders, cartId);
65
- }
66
-
67
- return cart;
68
- }
69
-
70
- export async function createCart(): Promise<string | null> {
71
- const client = getShopifyClient();
72
- const data = await client.query<{ payload?: { cart?: { id: string } } }>(CreateCart);
73
- return data?.payload?.cart?.id ?? null;
74
- }
@@ -1,35 +0,0 @@
1
- import { getShopifyClient } from "../client";
2
- import { GetShopInfo } from "../utils/storefront/queries";
3
- import type { Metafield } from "../utils/types";
4
-
5
- export interface Shop {
6
- name: string;
7
- description?: string;
8
- privacyPolicy?: { title: string; body: string };
9
- refundPolicy?: { title: string; body: string };
10
- shippingPolicy?: { title: string; body: string };
11
- subscriptionPolicy?: { title: string; body: string };
12
- termsOfService?: { title: string; body: string };
13
- metafields?: Array<{
14
- description?: string | null;
15
- key: string;
16
- namespace: string;
17
- type: string;
18
- value: string;
19
- reference?: { image?: { url: string } } | null;
20
- references?: { edges: Array<{ node: { image?: { url: string } } }> } | null;
21
- } | null>;
22
- }
23
-
24
- export interface Props {
25
- metafields?: Metafield[];
26
- }
27
-
28
- export default async function shopLoader(props?: Props): Promise<Shop> {
29
- const client = getShopifyClient();
30
- const metafields = props?.metafields || [];
31
-
32
- const data = await client.query<{ shop: Shop }>(GetShopInfo, { identifiers: metafields });
33
-
34
- return data.shop;
35
- }
@@ -1,39 +0,0 @@
1
- import { getShopifyClient } from "../client";
2
- import { FetchCustomerInfo } from "../utils/storefront/queries";
3
- import { getUserCookie } from "../utils/user";
4
-
5
- export interface ShopifyUser {
6
- "@id": string;
7
- email: string;
8
- givenName: string;
9
- familyName: string;
10
- }
11
-
12
- export default async function userLoader(requestHeaders: Headers): Promise<ShopifyUser | null> {
13
- const client = getShopifyClient();
14
- const customerAccessToken = getUserCookie(requestHeaders);
15
-
16
- if (!customerAccessToken) return null;
17
-
18
- try {
19
- const data = await client.query<{
20
- customer?: {
21
- id: string;
22
- email?: string | null;
23
- firstName?: string | null;
24
- lastName?: string | null;
25
- };
26
- }>(FetchCustomerInfo, { customerAccessToken });
27
-
28
- if (!data.customer) return null;
29
-
30
- return {
31
- "@id": data.customer.id,
32
- email: data.customer.email ?? "",
33
- givenName: data.customer.firstName ?? "",
34
- familyName: data.customer.lastName ?? "",
35
- };
36
- } catch {
37
- return null;
38
- }
39
- }
@@ -1,39 +0,0 @@
1
- // AUTO-GENERATED by scripts/generate-manifests.ts — DO NOT EDIT
2
- // This file is checked into source control and updated via: npm run generate:manifests
3
-
4
- import * as actions_cart_addItems from "./actions/cart/addItems";
5
- import * as actions_cart_updateCoupons from "./actions/cart/updateCoupons";
6
- import * as actions_cart_updateItems from "./actions/cart/updateItems";
7
- import * as actions_user_signIn from "./actions/user/signIn";
8
- import * as actions_user_signUp from "./actions/user/signUp";
9
- import * as loaders_cart from "./loaders/cart";
10
- import * as loaders_ProductDetailsPage from "./loaders/ProductDetailsPage";
11
- import * as loaders_ProductList from "./loaders/ProductList";
12
- import * as loaders_ProductListingPage from "./loaders/ProductListingPage";
13
- import * as loaders_RelatedProducts from "./loaders/RelatedProducts";
14
- import * as loaders_shop from "./loaders/shop";
15
- import * as loaders_user from "./loaders/user";
16
-
17
- const manifest = {
18
- name: "shopify",
19
- loaders: {
20
- "shopify/loaders/ProductDetailsPage": loaders_ProductDetailsPage,
21
- "shopify/loaders/ProductList": loaders_ProductList,
22
- "shopify/loaders/ProductListingPage": loaders_ProductListingPage,
23
- "shopify/loaders/RelatedProducts": loaders_RelatedProducts,
24
- "shopify/loaders/cart": loaders_cart,
25
- "shopify/loaders/shop": loaders_shop,
26
- "shopify/loaders/user": loaders_user,
27
- },
28
- actions: {
29
- "shopify/actions/cart/addItems": actions_cart_addItems,
30
- "shopify/actions/cart/updateCoupons": actions_cart_updateCoupons,
31
- "shopify/actions/cart/updateItems": actions_cart_updateItems,
32
- "shopify/actions/user/signIn": actions_user_signIn,
33
- "shopify/actions/user/signUp": actions_user_signUp,
34
- },
35
- sections: {},
36
- } as const;
37
-
38
- export type Manifest = typeof manifest;
39
- export default manifest;