feat: client Shopify Admin REST API (search + upload)
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
const API_VERSION = '2024-01'
|
||||
|
||||
function getConfig() {
|
||||
const domain = process.env.SHOPIFY_STORE_DOMAIN
|
||||
const token = process.env.SHOPIFY_ADMIN_API_TOKEN
|
||||
if (!domain || !token) {
|
||||
throw new Error('SHOPIFY_STORE_DOMAIN et SHOPIFY_ADMIN_API_TOKEN requis')
|
||||
}
|
||||
return {
|
||||
baseUrl: `https://${domain}/admin/api/${API_VERSION}`,
|
||||
headers: {
|
||||
'X-Shopify-Access-Token': token,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export type ShopifyProductResult =
|
||||
| { found: false }
|
||||
| { found: true; shopifyId: string; title: string }
|
||||
|
||||
/**
|
||||
* Recherche un produit Shopify par sa référence.
|
||||
* Tente d'abord par handle (ex: "ref-1042"), puis par titre exact.
|
||||
*/
|
||||
export async function searchProductByRef(ref: string): Promise<ShopifyProductResult> {
|
||||
const { baseUrl, headers } = getConfig()
|
||||
|
||||
// Normalise la référence en handle Shopify (minuscules, tirets)
|
||||
const handle = ref.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '')
|
||||
|
||||
const tryFetch = async (params: string) => {
|
||||
const res = await fetch(`${baseUrl}/products.json?${params}&fields=id,title,handle&limit=1`, { headers })
|
||||
if (!res.ok) throw new Error(`Shopify API error: ${res.status}`)
|
||||
const data = await res.json()
|
||||
return (data.products ?? []) as Array<{ id: number; title: string; handle: string }>
|
||||
}
|
||||
|
||||
let products = await tryFetch(`handle=${encodeURIComponent(handle)}`)
|
||||
|
||||
if (products.length === 0) {
|
||||
products = await tryFetch(`title=${encodeURIComponent(ref)}`)
|
||||
}
|
||||
|
||||
if (products.length === 0) return { found: false }
|
||||
|
||||
return {
|
||||
found: true,
|
||||
shopifyId: String(products[0].id),
|
||||
title: products[0].title,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload une image (base64) vers un produit Shopify via l'API REST.
|
||||
* @param shopifyProductId — ID numérique du produit (string)
|
||||
* @param imageBase64 — contenu JPEG encodé en base64 (sans le préfixe data:)
|
||||
* @param filename — nom de fichier avec extension (ex: "REF-1042.jpg")
|
||||
*/
|
||||
export async function uploadProductImage(
|
||||
shopifyProductId: string,
|
||||
imageBase64: string,
|
||||
filename: string,
|
||||
): Promise<{ url: string }> {
|
||||
const { baseUrl, headers } = getConfig()
|
||||
|
||||
const res = await fetch(`${baseUrl}/products/${shopifyProductId}/images.json`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify({ image: { attachment: imageBase64, filename } }),
|
||||
})
|
||||
|
||||
if (!res.ok) {
|
||||
const body = await res.text()
|
||||
throw new Error(`Shopify upload error: ${res.status} — ${body}`)
|
||||
}
|
||||
|
||||
const data = await res.json()
|
||||
return { url: data.image.src as string }
|
||||
}
|
||||
Reference in New Issue
Block a user