← back to Dw War Room
vite.config.ts
108 lines
import { defineConfig } from 'vite';
import { resolve } from 'path';
import https from 'https';
// Shopify GraphQL search proxy for Vite dev server
function shopifySearchPlugin() {
const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
const SHOPIFY_TOKEN = (process.env.SHOPIFY_ADMIN_TOKEN || '');
const API_VERSION = '2024-01';
return {
name: 'shopify-search-proxy',
configureServer(server: any) {
server.middlewares.use('/api/shopify/search', (req: any, res: any) => {
const url = new URL(req.url || '/', `http://${req.headers.host}`);
const query = url.searchParams.get('q') || '';
const limit = Math.min(parseInt(url.searchParams.get('limit') || '10', 10), 20);
if (query.length < 2) {
res.writeHead(400, { 'Content-Type': 'application/json' });
return res.end(JSON.stringify({ error: 'Query too short' }));
}
const gqlQuery = JSON.stringify({
query: `{
products(first: ${limit}, query: "${query.replace(/"/g, '\\"')}") {
edges { node {
id title vendor productType handle tags
images(first: 1) { edges { node { url } } }
variants(first: 1) { edges { node { price sku } } }
}}
}
}`
});
const options = {
hostname: SHOPIFY_STORE,
path: `/admin/api/${API_VERSION}/graphql.json`,
method: 'POST',
headers: {
'X-Shopify-Access-Token': SHOPIFY_TOKEN,
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(gqlQuery),
},
};
const proxyReq = https.request(options, (shopifyRes) => {
let data = '';
shopifyRes.on('data', (chunk: string) => { data += chunk; });
shopifyRes.on('end', () => {
try {
const gql = JSON.parse(data);
const edges = gql?.data?.products?.edges || [];
const products = edges.map(({ node }: any) => ({
id: parseInt(node.id.replace('gid://shopify/Product/', ''), 10),
title: node.title,
vendor: node.vendor,
product_type: node.productType,
handle: node.handle,
tags: node.tags ? node.tags.join(', ') : '',
images: node.images?.edges?.length
? node.images.edges.map((e: any) => ({ src: e.node.url }))
: [],
variants: node.variants?.edges?.length
? node.variants.edges.map((e: any) => ({ price: e.node.price, sku: e.node.sku || '' }))
: [{ price: '0.00', sku: '' }],
}));
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ products }));
} catch {
res.writeHead(502, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Parse error', products: [] }));
}
});
});
proxyReq.on('error', () => {
res.writeHead(502, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Proxy error', products: [] }));
});
proxyReq.write(gqlQuery);
proxyReq.end();
});
},
};
}
export default defineConfig({
plugins: [shopifySearchPlugin()],
server: {
port: 4060,
host: '0.0.0.0',
},
preview: {
port: 4060,
host: '0.0.0.0',
},
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
showroom: resolve(__dirname, 'showroom.html'),
},
},
},
});