@doswiftly/cli 0.1.18 → 0.1.19
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/README.md +23 -323
- package/dist/commands/check.js +1 -1
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +39 -20
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/doctor.js +3 -3
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +4 -4
- package/dist/commands/sdk.js +5 -5
- package/dist/commands/sdk.js.map +1 -1
- package/dist/commands/template.js +4 -4
- package/dist/commands/template.js.map +1 -1
- package/dist/commands/types.js +5 -5
- package/dist/commands/types.js.map +1 -1
- package/dist/commands/verify.js +2 -2
- package/dist/commands/verify.js.map +1 -1
- package/dist/lib/package-manager.d.ts +1 -1
- package/dist/lib/package-manager.js +1 -1
- package/package.json +1 -1
- package/templates/storefront-nextjs/README.md +16 -12
- package/templates/storefront-nextjs/app/account/orders/page.tsx +2 -2
- package/templates/storefront-nextjs/app/account/page.tsx +2 -2
- package/templates/storefront-nextjs/app/auth/login/page.tsx +1 -1
- package/templates/storefront-nextjs/app/auth/register/page.tsx +1 -1
- package/templates/storefront-nextjs/app/cart/page.tsx +1 -1
- package/templates/storefront-nextjs/app/categories/[slug]/page.tsx +2 -2
- package/templates/storefront-nextjs/app/categories/page.tsx +1 -1
- package/templates/storefront-nextjs/app/collections/[slug]/page.tsx +1 -1
- package/templates/storefront-nextjs/app/collections/page.tsx +1 -1
- package/templates/storefront-nextjs/app/page.tsx +1 -1
- package/templates/storefront-nextjs/app/products/[slug]/page.tsx +1 -1
- package/templates/storefront-nextjs/app/products/page.tsx +2 -2
- package/templates/storefront-nextjs/app/search/page.tsx +1 -1
- package/templates/storefront-nextjs/components/auth/auth-guard.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/add-to-cart-button.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/cart-icon.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/currency-selector.tsx +2 -2
- package/templates/storefront-nextjs/components/commerce/product-filters.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/product-price.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/search-input.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/sort-select.tsx +1 -1
- package/templates/storefront-nextjs/components/providers.tsx +1 -1
- package/templates/storefront-nextjs/lib/currency.tsx +3 -3
- package/templates/storefront-nextjs/lib/format.ts +1 -1
- package/templates/storefront-nextjs/lib/graphql-queries.ts +3 -3
- package/templates/storefront-nextjs/package.dev.json +1 -1
- package/templates/storefront-nextjs/package.json +1 -1
- package/templates/storefront-nextjs/package.json.template +1 -1
- package/templates/storefront-nextjs-shadcn/.github/workflows/deploy.yml +47 -0
- package/templates/storefront-nextjs-shadcn/.github/workflows/preview.yml +47 -0
- package/templates/storefront-nextjs-shadcn/CLAUDE.md +148 -35
- package/templates/storefront-nextjs-shadcn/README.md +29 -162
- package/templates/storefront-nextjs-shadcn/app/account/addresses/page.tsx +98 -91
- package/templates/storefront-nextjs-shadcn/app/account/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/account/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/account/loyalty/page.tsx +53 -162
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/loading.tsx +60 -0
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/page.tsx +36 -47
- package/templates/storefront-nextjs-shadcn/app/account/orders/page.tsx +46 -29
- package/templates/storefront-nextjs-shadcn/app/account/page.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/app/account/settings/page.tsx +108 -71
- package/templates/storefront-nextjs-shadcn/app/api/auth/clear-token/route.ts +2 -86
- package/templates/storefront-nextjs-shadcn/app/api/auth/set-token/route.ts +2 -124
- package/templates/storefront-nextjs-shadcn/app/auth/forgot-password/page.tsx +10 -5
- package/templates/storefront-nextjs-shadcn/app/blog/[slug]/loading.tsx +17 -0
- package/templates/storefront-nextjs-shadcn/app/blog/[slug]/page.tsx +43 -2
- package/templates/storefront-nextjs-shadcn/app/blog/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/brands/page.tsx +2 -1
- package/templates/storefront-nextjs-shadcn/app/cart/loading.tsx +26 -0
- package/templates/storefront-nextjs-shadcn/app/cart/page.tsx +6 -3
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/category-products-client.tsx +56 -0
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/loading.tsx +32 -0
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/page.tsx +76 -59
- package/templates/storefront-nextjs-shadcn/app/categories/page.tsx +8 -4
- package/templates/storefront-nextjs-shadcn/app/checkout/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/checkout/loading.tsx +31 -0
- package/templates/storefront-nextjs-shadcn/app/checkout/page.tsx +116 -79
- package/templates/storefront-nextjs-shadcn/app/collections/[handle]/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/collections/[handle]/page.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/app/collections/loading.tsx +18 -0
- package/templates/storefront-nextjs-shadcn/app/collections/page.tsx +7 -4
- package/templates/storefront-nextjs-shadcn/app/global-error.tsx +117 -0
- package/templates/storefront-nextjs-shadcn/app/globals.css +8 -0
- package/templates/storefront-nextjs-shadcn/app/layout.tsx +46 -11
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/loading.tsx +29 -0
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/page.tsx +6 -6
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/product-client.tsx +15 -61
- package/templates/storefront-nextjs-shadcn/app/products/loading.tsx +32 -0
- package/templates/storefront-nextjs-shadcn/app/products/products-client.tsx +405 -151
- package/templates/storefront-nextjs-shadcn/app/search/loading.tsx +18 -0
- package/templates/storefront-nextjs-shadcn/app/wishlist/page.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/codegen.ts +48 -31
- package/templates/storefront-nextjs-shadcn/components/account/customer-info.fragment.graphql +36 -0
- package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +3 -1
- package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +26 -24
- package/templates/storefront-nextjs-shadcn/components/account/order-summary.fragment.graphql +36 -0
- package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +9 -9
- package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +11 -37
- package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +37 -23
- package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +4 -3
- package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/cart/cart-line.fragment.graphql +53 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +22 -7
- package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/common/price-display.tsx +35 -11
- package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +3 -3
- package/templates/storefront-nextjs-shadcn/components/filters/range-slider-filter.tsx +5 -5
- package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +2 -1
- package/templates/storefront-nextjs-shadcn/components/home/collection-card.fragment.graphql +21 -0
- package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +2 -12
- package/templates/storefront-nextjs-shadcn/components/home/index.ts +0 -1
- package/templates/storefront-nextjs-shadcn/components/hydrated.tsx +24 -0
- package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +4 -4
- package/templates/storefront-nextjs-shadcn/components/layout/category-node.fragment.graphql +22 -0
- package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +33 -23
- package/templates/storefront-nextjs-shadcn/components/loyalty/points-balance.tsx +2 -11
- package/templates/storefront-nextjs-shadcn/components/loyalty/points-history.tsx +8 -25
- package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +10 -19
- package/templates/storefront-nextjs-shadcn/components/loyalty/rewards-catalog.tsx +17 -41
- package/templates/storefront-nextjs-shadcn/components/loyalty/tier-progress.tsx +2 -29
- package/templates/storefront-nextjs-shadcn/components/order/index.ts +6 -1
- package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +3 -1
- package/templates/storefront-nextjs-shadcn/components/product/filter-active-pills.tsx +69 -0
- package/templates/storefront-nextjs-shadcn/components/product/filter-mobile-sheet.tsx +84 -0
- package/templates/storefront-nextjs-shadcn/components/product/filter-price-range.tsx +138 -0
- package/templates/storefront-nextjs-shadcn/components/product/index.ts +9 -2
- package/templates/storefront-nextjs-shadcn/components/product/product-card.fragment.graphql +49 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +3 -31
- package/templates/storefront-nextjs-shadcn/components/product/product-detail.fragment.graphql +52 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +176 -123
- package/templates/storefront-nextjs-shadcn/components/product/product-grid.tsx +3 -5
- package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/product/product-price.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/product/product-reviews.tsx +5 -4
- package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +19 -7
- package/templates/storefront-nextjs-shadcn/components/product/product-variant-selector.tsx +8 -23
- package/templates/storefront-nextjs-shadcn/components/product/product-variant.fragment.graphql +51 -0
- package/templates/storefront-nextjs-shadcn/components/product/review-card.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +1 -7
- package/templates/storefront-nextjs-shadcn/components/product/savings-display.tsx +17 -2
- package/templates/storefront-nextjs-shadcn/components/product/similar-products.tsx +3 -2
- package/templates/storefront-nextjs-shadcn/components/providers/index.ts +1 -1
- package/templates/storefront-nextjs-shadcn/components/providers/stores-provider.tsx +30 -0
- package/templates/storefront-nextjs-shadcn/components/providers/theme-provider.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/returns/index.ts +2 -2
- package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +3 -2
- package/templates/storefront-nextjs-shadcn/components/search/search-results.tsx +3 -2
- package/templates/storefront-nextjs-shadcn/components/ui/form.tsx +174 -0
- package/templates/storefront-nextjs-shadcn/components/ui/index.ts +30 -2
- package/templates/storefront-nextjs-shadcn/components/ui/progress.tsx +40 -0
- package/templates/storefront-nextjs-shadcn/components/ui/sheet.tsx +107 -0
- package/templates/storefront-nextjs-shadcn/components/ui/slider.tsx +33 -0
- package/templates/storefront-nextjs-shadcn/components/ui/textarea.tsx +24 -0
- package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +3 -1
- package/templates/storefront-nextjs-shadcn/generated/graphql.ts +12779 -0
- package/templates/storefront-nextjs-shadcn/graphql/custom.example.graphql +159 -0
- package/templates/storefront-nextjs-shadcn/hooks/index.ts +2 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-auth-sync.ts +42 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-auth.ts +17 -295
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +51 -19
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +13 -9
- package/templates/storefront-nextjs-shadcn/lib/auth/routes.ts +4 -17
- package/templates/storefront-nextjs-shadcn/lib/graphql/client.ts +22 -99
- package/templates/storefront-nextjs-shadcn/lib/graphql/config.ts +32 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/fragments.ts +34 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +687 -632
- package/templates/storefront-nextjs-shadcn/lib/graphql/query-keys.ts +86 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +131 -182
- package/templates/storefront-nextjs-shadcn/lib/graphql/types.ts +62 -0
- package/templates/storefront-nextjs-shadcn/lib/theme/theme-config.ts +0 -17
- package/templates/storefront-nextjs-shadcn/next-env.d.ts +6 -0
- package/templates/storefront-nextjs-shadcn/package.dev.json +1 -3
- package/templates/storefront-nextjs-shadcn/package.json +12 -13
- package/templates/storefront-nextjs-shadcn/package.json.template +6 -7
- package/templates/storefront-nextjs-shadcn/proxy.ts +3 -4
- package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +41 -39
- package/templates/storefront-nextjs-shadcn/stores/checkout-store.ts +64 -75
- package/templates/storefront-nextjs-shadcn/stores/wishlist-store.ts +178 -177
- package/templates/storefront-nextjs-shadcn/tsconfig.json +23 -5
- package/templates/storefront-nextjs-shadcn/CART_INTEGRATION.md +0 -282
- package/templates/storefront-nextjs-shadcn/GRAPHQL_DOCUMENT_NAMES.md +0 -190
- package/templates/storefront-nextjs-shadcn/GRAPHQL_ERROR_HANDLING.md +0 -263
- package/templates/storefront-nextjs-shadcn/GRAPHQL_FIXES_SUMMARY.md +0 -135
- package/templates/storefront-nextjs-shadcn/GRAPHQL_INTEGRATION_COMPLETE.md +0 -142
- package/templates/storefront-nextjs-shadcn/INTEGRATION_CHECKLIST.md +0 -448
- package/templates/storefront-nextjs-shadcn/PRODUCT_DETAIL_PAGE_IMPLEMENTATION.md +0 -307
- package/templates/storefront-nextjs-shadcn/THEME_CUSTOMIZATION.md +0 -245
- package/templates/storefront-nextjs-shadcn/components/providers/currency-provider.tsx +0 -103
- package/templates/storefront-nextjs-shadcn/graphql/collections.example.ts +0 -168
- package/templates/storefront-nextjs-shadcn/graphql/products.example.ts +0 -160
- package/templates/storefront-nextjs-shadcn/lib/auth/cookies.ts +0 -220
- package/templates/storefront-nextjs-shadcn/lib/config.ts +0 -46
- package/templates/storefront-nextjs-shadcn/lib/currency/IMPLEMENTATION_SUMMARY.md +0 -254
- package/templates/storefront-nextjs-shadcn/lib/currency/README.md +0 -464
- package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.test.ts +0 -328
- package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.ts +0 -295
- package/templates/storefront-nextjs-shadcn/lib/currency/index.ts +0 -27
- package/templates/storefront-nextjs-shadcn/lib/format.ts +0 -226
- package/templates/storefront-nextjs-shadcn/lib/hooks.ts +0 -30
- package/templates/storefront-nextjs-shadcn/stores/auth-store.ts +0 -66
- package/templates/storefront-nextjs-shadcn/stores/currency-store.ts +0 -103
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { gql } from 'graphql-tag';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Example: Custom GraphQL query for collections
|
|
5
|
-
*
|
|
6
|
-
* This file demonstrates how to write custom GraphQL queries for collections
|
|
7
|
-
* that will be picked up by codegen and generate TypeScript types.
|
|
8
|
-
*
|
|
9
|
-
* To use this example:
|
|
10
|
-
* 1. Rename this file from collections.example.ts to collections.ts
|
|
11
|
-
* 2. Run `pnpm run codegen` to generate types
|
|
12
|
-
* 3. Import the generated query in your components
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
// Example 1: Get featured collections
|
|
16
|
-
export const GET_FEATURED_COLLECTIONS = gql`
|
|
17
|
-
query GetFeaturedCollections($first: Int = 6) {
|
|
18
|
-
collections(first: $first, query: "featured:true") {
|
|
19
|
-
edges {
|
|
20
|
-
node {
|
|
21
|
-
id
|
|
22
|
-
handle
|
|
23
|
-
title
|
|
24
|
-
description
|
|
25
|
-
image {
|
|
26
|
-
url
|
|
27
|
-
altText
|
|
28
|
-
width
|
|
29
|
-
height
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
cursor
|
|
33
|
-
}
|
|
34
|
-
pageInfo {
|
|
35
|
-
hasNextPage
|
|
36
|
-
endCursor
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
`;
|
|
41
|
-
|
|
42
|
-
// Example 2: Get collection with products
|
|
43
|
-
export const GET_COLLECTION_WITH_PRODUCTS = gql`
|
|
44
|
-
query GetCollectionWithProducts(
|
|
45
|
-
$handle: String!
|
|
46
|
-
$first: Int = 20
|
|
47
|
-
$after: String
|
|
48
|
-
) {
|
|
49
|
-
collection(handle: $handle) {
|
|
50
|
-
id
|
|
51
|
-
title
|
|
52
|
-
description
|
|
53
|
-
descriptionHtml
|
|
54
|
-
image {
|
|
55
|
-
url
|
|
56
|
-
altText
|
|
57
|
-
}
|
|
58
|
-
seo {
|
|
59
|
-
title
|
|
60
|
-
description
|
|
61
|
-
}
|
|
62
|
-
products(
|
|
63
|
-
first: $first
|
|
64
|
-
after: $after
|
|
65
|
-
) {
|
|
66
|
-
edges {
|
|
67
|
-
node {
|
|
68
|
-
id
|
|
69
|
-
handle
|
|
70
|
-
title
|
|
71
|
-
description
|
|
72
|
-
featuredImage {
|
|
73
|
-
url
|
|
74
|
-
altText
|
|
75
|
-
}
|
|
76
|
-
priceRange {
|
|
77
|
-
minVariantPrice {
|
|
78
|
-
amount
|
|
79
|
-
currencyCode
|
|
80
|
-
baseAmount
|
|
81
|
-
baseCurrencyCode
|
|
82
|
-
isConverted
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
compareAtPriceRange {
|
|
86
|
-
minVariantPrice {
|
|
87
|
-
amount
|
|
88
|
-
currencyCode
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
vendor
|
|
92
|
-
productType
|
|
93
|
-
tags
|
|
94
|
-
totalInventory
|
|
95
|
-
}
|
|
96
|
-
cursor
|
|
97
|
-
}
|
|
98
|
-
pageInfo {
|
|
99
|
-
hasNextPage
|
|
100
|
-
hasPreviousPage
|
|
101
|
-
startCursor
|
|
102
|
-
endCursor
|
|
103
|
-
}
|
|
104
|
-
totalCount
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
`;
|
|
109
|
-
|
|
110
|
-
// Example 3: Get all collections with product counts
|
|
111
|
-
export const GET_ALL_COLLECTIONS = gql`
|
|
112
|
-
query GetAllCollections(
|
|
113
|
-
$first: Int = 50
|
|
114
|
-
$after: String
|
|
115
|
-
$sortKey: CollectionSortKeys = TITLE
|
|
116
|
-
) {
|
|
117
|
-
collections(first: $first, after: $after, sortKey: $sortKey) {
|
|
118
|
-
edges {
|
|
119
|
-
node {
|
|
120
|
-
id
|
|
121
|
-
handle
|
|
122
|
-
title
|
|
123
|
-
description
|
|
124
|
-
image {
|
|
125
|
-
url
|
|
126
|
-
altText
|
|
127
|
-
}
|
|
128
|
-
products(first: 1) {
|
|
129
|
-
totalCount
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
cursor
|
|
133
|
-
}
|
|
134
|
-
pageInfo {
|
|
135
|
-
hasNextPage
|
|
136
|
-
hasPreviousPage
|
|
137
|
-
startCursor
|
|
138
|
-
endCursor
|
|
139
|
-
}
|
|
140
|
-
totalCount
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
`;
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Usage in components:
|
|
147
|
-
*
|
|
148
|
-
* // Server Component
|
|
149
|
-
* import { getClient } from '@/lib/graphql/server';
|
|
150
|
-
* import { GetFeaturedCollectionsDocument } from '@/generated/graphql';
|
|
151
|
-
*
|
|
152
|
-
* const client = getClient();
|
|
153
|
-
* const { collections } = await client.request(GetFeaturedCollectionsDocument);
|
|
154
|
-
*
|
|
155
|
-
* // Client Component
|
|
156
|
-
* import { useQuery } from '@tanstack/react-query';
|
|
157
|
-
* import { getGraphQLClient } from '@/lib/graphql/client';
|
|
158
|
-
* import { GetCollectionWithProductsDocument } from '@/generated/graphql';
|
|
159
|
-
*
|
|
160
|
-
* const client = getGraphQLClient();
|
|
161
|
-
* const { data } = useQuery({
|
|
162
|
-
* queryKey: ['Collection', handle],
|
|
163
|
-
* queryFn: () => client.request(GetCollectionWithProductsDocument, {
|
|
164
|
-
* handle,
|
|
165
|
-
* first: 20
|
|
166
|
-
* }),
|
|
167
|
-
* });
|
|
168
|
-
*/
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { gql } from 'graphql-tag';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Example: Custom GraphQL query for featured products
|
|
5
|
-
*
|
|
6
|
-
* This file demonstrates how to write custom GraphQL queries
|
|
7
|
-
* that will be picked up by codegen and generate TypeScript types.
|
|
8
|
-
*
|
|
9
|
-
* To use this example:
|
|
10
|
-
* 1. Rename this file from products.example.ts to products.ts
|
|
11
|
-
* 2. Run `pnpm run codegen` to generate types
|
|
12
|
-
* 3. Import the generated query in your components
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
// Example 1: Get featured products with specific fields
|
|
16
|
-
export const GET_FEATURED_PRODUCTS = gql`
|
|
17
|
-
query GetFeaturedProducts($first: Int = 6) {
|
|
18
|
-
products(first: $first, query: "tag:featured") {
|
|
19
|
-
edges {
|
|
20
|
-
node {
|
|
21
|
-
id
|
|
22
|
-
handle
|
|
23
|
-
title
|
|
24
|
-
description
|
|
25
|
-
featuredImage {
|
|
26
|
-
url
|
|
27
|
-
altText
|
|
28
|
-
width
|
|
29
|
-
height
|
|
30
|
-
}
|
|
31
|
-
priceRange {
|
|
32
|
-
minVariantPrice {
|
|
33
|
-
amount
|
|
34
|
-
currencyCode
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
cursor
|
|
39
|
-
}
|
|
40
|
-
pageInfo {
|
|
41
|
-
hasNextPage
|
|
42
|
-
endCursor
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
`;
|
|
47
|
-
|
|
48
|
-
// Example 2: Get product with reviews
|
|
49
|
-
export const GET_PRODUCT_WITH_REVIEWS = gql`
|
|
50
|
-
query GetProductWithReviews($handle: String!) {
|
|
51
|
-
product(handle: $handle) {
|
|
52
|
-
id
|
|
53
|
-
title
|
|
54
|
-
description
|
|
55
|
-
descriptionHtml
|
|
56
|
-
averageRating
|
|
57
|
-
reviewCount
|
|
58
|
-
featuredImage {
|
|
59
|
-
url
|
|
60
|
-
altText
|
|
61
|
-
}
|
|
62
|
-
priceRange {
|
|
63
|
-
minVariantPrice {
|
|
64
|
-
amount
|
|
65
|
-
currencyCode
|
|
66
|
-
baseAmount
|
|
67
|
-
baseCurrencyCode
|
|
68
|
-
isConverted
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
variants(first: 10) {
|
|
72
|
-
id
|
|
73
|
-
title
|
|
74
|
-
price {
|
|
75
|
-
amount
|
|
76
|
-
currencyCode
|
|
77
|
-
}
|
|
78
|
-
available
|
|
79
|
-
quantityAvailable
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
`;
|
|
84
|
-
|
|
85
|
-
// Example 3: Search products with filters
|
|
86
|
-
export const SEARCH_PRODUCTS_WITH_FILTERS = gql`
|
|
87
|
-
query SearchProductsWithFilters(
|
|
88
|
-
$query: String!
|
|
89
|
-
$first: Int = 20
|
|
90
|
-
$after: String
|
|
91
|
-
$filters: ProductFilterInput
|
|
92
|
-
) {
|
|
93
|
-
products(
|
|
94
|
-
query: $query
|
|
95
|
-
first: $first
|
|
96
|
-
after: $after
|
|
97
|
-
filters: $filters
|
|
98
|
-
) {
|
|
99
|
-
edges {
|
|
100
|
-
node {
|
|
101
|
-
id
|
|
102
|
-
handle
|
|
103
|
-
title
|
|
104
|
-
vendor
|
|
105
|
-
productType
|
|
106
|
-
featuredImage {
|
|
107
|
-
url
|
|
108
|
-
altText
|
|
109
|
-
}
|
|
110
|
-
priceRange {
|
|
111
|
-
minVariantPrice {
|
|
112
|
-
amount
|
|
113
|
-
currencyCode
|
|
114
|
-
}
|
|
115
|
-
maxVariantPrice {
|
|
116
|
-
amount
|
|
117
|
-
currencyCode
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
compareAtPriceRange {
|
|
121
|
-
minVariantPrice {
|
|
122
|
-
amount
|
|
123
|
-
currencyCode
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
cursor
|
|
128
|
-
}
|
|
129
|
-
pageInfo {
|
|
130
|
-
hasNextPage
|
|
131
|
-
hasPreviousPage
|
|
132
|
-
startCursor
|
|
133
|
-
endCursor
|
|
134
|
-
}
|
|
135
|
-
totalCount
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
`;
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Usage in components:
|
|
142
|
-
*
|
|
143
|
-
* // Server Component
|
|
144
|
-
* import { getClient } from '@/lib/graphql/server';
|
|
145
|
-
* import { GetFeaturedProductsDocument } from '@/generated/graphql';
|
|
146
|
-
*
|
|
147
|
-
* const client = getClient();
|
|
148
|
-
* const { products } = await client.request(GetFeaturedProductsDocument, { first: 6 });
|
|
149
|
-
*
|
|
150
|
-
* // Client Component
|
|
151
|
-
* import { useQuery } from '@tanstack/react-query';
|
|
152
|
-
* import { getGraphQLClient } from '@/lib/graphql/client';
|
|
153
|
-
* import { GetFeaturedProductsDocument } from '@/generated/graphql';
|
|
154
|
-
*
|
|
155
|
-
* const client = getGraphQLClient();
|
|
156
|
-
* const { data } = useQuery({
|
|
157
|
-
* queryKey: ['FeaturedProducts'],
|
|
158
|
-
* queryFn: () => client.request(GetFeaturedProductsDocument, { first: 6 }),
|
|
159
|
-
* });
|
|
160
|
-
*/
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cookie Helpers for Authentication
|
|
3
|
-
*
|
|
4
|
-
* Provides utilities for managing authentication cookies in both
|
|
5
|
-
* client-side and server-side contexts.
|
|
6
|
-
*
|
|
7
|
-
* Security Notes:
|
|
8
|
-
* - Cookies are httpOnly (set via API routes, not client-side)
|
|
9
|
-
* - Cookies are secure in production (HTTPS only)
|
|
10
|
-
* - Cookies are SameSite=Lax to prevent CSRF
|
|
11
|
-
* - Token validation happens on GraphQL backend
|
|
12
|
-
*
|
|
13
|
-
* @see lib/auth/routes.ts - Cookie name constant
|
|
14
|
-
* @see app/api/auth/set-token/route.ts - Server-side cookie setter
|
|
15
|
-
* @see app/api/auth/clear-token/route.ts - Server-side cookie clearer
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { AUTH_COOKIE_NAME } from "./routes";
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Cookie configuration for authentication token
|
|
22
|
-
*/
|
|
23
|
-
export const AUTH_COOKIE_CONFIG = {
|
|
24
|
-
name: AUTH_COOKIE_NAME,
|
|
25
|
-
maxAge: 60 * 60 * 24 * 30, // 30 days (in seconds)
|
|
26
|
-
path: "/",
|
|
27
|
-
sameSite: "lax" as const,
|
|
28
|
-
secure: process.env.NODE_ENV === "production",
|
|
29
|
-
httpOnly: true, // Cannot be accessed via JavaScript (security)
|
|
30
|
-
} as const;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Get authentication token from cookies (client-side)
|
|
34
|
-
*
|
|
35
|
-
* Note: This only works if the cookie is NOT httpOnly.
|
|
36
|
-
* For httpOnly cookies, use server-side methods or API routes.
|
|
37
|
-
*
|
|
38
|
-
* @returns Token string or null if not found
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* ```tsx
|
|
42
|
-
* const token = getAuthToken();
|
|
43
|
-
* if (token) {
|
|
44
|
-
* // User is authenticated
|
|
45
|
-
* }
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
|
-
export function getAuthToken(): string | null {
|
|
49
|
-
if (typeof window === "undefined") {
|
|
50
|
-
return null; // Server-side
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const cookies = document.cookie.split("; ");
|
|
54
|
-
const authCookie = cookies.find((c) => c.startsWith(`${AUTH_COOKIE_NAME}=`));
|
|
55
|
-
|
|
56
|
-
if (!authCookie) {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return authCookie.split("=")[1] || null;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Check if user is authenticated (client-side)
|
|
65
|
-
*
|
|
66
|
-
* Note: This checks cookie EXISTENCE, not VALIDITY.
|
|
67
|
-
* Token validation happens on the GraphQL backend.
|
|
68
|
-
*
|
|
69
|
-
* @returns True if auth cookie exists
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* ```tsx
|
|
73
|
-
* const isAuthenticated = isAuthTokenPresent();
|
|
74
|
-
* if (isAuthenticated) {
|
|
75
|
-
* // Show authenticated UI
|
|
76
|
-
* }
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
export function isAuthTokenPresent(): boolean {
|
|
80
|
-
return getAuthToken() !== null;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Set authentication token (via API route)
|
|
85
|
-
*
|
|
86
|
-
* This function calls the API route to set an httpOnly cookie.
|
|
87
|
-
* Direct client-side cookie setting is NOT secure for auth tokens.
|
|
88
|
-
*
|
|
89
|
-
* @param token - Customer access token from GraphQL
|
|
90
|
-
* @returns Promise that resolves when cookie is set
|
|
91
|
-
*
|
|
92
|
-
* @example
|
|
93
|
-
* ```tsx
|
|
94
|
-
* const { customerAccessToken } = await loginMutation.mutateAsync({
|
|
95
|
-
* input: { email, password }
|
|
96
|
-
* });
|
|
97
|
-
*
|
|
98
|
-
* if (customerAccessToken) {
|
|
99
|
-
* await setAuthToken(customerAccessToken.accessToken);
|
|
100
|
-
* }
|
|
101
|
-
* ```
|
|
102
|
-
*/
|
|
103
|
-
export async function setAuthToken(token: string): Promise<void> {
|
|
104
|
-
const response = await fetch("/api/auth/set-token", {
|
|
105
|
-
method: "POST",
|
|
106
|
-
headers: {
|
|
107
|
-
"Content-Type": "application/json",
|
|
108
|
-
},
|
|
109
|
-
body: JSON.stringify({ token }),
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
if (!response.ok) {
|
|
113
|
-
throw new Error("Failed to set authentication token");
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Clear authentication token (via API route)
|
|
119
|
-
*
|
|
120
|
-
* This function calls the API route to clear the httpOnly cookie.
|
|
121
|
-
*
|
|
122
|
-
* @returns Promise that resolves when cookie is cleared
|
|
123
|
-
*
|
|
124
|
-
* @example
|
|
125
|
-
* ```tsx
|
|
126
|
-
* await clearAuthToken();
|
|
127
|
-
* router.push('/auth/login');
|
|
128
|
-
* ```
|
|
129
|
-
*/
|
|
130
|
-
export async function clearAuthToken(): Promise<void> {
|
|
131
|
-
const response = await fetch("/api/auth/clear-token", {
|
|
132
|
-
method: "POST",
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
if (!response.ok) {
|
|
136
|
-
throw new Error("Failed to clear authentication token");
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Parse cookie string into key-value object
|
|
142
|
-
*
|
|
143
|
-
* Utility function for parsing cookie strings in server-side contexts.
|
|
144
|
-
*
|
|
145
|
-
* @param cookieString - Raw cookie string from request headers
|
|
146
|
-
* @returns Object with cookie key-value pairs
|
|
147
|
-
*
|
|
148
|
-
* @example
|
|
149
|
-
* ```tsx
|
|
150
|
-
* const cookies = parseCookies(request.headers.get('cookie') || '');
|
|
151
|
-
* const token = cookies[AUTH_COOKIE_NAME];
|
|
152
|
-
* ```
|
|
153
|
-
*/
|
|
154
|
-
export function parseCookies(cookieString: string): Record<string, string> {
|
|
155
|
-
return cookieString
|
|
156
|
-
.split("; ")
|
|
157
|
-
.reduce((acc, cookie) => {
|
|
158
|
-
const [key, value] = cookie.split("=");
|
|
159
|
-
if (key && value) {
|
|
160
|
-
acc[key] = value;
|
|
161
|
-
}
|
|
162
|
-
return acc;
|
|
163
|
-
}, {} as Record<string, string>);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Serialize cookie for Set-Cookie header
|
|
168
|
-
*
|
|
169
|
-
* Utility function for creating Set-Cookie header values in API routes.
|
|
170
|
-
*
|
|
171
|
-
* @param name - Cookie name
|
|
172
|
-
* @param value - Cookie value
|
|
173
|
-
* @param options - Cookie options (maxAge, path, etc.)
|
|
174
|
-
* @returns Serialized cookie string for Set-Cookie header
|
|
175
|
-
*
|
|
176
|
-
* @example
|
|
177
|
-
* ```tsx
|
|
178
|
-
* const cookieHeader = serializeCookie(
|
|
179
|
-
* AUTH_COOKIE_NAME,
|
|
180
|
-
* token,
|
|
181
|
-
* AUTH_COOKIE_CONFIG
|
|
182
|
-
* );
|
|
183
|
-
* response.headers.set('Set-Cookie', cookieHeader);
|
|
184
|
-
* ```
|
|
185
|
-
*/
|
|
186
|
-
export function serializeCookie(
|
|
187
|
-
name: string,
|
|
188
|
-
value: string,
|
|
189
|
-
options: {
|
|
190
|
-
maxAge?: number;
|
|
191
|
-
path?: string;
|
|
192
|
-
sameSite?: "strict" | "lax" | "none";
|
|
193
|
-
secure?: boolean;
|
|
194
|
-
httpOnly?: boolean;
|
|
195
|
-
} = {}
|
|
196
|
-
): string {
|
|
197
|
-
const parts = [`${name}=${value}`];
|
|
198
|
-
|
|
199
|
-
if (options.maxAge) {
|
|
200
|
-
parts.push(`Max-Age=${options.maxAge}`);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (options.path) {
|
|
204
|
-
parts.push(`Path=${options.path}`);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (options.sameSite) {
|
|
208
|
-
parts.push(`SameSite=${options.sameSite}`);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (options.secure) {
|
|
212
|
-
parts.push("Secure");
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (options.httpOnly) {
|
|
216
|
-
parts.push("HttpOnly");
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
return parts.join("; ");
|
|
220
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shop Configuration
|
|
3
|
-
*
|
|
4
|
-
* Centralized configuration for shop settings.
|
|
5
|
-
* Customize these values to match your store's policies.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export const shopConfig = {
|
|
9
|
-
/**
|
|
10
|
-
* Currency settings
|
|
11
|
-
*/
|
|
12
|
-
currency: {
|
|
13
|
-
default: 'USD',
|
|
14
|
-
supported: ['USD', 'EUR', 'GBP', 'PLN'],
|
|
15
|
-
},
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Shipping policy settings
|
|
19
|
-
*/
|
|
20
|
-
shipping: {
|
|
21
|
-
freeShippingThreshold: 50,
|
|
22
|
-
standardDeliveryDays: { min: 3, max: 5 },
|
|
23
|
-
features: [
|
|
24
|
-
'Express shipping available at checkout',
|
|
25
|
-
'International shipping available',
|
|
26
|
-
'30-day return policy',
|
|
27
|
-
],
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Product display settings
|
|
32
|
-
*/
|
|
33
|
-
products: {
|
|
34
|
-
gridColumns: 4,
|
|
35
|
-
itemsPerPage: 12,
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Cart settings
|
|
40
|
-
*/
|
|
41
|
-
cart: {
|
|
42
|
-
maxQuantityPerItem: 99,
|
|
43
|
-
},
|
|
44
|
-
} as const;
|
|
45
|
-
|
|
46
|
-
export type ShopConfig = typeof shopConfig;
|