Implement product updating logic
This commit is contained in:
@@ -15,18 +15,21 @@ const server = Bun.serve({
|
|||||||
async POST(req) {
|
async POST(req) {
|
||||||
const payload: Printful.Webhook.EventPayload = await req.json()
|
const payload: Printful.Webhook.EventPayload = await req.json()
|
||||||
console.log(JSON.stringify(payload));
|
console.log(JSON.stringify(payload));
|
||||||
|
console.log("PRINTFUL WEBHOOK: " + payload.type);
|
||||||
switch (payload.type) {
|
switch (payload.type) {
|
||||||
|
// ADD/UPDATE
|
||||||
case Printful.Webhook.Event.ProductUpdated:
|
case Printful.Webhook.Event.ProductUpdated:
|
||||||
const printfulProduct = await Printful.getSyncProduct(payload.data.sync_product.id)
|
const printfulProduct = await Printful.getSyncProduct(payload.data.sync_product.id)
|
||||||
const productRecord = productRecords.findFromPrintful(payload.data.sync_product.id)
|
const productRecord = productRecords.findFromPrintful(payload.data.sync_product.id)
|
||||||
|
|
||||||
if (productRecord) {
|
if (productRecord) {
|
||||||
await Webflow.createProduct(printfulProduct, productRecords);
|
await Webflow.updateProduct(printfulProduct, productRecords);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
await Webflow.createProduct(printfulProduct, productRecords);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
// DELETE
|
||||||
case Printful.Webhook.Event.ProductDeleted:
|
case Printful.Webhook.Event.ProductDeleted:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -38,4 +41,6 @@ const server = Bun.serve({
|
|||||||
development: true
|
development: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
productRecords.add({ webflowProductId: 123, printfulProductId: 321 });
|
||||||
|
|
||||||
console.log(`Listening on ${server.url}`);
|
console.log(`Listening on ${server.url}`);
|
||||||
|
|||||||
+103
-8
@@ -43,6 +43,108 @@ export namespace Webflow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function updateProduct(printfulProduct: Printful.Products.SyncProduct, productRecords: ProductRecords) {
|
||||||
|
const webflowProductId = productRecords.findFromPrintful(printfulProduct.result.sync_product.id)?.webflowProductId;
|
||||||
|
if (!webflowProductId) {
|
||||||
|
throw new Error("Product is not recognized");
|
||||||
|
}
|
||||||
|
|
||||||
|
const printfulVariants = printfulProduct.result.sync_variants;
|
||||||
|
const webflowVariants: Products.Sku[] = [];
|
||||||
|
for (const printfulVariant of printfulVariants) {
|
||||||
|
webflowVariants.push({
|
||||||
|
"fieldData": {
|
||||||
|
"name": printfulVariant.name,
|
||||||
|
"slug": formatSlug(printfulVariant.name),
|
||||||
|
"sku-values": {
|
||||||
|
"color": printfulVariant.color,
|
||||||
|
"size": printfulVariant.size,
|
||||||
|
},
|
||||||
|
"price": {
|
||||||
|
"value": +printfulVariant.retail_price * 100,
|
||||||
|
"unit": printfulVariant.currency,
|
||||||
|
"currency": printfulVariant.currency
|
||||||
|
},
|
||||||
|
// TODO: sync image
|
||||||
|
"main-image": "https://www.example.com/image.jpg"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const variantColors = printfulVariants.map(v => v.color);
|
||||||
|
const variantSizes = printfulVariants.map(v => v.size);
|
||||||
|
const variantExternalIds = printfulVariants.map(v => v.external_id);
|
||||||
|
|
||||||
|
const foundColors = Array.from(new Set(variantColors));
|
||||||
|
const foundSizes = Array.from(new Set(variantSizes));
|
||||||
|
|
||||||
|
let updateProductResponse = await fetch(`${API_URL}/products/${webflowProductId}`, {
|
||||||
|
method: "PATCH",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": `bearer ${Bun.env.WEBFLOW_AUTH}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
"product": {
|
||||||
|
"fieldData": {
|
||||||
|
"name": printfulProduct.result.sync_product.name,
|
||||||
|
"slug": formatSlug(printfulProduct.result.sync_product.name),
|
||||||
|
"sku-properties": [
|
||||||
|
{
|
||||||
|
"id": "color",
|
||||||
|
"name": "Color",
|
||||||
|
"enum": foundColors.map(color => ({
|
||||||
|
"id": color,
|
||||||
|
"slug": formatSlug(color),
|
||||||
|
"name": color
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "size",
|
||||||
|
"name": "Size",
|
||||||
|
"enum": foundSizes.map(size => ({
|
||||||
|
"id": size,
|
||||||
|
"slug": formatSlug(size),
|
||||||
|
"name": size
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sku": webflowVariants[0]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
updateProductResponse = await updateProductResponse.json();
|
||||||
|
|
||||||
|
const getProductResponse = await fetch(`${API_URL}/products/${webflowProductId}`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Authorization": `bearer ${Bun.env.WEBFLOW_AUTH}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const product = await getProductResponse.json();
|
||||||
|
|
||||||
|
for (let i = 0; i < product["skus"].length; ++i) {
|
||||||
|
const webflowSkuId = variantExternalIds[i];
|
||||||
|
|
||||||
|
await fetch(`${API_URL}/products/${webflowProductId}/skus/${webflowSkuId}`, {
|
||||||
|
method: "PATCH",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": `bearer ${Bun.env.WEBFLOW_AUTH}`
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
"sku": webflowVariants[i]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"updateProduct": updateProductResponse,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export async function createProduct(printfulProduct: Printful.Products.SyncProduct, productRecords: ProductRecords) {
|
export async function createProduct(printfulProduct: Printful.Products.SyncProduct, productRecords: ProductRecords) {
|
||||||
const printfulVariants = printfulProduct.result.sync_variants;
|
const printfulVariants = printfulProduct.result.sync_variants;
|
||||||
|
|
||||||
@@ -61,7 +163,7 @@ export namespace Webflow {
|
|||||||
"unit": printfulVariant.currency,
|
"unit": printfulVariant.currency,
|
||||||
"currency": printfulVariant.currency
|
"currency": printfulVariant.currency
|
||||||
},
|
},
|
||||||
// TODO
|
// TODO: sync image
|
||||||
"main-image": "https://www.example.com/image.jpg"
|
"main-image": "https://www.example.com/image.jpg"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -71,7 +173,6 @@ export namespace Webflow {
|
|||||||
const foundSizes = Array.from(new Set(printfulVariants.map(v => v.size)));
|
const foundSizes = Array.from(new Set(printfulVariants.map(v => v.size)));
|
||||||
|
|
||||||
// CREATE WEBFLOW PRODUCT
|
// CREATE WEBFLOW PRODUCT
|
||||||
console.log("CREATE WEBFLOW PRODUCT");
|
|
||||||
let addProductResponse = await fetch(`${API_URL}/products`, {
|
let addProductResponse = await fetch(`${API_URL}/products`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -109,13 +210,11 @@ export namespace Webflow {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
addProductResponse = await addProductResponse.json();
|
addProductResponse = await addProductResponse.json();
|
||||||
console.log(JSON.stringify(addProductResponse));
|
|
||||||
|
|
||||||
const webflowProductId = addProductResponse["product"]["id"];
|
const webflowProductId = addProductResponse["product"]["id"];
|
||||||
const printfulProductId = printfulProduct.result.sync_product.id;
|
const printfulProductId = printfulProduct.result.sync_product.id;
|
||||||
|
|
||||||
// CREATE WEBFLOW PRODUCT SKUs
|
// CREATE WEBFLOW PRODUCT SKUs
|
||||||
console.log("CREATE SKUS");
|
|
||||||
let createSkuResponse = await fetch(`${API_URL}/products/${webflowProductId}/skus`, {
|
let createSkuResponse = await fetch(`${API_URL}/products/${webflowProductId}/skus`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -127,12 +226,10 @@ export namespace Webflow {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
createSkuResponse = await createSkuResponse.json();
|
createSkuResponse = await createSkuResponse.json();
|
||||||
console.log(JSON.stringify(createSkuResponse));
|
|
||||||
|
|
||||||
const responseSkus = [addProductResponse["sku"], ...createSkuResponse["skus"]];
|
const responseSkus = [addProductResponse["sku"], ...createSkuResponse["skus"]];
|
||||||
|
|
||||||
// SYNC WEBFLOW/PRINTFUL PRODUCT AND VARIANT IDs
|
// SYNC WEBFLOW/PRINTFUL PRODUCT AND VARIANT IDs
|
||||||
console.log("SYNC PRODUCT IDs");
|
|
||||||
let modifyPrintfulProductResponse = await fetch(`${Printful.API_URL}/store/products/${printfulProductId}`, {
|
let modifyPrintfulProductResponse = await fetch(`${Printful.API_URL}/store/products/${printfulProductId}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -151,10 +248,8 @@ export namespace Webflow {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
modifyPrintfulProductResponse = await modifyPrintfulProductResponse.json();
|
modifyPrintfulProductResponse = await modifyPrintfulProductResponse.json();
|
||||||
console.log(JSON.stringify(modifyPrintfulProductResponse));
|
|
||||||
|
|
||||||
// CACHE WEBFLOW/PRINTFUL PRODUCT ASSOCIATION
|
// CACHE WEBFLOW/PRINTFUL PRODUCT ASSOCIATION
|
||||||
console.log("CACHING PRODUCT ASSOCIATION");
|
|
||||||
productRecords.add({ printfulProductId, webflowProductId });
|
productRecords.add({ printfulProductId, webflowProductId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user