Skip to content

Commit

Permalink
chore(sm): add sync script
Browse files Browse the repository at this point in the history
  • Loading branch information
ddaoxuan committed Nov 5, 2024
1 parent b21d0e7 commit fcd7629
Show file tree
Hide file tree
Showing 9 changed files with 755 additions and 45 deletions.
2 changes: 2 additions & 0 deletions starters/shopify-meilisearch/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ graph.svg
# testing
coverage
.vercel

scripts/dist
12 changes: 12 additions & 0 deletions starters/shopify-meilisearch/lib/meilisearch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,18 @@ export const getAllProducts = async (options?: Omit<DocumentsQuery<CommerceProdu
})
}

export const getAllCategories = async (options?: Omit<DocumentsQuery<PlatformCollection>, "limit">) => {
if (isDemoMode()) return getDemoCategories()

return await meilisearch.getDocuments<PlatformCollection>({
indexName: env.MEILISEARCH_CATEGORIES_INDEX,
options: {
...options,
limit: 10000,
},
})
}

export const getSimilarProducts = unstable_cache(
async (handle: string, collection: string | undefined) => {
const limit = 8
Expand Down
43 changes: 41 additions & 2 deletions starters/shopify-meilisearch/lib/shopify/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { getMenuQuery, type MenuQuery } from "./queries/menu.storefront"
import { getPageQuery, getPagesQuery } from "./queries/page.storefront"
import { getLatestProductFeedQuery } from "./queries/product-feed.admin"
import { getAdminProductQuery, getProductStatusQuery } from "./queries/product.admin"
import { getProductQuery, getProductsByHandleQuery } from "./queries/product.storefront"
import { getProductQuery, getProductsByHandleQuery, getProductsQuery } from "./queries/product.storefront"

import type {
LatestProductFeedsQuery,
Expand Down Expand Up @@ -105,6 +105,8 @@ export function createShopifyClient({ storefrontAccessToken, adminAccessToken, s
updateUser: async (accessToken: string, input: Omit<PlatformUserCreateInput, "password">) => updateUser(client!, accessToken, input),
createUserAccessToken: async (input: Pick<PlatformUserCreateInput, "password" | "email">) => createUserAccessToken(client!, input),
getHierarchicalCollections: async (handle: string, depth?: number) => getHierarchicalCollections(client!, handle, depth),
getAllProducts: async () => getAllProducts(client!),
getAllCollections: async () => getAllCollections(client!),
}
}

Expand All @@ -116,7 +118,7 @@ async function getMenu(client: StorefrontApiClient, handle: string = "main-menu"
return { items: mappedItems || [] }
}

async function getHierarchicalCollections(client: StorefrontApiClient, handle: string, depth = 3): Promise<PlatformMenu> {
async function getHierarchicalCollections(client: StorefrontApiClient, handle: string, depth = 3) {
const query = getMenuQuery(depth)
const response = await client.request<MenuQuery>(query, { variables: { handle } })
const mappedItems = response.data?.menu.items.filter((item) => item.resource?.__typename === "Collection")
Expand Down Expand Up @@ -266,6 +268,43 @@ async function getAdminProduct(client: AdminApiClient, id: string) {
return normalizeProduct({ ...response.data?.product, variants })
}

async function getAllProducts(client: StorefrontApiClient, limit: number = 250): Promise<PlatformProduct[]> {
const products: PlatformProduct[] = []
let hasNextPage = true
let cursor: string | null = null

while (hasNextPage) {
const response = await client.request(getProductsQuery, {
variables: { numProducts: limit, cursor },
})

const fetchedProducts = response.data?.products?.edges || []
products.push(...fetchedProducts.map((edge) => normalizeProduct(edge.node)))

hasNextPage = response.data?.products?.pageInfo?.hasNextPage || false
cursor = hasNextPage ? response.data?.products?.pageInfo?.endCursor : null
}

return products
}

async function getAllCollections(client: StorefrontApiClient, limit?: number) {
const collections: PlatformCollection[] = []
let hasNextPage = true
let cursor: string | null = null

while (hasNextPage) {
const response = await client.request(getCollectionsQuery, { variables: { first: limit, after: cursor } })
const fetchedCollections = response.data?.collections?.edges || []
collections.push(...fetchedCollections.map((edge) => normalizeCollection(edge.node)))

hasNextPage = response.data?.collections?.pageInfo?.hasNextPage || false
cursor = hasNextPage ? response?.data?.collections?.pageInfo?.endCursor : null
}

return collections
}

export const storefrontClient = createShopifyClient({
storeDomain: env.SHOPIFY_STORE_DOMAIN || "",
storefrontAccessToken: env.SHOPIFY_STOREFRONT_ACCESS_TOKEN || "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ export const getCollectionQuery = `#graphql
`

export const getCollectionsQuery = `#graphql
query Collections($limit: Int = 250) {
collections(first: $limit, sortKey: TITLE) {
query Collections($first: Int = 250, $after: String) {
collections(first: $first, after: $after, sortKey: TITLE) {
edges {
node {
...singleCollection
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
${collectionFragment}
Expand Down
61 changes: 34 additions & 27 deletions starters/shopify-meilisearch/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"postinstall": "npx patch-package -y",
"generate-bloom-filter": "ts-node ./lib/redirects/generate-bloom-filter.ts",
"codegen": "graphql-codegen && graphql-codegen -p admin",
"coupling-graph": "npx madge --extensions js,jsx,ts,tsx,css,md,mdx ./ --exclude '.next|tailwind.config.js|reset.d.ts|prettier.config.js|postcss.config.js|playwright.config.ts|next.config.js|next-env.d.ts|instrumentation.ts|e2e/|README.md|eslintrc.js' --image graph.svg"
"coupling-graph": "npx madge --extensions js,jsx,ts,tsx,css,md,mdx ./ --exclude '.next|tailwind.config.js|reset.d.ts|prettier.config.js|postcss.config.js|playwright.config.ts|next.config.js|next-env.d.ts|instrumentation.ts|e2e/|README.md|eslintrc.js' --image graph.svg",
"sync": "yarn build:scripts && node scripts/dist/sync.mjs",
"build:scripts": "tsup scripts/ -d scripts/dist"
},
"dependencies": {
"@ai-sdk/openai": "^0.0.16",
Expand All @@ -41,12 +43,16 @@
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toggle-group": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.7",
"@shopify/admin-api-client": "0.2.3",
"@shopify/storefront-api-client": "0.2.3",
"@t3-oss/env-nextjs": "^0.9.2",
"@uidotdev/usehooks": "^2.4.1",
"@vercel/analytics": "^1.2.2",
"@vercel/flags": "2.2.1",
"@vercel/speed-insights": "^1.0.10",
"@vercel/toolbar": "0.1.10",
"ai": "^3.1.15",
"autoprefixer": "^10.4.19",
"bloom-filters": "^3.0.1",
"class-variance-authority": "^0.7.0",
"date-fns": "^3.6.0",
Expand All @@ -57,58 +63,59 @@
"nuqs": "^1.17.1",
"p-retry": "^6.2.0",
"playwright": "^1.42.1",
"postcss": "^8.4.38",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.51.1",
"replicate": "^0.29.1",
"schema-dts": "^1.1.2",
"sharp": "0.32.6",
"sonner": "^1.4.41",
"zustand": "^4.5.2",
"@t3-oss/env-nextjs": "^0.9.2",
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"@shopify/admin-api-client": "0.2.3",
"@shopify/storefront-api-client": "0.2.3"
"zustand": "^4.5.2"
},
"devDependencies": {
"@graphql-codegen/cli": "5.0.2",
"@graphql-codegen/client-preset": "4.1.0",
"@jest/globals": "^29.7.0",
"@playwright/test": "^1.42.1",
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"@shopify/api-codegen-preset": "0.0.6",
"@swc/core": "^1.8.0",
"@t3-oss/env-core": "^0.9.2",
"@testing-library/dom": "^10.3.2",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.2",
"@testing-library/dom": "^10.3.2",
"@testing-library/user-event": "14.5.2",
"@total-typescript/ts-reset": "^0.5.1",
"@types/jest": "^29.5.12",
"@types/node": "^20.11.30",
"@types/react": "^18.2.69",
"@types/react-dom": "^18.2.22",
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"@vercel/style-guide": "^5.0.0",
"eslint-config-turbo": "^1.10.12",
"dotenv": "^16.4.5",
"eslint": "8.54.0",
"eslint-config-next": "14.0.3",
"eslint-config-prettier": "^9.0.0",
"eslint-config-react-app": "^7.0.1",
"eslint-config-turbo": "^1.10.12",
"eslint-plugin-import": "^2.29.0",
"eslint-plugin-react": "7.33.2",
"eslint-plugin-tailwindcss": "^3.13.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"lodash.isequal": "^4.5.0",
"lodash.omit": "^4.5.0",
"patch-package": "^8.0.0",
"prettier": "3.2.5",
"prettier-plugin-tailwindcss": "^0.5.12",
"server-only": "^0.0.1",
"tailwind-merge": "^2.2.2",
"tailwindcss": "^3.4.1",
"zod": "^3.22.4",
"typescript": "5.4.3",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"server-only": "^0.0.1",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"patch-package": "^8.0.0",
"@jest/globals": "^29.7.0",
"@t3-oss/env-core": "^0.9.2",
"@total-typescript/ts-reset": "^0.5.1",
"@types/jest": "^29.5.12",
"@types/react": "^18.2.69",
"@types/react-dom": "^18.2.22",
"@types/node": "^20.11.30",
"@graphql-codegen/cli": "5.0.2",
"@graphql-codegen/client-preset": "4.1.0",
"@shopify/api-codegen-preset": "0.0.6"
"tsup": "^8.0.2",
"typescript": "5.4.3",
"zod": "^3.22.4"
}
}
10 changes: 0 additions & 10 deletions starters/shopify-meilisearch/public/demo-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,6 @@
{
"handle": "home",
"title": "Home",
"descriptionHtml": "",
"updatedAt": "2024-04-05T14:02:23Z",
"id": "gid://shopify/Collection/287131631716",
"descriptionHtml": "",
Expand Down Expand Up @@ -1547,7 +1546,6 @@
"descriptionHtml": "The fashion category in our store is a vibrant and diverse collection designed to cater to all your style needs. From the latest runway trends to timeless classics, our range offers a wide selection of apparel, accessories, and footwear for men, women, and children. Whether you're refreshing your wardrobe for the season, seeking the perfect outfit for a special occasion, or simply indulging in your passion for fashion, our curated selections feature high-quality pieces from renowned brands and emerging designers. With a focus on sustainability, we also present eco-friendly options that merge style with environmental consciousness. Explore our fashion category to discover stylish and affordable choices that will keep you at the forefront of fashion trends",
"updatedAt": "2024-04-05T14:23:20Z",
"id": "gid://shopify/Collection/287132844132",
"descriptionHtml": "The fashion category in our store is a vibrant and diverse collection designed to cater to all your style needs. From the latest runway trends to timeless classics, our range offers a wide selection of apparel, accessories, and footwear for men, women, and children. Whether you're refreshing your wardrobe for the season, seeking the perfect outfit for a special occasion, or simply indulging in your passion for fashion, our curated selections feature high-quality pieces from renowned brands and emerging designers. With a focus on sustainability, we also present eco-friendly options that merge style with environmental consciousness. Explore our fashion category to discover stylish and affordable choices that will keep you at the forefront of fashion trends",
"image": null
}
]
Expand Down Expand Up @@ -1833,7 +1831,6 @@
"descriptionHtml": "",
"updatedAt": "2024-04-05T14:04:01Z",
"id": "gid://shopify/Collection/287131631716",
"descriptionHtml": "",
"image": null
}
]
Expand Down Expand Up @@ -1978,7 +1975,6 @@
{
"handle": "home",
"title": "Home",
"descriptionHtml": "The home category in our store unfolds as a meticulously curated selection aimed at transforming your living spaces into havens of comfort, style, and functionality. From chic furniture that marries form with function to decorative accents that add a personal touch to any room, our collection spans across all areas of your home—living room, bedroom, kitchen, and beyond. Dive into our assortment of bedding, cookware, lighting, and home accessories designed to elevate your everyday life and reflect your unique taste. For those who prioritize sustainability, we offer eco-conscious choices that ensure your home decor is not only beautiful but also kind to the planet. Embrace the joy of home making with our diverse range, offering solutions for every style, budget, and space. Discover everything you need to create a space that truly feels like home.",
"updatedAt": "2024-04-05T14:42:06Z",
"id": "gid://shopify/Collection/287132778596",
"descriptionHtml": "The home category in our store unfolds as a meticulously curated selection aimed at transforming your living spaces into havens of comfort, style, and functionality. From chic furniture that marries form with function to decorative accents that add a personal touch to any room, our collection spans across all areas of your home—living room, bedroom, kitchen, and beyond. Dive into our assortment of bedding, cookware, lighting, and home accessories designed to elevate your everyday life and reflect your unique taste. For those who prioritize sustainability, we offer eco-conscious choices that ensure your home decor is not only beautiful but also kind to the planet. Embrace the joy of home making with our diverse range, offering solutions for every style, budget, and space. Discover everything you need to create a space that truly feels like home.\n",
Expand Down Expand Up @@ -2264,7 +2260,6 @@
{
"handle": "fashion",
"title": "Fashion",
"descriptionHtml": "The fashion category in our store is a vibrant and diverse collection designed to cater to all your style needs. From the latest runway trends to timeless classics, our range offers a wide selection of apparel, accessories, and footwear for men, women, and children. Whether you're refreshing your wardrobe for the season, seeking the perfect outfit for a special occasion, or simply indulging in your passion for fashion, our curated selections feature high-quality pieces from renowned brands and emerging designers. With a focus on sustainability, we also present eco-friendly options that merge style with environmental consciousness. Explore our fashion category to discover stylish and affordable choices that will keep you at the forefront of fashion trends",
"updatedAt": "2024-04-05T14:23:20Z",
"id": "gid://shopify/Collection/287132844132",
"descriptionHtml": "The fashion category in our store is a vibrant and diverse collection designed to cater to all your style needs. From the latest runway trends to timeless classics, our range offers a wide selection of apparel, accessories, and footwear for men, women, and children. Whether you're refreshing your wardrobe for the season, seeking the perfect outfit for a special occasion, or simply indulging in your passion for fashion, our curated selections feature high-quality pieces from renowned brands and emerging designers. With a focus on sustainability, we also present eco-friendly options that merge style with environmental consciousness. Explore our fashion category to discover stylish and affordable choices that will keep you at the forefront of fashion trends",
Expand Down Expand Up @@ -2550,7 +2545,6 @@
{
"handle": "home",
"title": "Home",
"descriptionHtml": "",
"updatedAt": "2024-04-05T14:02:50Z",
"id": "gid://shopify/Collection/287131631716",
"descriptionHtml": "",
Expand Down Expand Up @@ -2977,7 +2971,6 @@
"descriptionHtml": "",
"updatedAt": "2024-04-05T14:03:30Z",
"id": "gid://shopify/Collection/287131631716",
"descriptionHtml": "",
"image": null
}
]
Expand Down Expand Up @@ -3125,7 +3118,6 @@
"descriptionHtml": "The electronics category in our store is a dynamic collection tailored to meet all your technological needs, blending the latest in gadgets with essential household appliances. Explore our range of smartphones, laptops, audio and visual equipment, smart home devices, wearables, drones, and gaming consoles, all designed to enhance your digital experience and streamline your lifestyle. With offerings from top brands and a focus on quality and innovation, our electronics category promises to keep you connected, entertained, and efficient, no matter where you are.",
"updatedAt": "2024-04-05T14:26:45Z",
"id": "gid://shopify/Collection/287132942436",
"descriptionHtml": "The electronics category in our store is a dynamic collection tailored to meet all your technological needs, blending the latest in gadgets with essential household appliances. Explore our range of smartphones, laptops, audio and visual equipment, smart home devices, wearables, drones, and gaming consoles, all designed to enhance your digital experience and streamline your lifestyle. With offerings from top brands and a focus on quality and innovation, our electronics category promises to keep you connected, entertained, and efficient, no matter where you are.\n",
"image": null
}
]
Expand Down Expand Up @@ -3270,7 +3262,6 @@
{
"handle": "home",
"title": "Home",
"descriptionHtml": "",
"updatedAt": "2024-04-05T14:02:23Z",
"id": "gid://shopify/Collection/287131631716",
"descriptionHtml": "",
Expand Down Expand Up @@ -3418,7 +3409,6 @@
{
"handle": "home",
"title": "Home",
"descriptionHtml": "",
"updatedAt": "2024-04-05T14:02:23Z",
"id": "gid://shopify/Collection/287131631716",
"descriptionHtml": "",
Expand Down
Loading

0 comments on commit fcd7629

Please sign in to comment.