medusa-plugin-printify 0.1.0

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.
Files changed (39) hide show
  1. package/.medusa/server/jest.config.js +20 -0
  2. package/.medusa/server/jest.setup.js +4 -0
  3. package/.medusa/server/src/admin/index.js +472 -0
  4. package/.medusa/server/src/admin/index.mjs +473 -0
  5. package/.medusa/server/src/api/admin/plugin/route.js +7 -0
  6. package/.medusa/server/src/api/admin/printify/orders/[id]/submit/route.js +19 -0
  7. package/.medusa/server/src/api/admin/printify/orders/route.js +18 -0
  8. package/.medusa/server/src/api/admin/printify/products/[id]/route.js +113 -0
  9. package/.medusa/server/src/api/admin/printify/products/route.js +35 -0
  10. package/.medusa/server/src/api/admin/printify/shops/route.js +18 -0
  11. package/.medusa/server/src/api/middlewares.js +12 -0
  12. package/.medusa/server/src/api/store/plugin/route.js +7 -0
  13. package/.medusa/server/src/api/webhooks/printify/route.js +102 -0
  14. package/.medusa/server/src/jobs/auto-submit-orders-job.js +31 -0
  15. package/.medusa/server/src/jobs/sync-products-job.js +23 -0
  16. package/.medusa/server/src/lib/webhook-utils.js +13 -0
  17. package/.medusa/server/src/links/printify-order-medusa-order.js +10 -0
  18. package/.medusa/server/src/links/printify-product-medusa-product.js +10 -0
  19. package/.medusa/server/src/modules/printify/api-client.js +67 -0
  20. package/.medusa/server/src/modules/printify/index.js +13 -0
  21. package/.medusa/server/src/modules/printify/migrations/Migration20260305115907.js +21 -0
  22. package/.medusa/server/src/modules/printify/migrations/Migration20260313185144.js +14 -0
  23. package/.medusa/server/src/modules/printify/models/order.js +18 -0
  24. package/.medusa/server/src/modules/printify/models/product.js +22 -0
  25. package/.medusa/server/src/modules/printify/models/shop.js +11 -0
  26. package/.medusa/server/src/modules/printify/service.js +38 -0
  27. package/.medusa/server/src/modules/printify/types.js +3 -0
  28. package/.medusa/server/src/subscribers/order-placed.js +55 -0
  29. package/.medusa/server/src/subscribers/plugin-registered.js +37 -0
  30. package/.medusa/server/src/utils/build-variant-prices.js +17 -0
  31. package/.medusa/server/src/utils/currency-converter.js +46 -0
  32. package/.medusa/server/src/workflows/create-printify-order.js +86 -0
  33. package/.medusa/server/src/workflows/index.js +12 -0
  34. package/.medusa/server/src/workflows/option-mapper.js +64 -0
  35. package/.medusa/server/src/workflows/submit-printify-order.js +29 -0
  36. package/.medusa/server/src/workflows/sync-products.js +313 -0
  37. package/.medusa/server/src/workflows/sync-shops.js +30 -0
  38. package/README.md +253 -0
  39. package/package.json +78 -0
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildVariantPrices = buildVariantPrices;
4
+ const currency_converter_1 = require("./currency-converter");
5
+ /**
6
+ * Builds a Medusa-compatible prices array for a variant,
7
+ * converting the Printify USD price (in cents) to all active currencies.
8
+ * Medusa stores amounts in major currency units (e.g. 19.99 = $19.99).
9
+ */
10
+ function buildVariantPrices(printifyPriceUsdCents, currencies, rates) {
11
+ const priceInDollars = (printifyPriceUsdCents ?? 0) / 100;
12
+ return currencies.map((currency) => ({
13
+ amount: (0, currency_converter_1.convertPrice)(priceInDollars, currency, rates),
14
+ currency_code: currency,
15
+ }));
16
+ }
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQtdmFyaWFudC1wcmljZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvYnVpbGQtdmFyaWFudC1wcmljZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFPQSxnREFVQztBQWpCRCw2REFBdUU7QUFFdkU7Ozs7R0FJRztBQUNILFNBQWdCLGtCQUFrQixDQUNoQyxxQkFBNkIsRUFDN0IsVUFBb0IsRUFDcEIsS0FBb0I7SUFFcEIsTUFBTSxjQUFjLEdBQUcsQ0FBQyxxQkFBcUIsSUFBSSxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUE7SUFDekQsT0FBTyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ25DLE1BQU0sRUFBRSxJQUFBLGlDQUFZLEVBQUMsY0FBYyxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUM7UUFDckQsYUFBYSxFQUFFLFFBQVE7S0FDeEIsQ0FBQyxDQUFDLENBQUE7QUFDTCxDQUFDIn0=
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchExchangeRates = fetchExchangeRates;
7
+ exports.convertPrice = convertPrice;
8
+ const axios_1 = __importDefault(require("axios"));
9
+ /**
10
+ * Fetches latest exchange rates from USD to the given currency codes
11
+ * using the Frankfurter API (free, ECB-backed, no API key needed).
12
+ * Returns a map of lowercase currency_code → rate relative to USD.
13
+ */
14
+ async function fetchExchangeRates(currencyCodes) {
15
+ const nonUsd = currencyCodes
16
+ .map((c) => c.toLowerCase())
17
+ .filter((c) => c !== "usd");
18
+ if (nonUsd.length === 0)
19
+ return {};
20
+ try {
21
+ const symbols = nonUsd.map((c) => c.toUpperCase()).join(",");
22
+ const { data } = await axios_1.default.get("https://api.frankfurter.dev/v1/latest", { params: { base: "USD", symbols }, timeout: 10000 });
23
+ const rates = {};
24
+ for (const [code, rate] of Object.entries(data.rates)) {
25
+ rates[code.toLowerCase()] = rate;
26
+ }
27
+ return rates;
28
+ }
29
+ catch (err) {
30
+ throw new Error(`Failed to fetch exchange rates: ${err instanceof Error ? err.message : err}`);
31
+ }
32
+ }
33
+ /**
34
+ * Converts a price in USD to the target currency using the given rates.
35
+ * Returns the converted amount rounded to 2 decimal places.
36
+ */
37
+ function convertPrice(amountInUsd, targetCurrency, rates) {
38
+ const currency = targetCurrency.toLowerCase();
39
+ if (currency === "usd")
40
+ return amountInUsd;
41
+ const rate = rates[currency];
42
+ if (rate == null)
43
+ throw new Error(`No exchange rate for ${currency}`);
44
+ return Math.round(amountInUsd * rate * 100) / 100;
45
+ }
46
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VycmVuY3ktY29udmVydGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL2N1cnJlbmN5LWNvbnZlcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQVNBLGdEQXlCQztBQU1ELG9DQVVDO0FBbERELGtEQUF5QjtBQUl6Qjs7OztHQUlHO0FBQ0ksS0FBSyxVQUFVLGtCQUFrQixDQUN0QyxhQUF1QjtJQUV2QixNQUFNLE1BQU0sR0FBRyxhQUFhO1NBQ3pCLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1NBQzNCLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFBO0lBRTdCLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxFQUFFLENBQUE7SUFFbEMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQzVELE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxNQUFNLGVBQUssQ0FBQyxHQUFHLENBQzlCLHVDQUF1QyxFQUN2QyxFQUFFLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUNyRCxDQUFBO1FBQ0QsTUFBTSxLQUFLLEdBQWtCLEVBQUUsQ0FBQTtRQUMvQixLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN0RCxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLEdBQUcsSUFBYyxDQUFBO1FBQzVDLENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQTtJQUNkLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2IsTUFBTSxJQUFJLEtBQUssQ0FDYixtQ0FBbUMsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQzlFLENBQUE7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQWdCLFlBQVksQ0FDMUIsV0FBbUIsRUFDbkIsY0FBc0IsRUFDdEIsS0FBb0I7SUFFcEIsTUFBTSxRQUFRLEdBQUcsY0FBYyxDQUFDLFdBQVcsRUFBRSxDQUFBO0lBQzdDLElBQUksUUFBUSxLQUFLLEtBQUs7UUFBRSxPQUFPLFdBQVcsQ0FBQTtJQUMxQyxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDNUIsSUFBSSxJQUFJLElBQUksSUFBSTtRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLFFBQVEsRUFBRSxDQUFDLENBQUE7SUFDckUsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsR0FBRyxJQUFJLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFBO0FBQ25ELENBQUMifQ==
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createPrintifyOrderWorkflow = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const printify_1 = require("../modules/printify");
6
+ const buildOrderPayloadStep = (0, workflows_sdk_1.createStep)("printify-build-order-payload-step", async (input) => {
7
+ const address = {
8
+ first_name: input.address.firstName,
9
+ last_name: input.address.lastName,
10
+ email: input.address.email,
11
+ phone: input.address.phone,
12
+ address1: input.address.address1,
13
+ address2: input.address.address2,
14
+ city: input.address.city,
15
+ region: input.address.province,
16
+ zip: input.address.postalCode,
17
+ country: input.address.countryCode.toUpperCase(),
18
+ };
19
+ const payload = {
20
+ external_id: input.medusaOrderId,
21
+ label: `Medusa Order ${input.medusaOrderId}`,
22
+ line_items: input.lineItems.map((item) => ({
23
+ product_id: item.printify_product_id,
24
+ variant_id: item.variant_id,
25
+ quantity: item.quantity,
26
+ })),
27
+ shipping_method: input.shippingMethod,
28
+ send_shipping_notification: false,
29
+ address_to: address,
30
+ };
31
+ return new workflows_sdk_1.StepResponse({ payload, address });
32
+ });
33
+ const createOrderInPrintifyStep = (0, workflows_sdk_1.createStep)("printify-create-order-in-printify-step", async ({ payload, shopId }, { container }) => {
34
+ const service = container.resolve(printify_1.PRINTIFY_MODULE);
35
+ const order = await service.getApiClient().createOrder(shopId, payload);
36
+ return new workflows_sdk_1.StepResponse(order, order.id);
37
+ }, async (printifyOrderId) => {
38
+ console.warn(`[printify] compensation: order ${printifyOrderId} may need manual cancellation in Printify`);
39
+ });
40
+ const persistLocalOrderStep = (0, workflows_sdk_1.createStep)("printify-persist-local-order-step", async ({ printifyOrder, input, address }, { container }) => {
41
+ const service = container.resolve(printify_1.PRINTIFY_MODULE);
42
+ // Capture variant costs immutably at order creation time
43
+ const costPerItem = {};
44
+ let totalCost = 0;
45
+ for (const item of input.lineItems) {
46
+ const products = await service.listPrintifyProducts({
47
+ printify_id: String(item.printify_product_id),
48
+ });
49
+ if (products.length > 0) {
50
+ const product = products[0];
51
+ const variants = product.variants || [];
52
+ const variant = variants.find((v) => v.id === item.variant_id);
53
+ if (variant) {
54
+ costPerItem[`${item.printify_product_id}:${item.variant_id}`] = variant.cost;
55
+ totalCost += variant.cost * item.quantity;
56
+ }
57
+ }
58
+ }
59
+ const created = await service.createPrintifyOrders([
60
+ {
61
+ printify_id: String(printifyOrder.id),
62
+ shop_id: input.shopId,
63
+ medusa_order_id: input.medusaOrderId,
64
+ status: printifyOrder.status || "pending",
65
+ shipping_method: String(input.shippingMethod),
66
+ line_items: input.lineItems,
67
+ address_to: address,
68
+ total_cost: totalCost || null,
69
+ cost_per_item: Object.keys(costPerItem).length > 0 ? costPerItem : null,
70
+ submitted_at: null,
71
+ },
72
+ ]);
73
+ const localOrder = Array.isArray(created) ? created[0] : created;
74
+ return new workflows_sdk_1.StepResponse({
75
+ printifyOrderId: printifyOrder.id,
76
+ localOrderId: localOrder.id,
77
+ status: printifyOrder.status,
78
+ });
79
+ });
80
+ exports.createPrintifyOrderWorkflow = (0, workflows_sdk_1.createWorkflow)("create-printify-order", (input) => {
81
+ const { payload, address } = buildOrderPayloadStep(input);
82
+ const printifyOrder = createOrderInPrintifyStep({ payload, shopId: input.shopId });
83
+ const result = persistLocalOrderStep({ printifyOrder, input, address });
84
+ return new workflows_sdk_1.WorkflowResponse(result);
85
+ });
86
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLXByaW50aWZ5LW9yZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9jcmVhdGUtcHJpbnRpZnktb3JkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBSzBDO0FBQzFDLGtEQUFxRDtBQW9DckQsTUFBTSxxQkFBcUIsR0FBRyxJQUFBLDBCQUFVLEVBQ3RDLG1DQUFtQyxFQUNuQyxLQUFLLEVBQUUsS0FBK0IsRUFBNkMsRUFBRTtJQUNuRixNQUFNLE9BQU8sR0FBb0I7UUFDL0IsVUFBVSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUztRQUNuQyxTQUFTLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRO1FBQ2pDLEtBQUssRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUs7UUFDMUIsS0FBSyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSztRQUMxQixRQUFRLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRO1FBQ2hDLFFBQVEsRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVE7UUFDaEMsSUFBSSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSTtRQUN4QixNQUFNLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRO1FBQzlCLEdBQUcsRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLFVBQVU7UUFDN0IsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLFdBQVcsRUFBRTtLQUNqRCxDQUFBO0lBRUQsTUFBTSxPQUFPLEdBQStCO1FBQzFDLFdBQVcsRUFBRSxLQUFLLENBQUMsYUFBYTtRQUNoQyxLQUFLLEVBQUUsZ0JBQWdCLEtBQUssQ0FBQyxhQUFhLEVBQUU7UUFDNUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ3pDLFVBQVUsRUFBRSxJQUFJLENBQUMsbUJBQW1CO1lBQ3BDLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVTtZQUMzQixRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7U0FDeEIsQ0FBQyxDQUFDO1FBQ0gsZUFBZSxFQUFFLEtBQUssQ0FBQyxjQUFjO1FBQ3JDLDBCQUEwQixFQUFFLEtBQUs7UUFDakMsVUFBVSxFQUFFLE9BQU87S0FDcEIsQ0FBQTtJQUVELE9BQU8sSUFBSSw0QkFBWSxDQUFDLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUE7QUFDL0MsQ0FBQyxDQUNGLENBQUE7QUFFRCxNQUFNLHlCQUF5QixHQUFHLElBQUEsMEJBQVUsRUFDMUMsd0NBQXdDLEVBQ3hDLEtBQUssRUFDSCxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQTJELEVBQzVFLEVBQUUsU0FBUyxFQUFFLEVBQ2IsRUFBRTtJQUNGLE1BQU0sT0FBTyxHQUEwQixTQUFTLENBQUMsT0FBTyxDQUFDLDBCQUFlLENBQUMsQ0FBQTtJQUN6RSxNQUFNLEtBQUssR0FBRyxNQUFNLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFBO0lBQ3ZFLE9BQU8sSUFBSSw0QkFBWSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUE7QUFDMUMsQ0FBQyxFQUNELEtBQUssRUFBRSxlQUF1QixFQUFFLEVBQUU7SUFDaEMsT0FBTyxDQUFDLElBQUksQ0FDVixrQ0FBa0MsZUFBZSwyQ0FBMkMsQ0FDN0YsQ0FBQTtBQUNILENBQUMsQ0FDRixDQUFBO0FBUUQsTUFBTSxxQkFBcUIsR0FBRyxJQUFBLDBCQUFVLEVBQ3RDLG1DQUFtQyxFQUNuQyxLQUFLLEVBQUUsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBcUIsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDNUUsTUFBTSxPQUFPLEdBQTBCLFNBQVMsQ0FBQyxPQUFPLENBQUMsMEJBQWUsQ0FBQyxDQUFBO0lBRXpFLHlEQUF5RDtJQUN6RCxNQUFNLFdBQVcsR0FBMkIsRUFBRSxDQUFBO0lBQzlDLElBQUksU0FBUyxHQUFHLENBQUMsQ0FBQTtJQUVqQixLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNuQyxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQztZQUNsRCxXQUFXLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQztTQUM5QyxDQUFDLENBQUE7UUFDRixJQUFJLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDeEIsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQzNCLE1BQU0sUUFBUSxHQUFJLE9BQU8sQ0FBQyxRQUEyRCxJQUFJLEVBQUUsQ0FBQTtZQUMzRixNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQTtZQUM5RCxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNaLFdBQVcsQ0FBQyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFBO2dCQUM1RSxTQUFTLElBQUksT0FBTyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFBO1lBQzNDLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLG9CQUFvQixDQUFDO1FBQ2pEO1lBQ0UsV0FBVyxFQUFFLE1BQU0sQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1lBQ3JDLE9BQU8sRUFBRSxLQUFLLENBQUMsTUFBTTtZQUNyQixlQUFlLEVBQUUsS0FBSyxDQUFDLGFBQWE7WUFDcEMsTUFBTSxFQUFFLGFBQWEsQ0FBQyxNQUFNLElBQUksU0FBUztZQUN6QyxlQUFlLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUM7WUFDN0MsVUFBVSxFQUFFLEtBQUssQ0FBQyxTQUErQztZQUNqRSxVQUFVLEVBQUUsT0FBTztZQUNuQixVQUFVLEVBQUUsU0FBUyxJQUFJLElBQUk7WUFDN0IsYUFBYSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJO1lBQ3ZFLFlBQVksRUFBRSxJQUFJO1NBQ25CO0tBQ0YsQ0FBQyxDQUFBO0lBRUYsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUE7SUFFaEUsT0FBTyxJQUFJLDRCQUFZLENBQUM7UUFDdEIsZUFBZSxFQUFFLGFBQWEsQ0FBQyxFQUFFO1FBQ2pDLFlBQVksRUFBRSxVQUFVLENBQUMsRUFBWTtRQUNyQyxNQUFNLEVBQUUsYUFBYSxDQUFDLE1BQU07S0FDN0IsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUNGLENBQUE7QUFFWSxRQUFBLDJCQUEyQixHQUFHLElBQUEsOEJBQWMsRUFDdkQsdUJBQXVCLEVBQ3ZCLENBQUMsS0FBK0IsRUFBRSxFQUFFO0lBQ2xDLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEdBQUcscUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDekQsTUFBTSxhQUFhLEdBQUcseUJBQXlCLENBQUMsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFBO0lBQ2xGLE1BQU0sTUFBTSxHQUFHLHFCQUFxQixDQUFDLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFBO0lBQ3ZFLE9BQU8sSUFBSSxnQ0FBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQTtBQUNyQyxDQUFDLENBQ0YsQ0FBQSJ9
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.submitPrintifyOrderWorkflow = exports.createPrintifyOrderWorkflow = exports.syncProductsWorkflow = exports.syncShopsWorkflow = void 0;
4
+ var sync_shops_1 = require("./sync-shops");
5
+ Object.defineProperty(exports, "syncShopsWorkflow", { enumerable: true, get: function () { return sync_shops_1.syncShopsWorkflow; } });
6
+ var sync_products_1 = require("./sync-products");
7
+ Object.defineProperty(exports, "syncProductsWorkflow", { enumerable: true, get: function () { return sync_products_1.syncProductsWorkflow; } });
8
+ var create_printify_order_1 = require("./create-printify-order");
9
+ Object.defineProperty(exports, "createPrintifyOrderWorkflow", { enumerable: true, get: function () { return create_printify_order_1.createPrintifyOrderWorkflow; } });
10
+ var submit_printify_order_1 = require("./submit-printify-order");
11
+ Object.defineProperty(exports, "submitPrintifyOrderWorkflow", { enumerable: true, get: function () { return submit_printify_order_1.submitPrintifyOrderWorkflow; } });
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJDQUFnRDtBQUF2QywrR0FBQSxpQkFBaUIsT0FBQTtBQUMxQixpREFBc0Q7QUFBN0MscUhBQUEsb0JBQW9CLE9BQUE7QUFDN0IsaUVBQW9HO0FBQTNGLG9JQUFBLDJCQUEyQixPQUFBO0FBQ3BDLGlFQUFxRTtBQUE1RCxvSUFBQSwyQkFBMkIsT0FBQSJ9
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mapPrintifyOptions = mapPrintifyOptions;
4
+ function mapPrintifyOptions(options, variants, images) {
5
+ if (!options || options.length === 0) {
6
+ return null;
7
+ }
8
+ // Build lookup: option value ID -> { optionName, valueTitle }
9
+ const valueLookup = new Map();
10
+ for (const opt of options) {
11
+ for (const val of opt.values) {
12
+ valueLookup.set(val.id, { optionName: opt.name, valueTitle: val.title });
13
+ }
14
+ }
15
+ const enabledVariants = variants.filter((v) => v.is_enabled);
16
+ if (enabledVariants.length === 0) {
17
+ return null;
18
+ }
19
+ // Build variant option map: printify variant ID -> { OptionName: ValueTitle }
20
+ const variantOptionMap = new Map();
21
+ for (const v of enabledVariants) {
22
+ const optionValues = {};
23
+ for (const valId of v.options) {
24
+ const lookup = valueLookup.get(valId);
25
+ if (lookup) {
26
+ optionValues[lookup.optionName] = lookup.valueTitle;
27
+ }
28
+ }
29
+ variantOptionMap.set(v.id, optionValues);
30
+ }
31
+ // Collect only option values used by enabled variants
32
+ const usedValueIds = new Set();
33
+ for (const v of enabledVariants) {
34
+ for (const valId of v.options) {
35
+ usedValueIds.add(valId);
36
+ }
37
+ }
38
+ // Build Medusa options with only used values, preserving Printify option order
39
+ const medusaOptions = options
40
+ .map((opt) => ({
41
+ title: opt.name,
42
+ values: [...new Set(opt.values
43
+ .filter((val) => usedValueIds.has(val.id))
44
+ .map((val) => val.title))],
45
+ }))
46
+ .filter((opt) => opt.values.length > 0);
47
+ // Build variant image map: printify variant ID -> image URLs
48
+ const enabledIds = new Set(enabledVariants.map((v) => v.id));
49
+ const variantImageMap = new Map();
50
+ for (const img of images) {
51
+ if (!img.variant_ids)
52
+ continue;
53
+ for (const vid of img.variant_ids) {
54
+ if (!enabledIds.has(vid))
55
+ continue;
56
+ if (!variantImageMap.has(vid)) {
57
+ variantImageMap.set(vid, []);
58
+ }
59
+ variantImageMap.get(vid).push({ url: img.src });
60
+ }
61
+ }
62
+ return { medusaOptions, variantOptionMap, variantImageMap };
63
+ }
64
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9uLW1hcHBlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy93b3JrZmxvd3Mvb3B0aW9uLW1hcHBlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVFBLGdEQXVFQztBQXZFRCxTQUFnQixrQkFBa0IsQ0FDaEMsT0FBeUIsRUFDekIsUUFBMkIsRUFDM0IsTUFBdUI7SUFFdkIsSUFBSSxDQUFDLE9BQU8sSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3JDLE9BQU8sSUFBSSxDQUFBO0lBQ2IsQ0FBQztJQUVELDhEQUE4RDtJQUM5RCxNQUFNLFdBQVcsR0FBRyxJQUFJLEdBQUcsRUFBc0QsQ0FBQTtJQUNqRixLQUFLLE1BQU0sR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQzFCLEtBQUssTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzdCLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQTtRQUMxRSxDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sZUFBZSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUU1RCxJQUFJLGVBQWUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDakMsT0FBTyxJQUFJLENBQUE7SUFDYixDQUFDO0lBRUQsOEVBQThFO0lBQzlFLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxHQUFHLEVBQWtDLENBQUE7SUFDbEUsS0FBSyxNQUFNLENBQUMsSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUNoQyxNQUFNLFlBQVksR0FBMkIsRUFBRSxDQUFBO1FBQy9DLEtBQUssTUFBTSxLQUFL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
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.submitPrintifyOrderWorkflow = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const printify_1 = require("../modules/printify");
6
+ const submitOrderStep = (0, workflows_sdk_1.createStep)("printify-submit-order-step", async ({ localOrderId, shopId }, { container }) => {
7
+ const service = container.resolve(printify_1.PRINTIFY_MODULE);
8
+ const orders = await service.listPrintifyOrders({ id: localOrderId });
9
+ const localOrder = orders[0];
10
+ if (!localOrder) {
11
+ throw new Error(`PrintifyOrder not found: ${localOrderId}`);
12
+ }
13
+ if (!localOrder.printify_id) {
14
+ throw new Error(`PrintifyOrder ${localOrderId} has no printify_id — cannot submit`);
15
+ }
16
+ const submitted = await service
17
+ .getApiClient()
18
+ .submitOrder(shopId, localOrder.printify_id);
19
+ await service.updatePrintifyOrders({ id: localOrderId }, { status: submitted.status, submitted_at: new Date() });
20
+ return new workflows_sdk_1.StepResponse({
21
+ status: submitted.status,
22
+ printifyOrderId: localOrder.printify_id,
23
+ });
24
+ });
25
+ exports.submitPrintifyOrderWorkflow = (0, workflows_sdk_1.createWorkflow)("submit-printify-order", (input) => {
26
+ const result = submitOrderStep(input);
27
+ return new workflows_sdk_1.WorkflowResponse(result);
28
+ });
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VibWl0LXByaW50aWZ5LW9yZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9zdWJtaXQtcHJpbnRpZnktb3JkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBSzBDO0FBQzFDLGtEQUFxRDtBQWFyRCxNQUFNLGVBQWUsR0FBRyxJQUFBLDBCQUFVLEVBQ2hDLDRCQUE0QixFQUM1QixLQUFLLEVBQUUsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUE0QixFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtJQUMxRSxNQUFNLE9BQU8sR0FBMEIsU0FBUyxDQUFDLE9BQU8sQ0FBQywwQkFBZSxDQUFDLENBQUE7SUFFekUsTUFBTSxNQUFNLEdBQUcsTUFBTSxPQUFPLENBQUMsa0JBQWtCLENBQUMsRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQTtJQUNyRSxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFFNUIsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsNEJBQTRCLFlBQVksRUFBRSxDQUFDLENBQUE7SUFDN0QsQ0FBQztJQUNELElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDNUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQkFBaUIsWUFBWSxxQ0FBcUMsQ0FBQyxDQUFBO0lBQ3JGLENBQUM7SUFFRCxNQUFNLFNBQVMsR0FBRyxNQUFNLE9BQU87U0FDNUIsWUFBWSxFQUFFO1NBQ2QsV0FBVyxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsV0FBcUIsQ0FBQyxDQUFBO0lBRXhELE1BQU0sT0FBTyxDQUFDLG9CQUFvQixDQUNoQyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsRUFDcEIsRUFBRSxNQUFNLEVBQUUsU0FBUyxDQUFDLE1BQU0sRUFBRSxZQUFZLEVBQUUsSUFBSSxJQUFJLEVBQUUsRUFBRSxDQUN2RCxDQUFBO0lBRUQsT0FBTyxJQUFJLDRCQUFZLENBQUM7UUFDdEIsTUFBTSxFQUFFLFNBQVMsQ0FBQyxNQUFNO1FBQ3hCLGVBQWUsRUFBRSxVQUFVLENBQUMsV0FBcUI7S0FDbEQsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUNGLENBQUE7QUFFWSxRQUFBLDJCQUEyQixHQUFHLElBQUEsOEJBQWMsRUFDdkQsdUJBQXVCLEVBQ3ZCLENBQUMsS0FBK0IsRUFBRSxFQUFFO0lBQ2xDLE1BQU0sTUFBTSxHQUFHLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUNyQyxPQUFPLElBQUksZ0NBQWdCLENBQUMsTUFBTSxDQUFDLENBQUE7QUFDckMsQ0FBQyxDQUNGLENBQUEifQ==
@@ -0,0 +1,313 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.syncProductsWorkflow = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
7
+ const printify_1 = require("../modules/printify");
8
+ const option_mapper_1 = require("./option-mapper");
9
+ const currency_converter_1 = require("../utils/currency-converter");
10
+ const build_variant_prices_1 = require("../utils/build-variant-prices");
11
+ const fetchAllProductsStep = (0, workflows_sdk_1.createStep)("printify-fetch-all-products-step", async ({ shopId }, { container }) => {
12
+ const service = container.resolve(printify_1.PRINTIFY_MODULE);
13
+ const client = service.getApiClient();
14
+ const products = [];
15
+ let page = 1;
16
+ let lastPage = 1;
17
+ do {
18
+ const response = await client.getProducts(shopId, page, 50);
19
+ products.push(...response.data);
20
+ lastPage = response.last_page;
21
+ page++;
22
+ } while (page <= lastPage);
23
+ return new workflows_sdk_1.StepResponse(products);
24
+ });
25
+ const upsertProductsStep = (0, workflows_sdk_1.createStep)("printify-upsert-products-step", async ({ products, shopId }, { container }) => {
26
+ const service = container.resolve(printify_1.PRINTIFY_MODULE);
27
+ for (const product of products) {
28
+ const existing = await service.listPrintifyProducts({ printify_id: String(product.id) });
29
+ const printifyPublished = product.visible && !product.is_locked;
30
+ // visibility_override is null until an admin manually sets it;
31
+ // MikroORM returns null (never undefined) for nullable boolean columns
32
+ const shouldUpdateVisibility = existing.length === 0 ||
33
+ existing[0].visibility_override === null;
34
+ const data = {
35
+ printify_id: String(product.id),
36
+ shop_id: shopId,
37
+ title: product.title,
38
+ description: product.description,
39
+ variants: product.variants,
40
+ images: product.images,
41
+ print_areas: product.print_areas,
42
+ printify_data: product,
43
+ ...(shouldUpdateVisibility ? { is_published: printifyPublished } : {}),
44
+ };
45
+ if (existing.length > 0) {
46
+ await service.updatePrintifyProducts({
47
+ selector: { printify_id: String(product.id) },
48
+ data,
49
+ });
50
+ }
51
+ else {
52
+ await service.createPrintifyProducts([data]);
53
+ }
54
+ }
55
+ return new workflows_sdk_1.StepResponse({ synced: products.length });
56
+ });
57
+ function slugify(text) {
58
+ return text
59
+ .toLowerCase()
60
+ .replace(/[^a-z0-9]+/g, "-")
61
+ .replace(/^-|-$/g, "");
62
+ }
63
+ function buildMedusaVariants(enabledVariants, mapped, printifyProductId, currencies, rates, existingVariantIdMap) {
64
+ return enabledVariants.map((v) => ({
65
+ ...(existingVariantIdMap?.get(v.id) ? { id: existingVariantIdMap.get(v.id) } : {}),
66
+ title: v.title,
67
+ sku: v.sku || undefined,
68
+ options: mapped.variantOptionMap.get(v.id) ?? {},
69
+ prices: (0, build_variant_prices_1.buildVariantPrices)(v.price, currencies, rates),
70
+ manage_inventory: false,
71
+ metadata: {
72
+ printify_variant_id: v.id,
73
+ printify_product_id: printifyProductId,
74
+ },
75
+ }));
76
+ }
77
+ async function associateVariantImages(productModuleService, medusaProductId, variantImageMap, logger) {
78
+ const product = await productModuleService.retrieveProduct(medusaProductId, {
79
+ relations: ["images", "variants"],
80
+ });
81
+ logger.info(`[printify] associateVariantImages: product ${medusaProductId} has ${product.images?.length ?? 0} images, ${product.variants?.length ?? 0} variants, variantImageMap has ${variantImageMap.size} entries`);
82
+ const urlToImageId = new Map();
83
+ for (const img of product.images ?? []) {
84
+ urlToImageId.set(img.url, img.id);
85
+ }
86
+ const pairs = [];
87
+ for (const variant of product.variants ?? []) {
88
+ const printifyVarId = variant.metadata?.printify_variant_id;
89
+ if (printifyVarId == null)
90
+ continue;
91
+ // Handle both number and string types from JSON round-trip
92
+ const numericId = typeof printifyVarId === "string" ? parseInt(printifyVarId, 10) : printifyVarId;
93
+ const imageUrls = variantImageMap.get(numericId);
94
+ if (!imageUrls?.length) {
95
+ logger.warn(`[printify] associateVariantImages: no images in variantImageMap for printify variant ${numericId}`);
96
+ continue;
97
+ }
98
+ for (const { url } of imageUrls) {
99
+ const medusaImageId = urlToImageId.get(url);
100
+ if (medusaImageId) {
101
+ pairs.push({ image_id: medusaImageId, variant_id: variant.id });
102
+ }
103
+ else {
104
+ logger.warn(`[printify] associateVariantImages: URL not found in Medusa images: ${url}`);
105
+ }
106
+ }
107
+ }
108
+ if (pairs.length > 0) {
109
+ await productModuleService.addImageToVariant(pairs);
110
+ logger.info(`[printify] Associated ${pairs.length} variant-image pairs for product ${medusaProductId}`);
111
+ }
112
+ else {
113
+ logger.warn(`[printify] associateVariantImages: NO pairs created for product ${medusaProductId}`);
114
+ }
115
+ }
116
+ function extractPrintifyMappings(pp) {
117
+ const printifyData = pp.printify_data;
118
+ const printifyOptions = printifyData?.options ?? [];
119
+ const variants = pp.variants ?? [];
120
+ const printifyImages = pp.images ?? [];
121
+ const enabledVariants = variants.filter((v) => v.is_enabled);
122
+ const mapped = (0, option_mapper_1.mapPrintifyOptions)(printifyOptions, variants, printifyImages);
123
+ return { variants, enabledVariants, printifyImages, mapped };
124
+ }
125
+ const createMedusaProductsStep = (0, workflows_sdk_1.createStep)("printify-create-medusa-products-step", async ({ shopId, _upsertDone }, { container }) => {
126
+ const service = container.resolve(printify_1.PRINTIFY_MODULE);
127
+ const query = container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
128
+ const link = container.resolve(utils_1.ContainerRegistrationKeys.LINK);
129
+ const productModuleService = container.resolve(utils_1.Modules.PRODUCT);
130
+ const logger = container.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
131
+ // Get all published printify products for this shop
132
+ const printifyProducts = await service.listPrintifyProducts({
133
+ shop_id: shopId,
134
+ is_published: true,
135
+ });
136
+ if (printifyProducts.length === 0) {
137
+ return new workflows_sdk_1.StepResponse({ created: 0, updated: 0 });
138
+ }
139
+ // Resolve shipping profile (first available)
140
+ const fulfillmentService = container.resolve(utils_1.Modules.FULFILLMENT);
141
+ const shippingProfiles = await fulfillmentService.listShippingProfiles({});
142
+ if (shippingProfiles.length === 0) {
143
+ logger.warn("[printify] No shipping profiles found — skipping Medusa product creation");
144
+ return new workflows_sdk_1.StepResponse({ created: 0, updated: 0 });
145
+ }
146
+ const shippingProfileId = shippingProfiles[0].id;
147
+ // Resolve sales channel: shop setting → store default → skip
148
+ const shops = await service.listPrintifyShops({ printify_id: shopId });
149
+ let salesChannelId = shops[0]?.sales_channel_id ?? null;
150
+ if (!salesChannelId) {
151
+ const storeService = container.resolve(utils_1.Modules.STORE);
152
+ const stores = await storeService.listStores({});
153
+ salesChannelId = stores[0]?.default_sales_channel_id ?? null;
154
+ if (salesChannelId) {
155
+ logger.info(`[printify] Using store default sales channel: ${salesChannelId}`);
156
+ }
157
+ }
158
+ if (!salesChannelId) {
159
+ logger.error(`[printify] PRODUCTS WILL NOT APPEAR ON STOREFRONT — no sales channel configured. ` +
160
+ `Set printify_shop.sales_channel_id via PATCH /admin/printify/shops/${shopId}, ` +
161
+ `or set a default_sales_channel_id on the store. ` +
162
+ `(${printifyProducts.length} published products waiting to sync)`);
163
+ return new workflows_sdk_1.StepResponse({ created: 0, updated: 0 });
164
+ }
165
+ // Fetch all unique currencies from active regions
166
+ const regionModule = container.resolve(utils_1.Modules.REGION);
167
+ const regions = await regionModule.listRegions({});
168
+ const currencies = [...new Set(regions.map((r) => r.currency_code))];
169
+ // Always include usd (Printify's base currency)
170
+ if (!currencies.includes("usd")) {
171
+ currencies.unshift("usd");
172
+ }
173
+ // Fetch exchange rates once for all products in this sync
174
+ let rates = {};
175
+ let ratesFetched = false;
176
+ if (currencies.length === 1 && currencies[0] === "usd") {
177
+ logger.info("[printify] Only USD region active — skipping exchange rate fetch");
178
+ ratesFetched = true;
179
+ }
180
+ else {
181
+ try {
182
+ rates = await (0, currency_converter_1.fetchExchangeRates)(currencies);
183
+ ratesFetched = true;
184
+ logger.info(`[printify] Fetched exchange rates for ${currencies.join(", ")}`);
185
+ }
186
+ catch (err) {
187
+ logger.warn(`[printify] Could not fetch exchange rates — falling back to USD only: ${err instanceof Error ? err.message : err}`);
188
+ }
189
+ }
190
+ // If rates fetch failed, only create USD prices (for new products)
191
+ const activeCurrencies = ratesFetched ? currencies : ["usd"];
192
+ // When we need multi-currency pricing but rates are unavailable,
193
+ // avoid overwriting existing multi-currency prices on product updates
194
+ const hasCompletePricing = ratesFetched || currencies.length <= 1;
195
+ let created = 0;
196
+ let updated = 0;
197
+ for (const pp of printifyProducts) {
198
+ // Check if a linked Medusa product already exists
199
+ let medusaProductId = null;
200
+ try {
201
+ const { data } = await query.graph({
202
+ entity: "printify_product",
203
+ fields: ["product.id"],
204
+ filters: { id: pp.id },
205
+ });
206
+ if (data.length > 0 && data[0].product?.id) {
207
+ medusaProductId = data[0].product.id;
208
+ }
209
+ }
210
+ catch {
211
+ // Link query failed — treat as no link
212
+ }
213
+ const { enabledVariants, printifyImages, mapped } = extractPrintifyMappings(pp);
214
+ if (enabledVariants.length === 0) {
215
+ logger.warn(`[printify] Product "${pp.title}" has no enabled variants — skipping`);
216
+ continue;
217
+ }
218
+ if (!mapped) {
219
+ logger.error(`[printify] Product "${pp.title}" (${pp.printify_id}) has no options in printify_data — skipping`);
220
+ continue;
221
+ }
222
+ if (!medusaProductId) {
223
+ // Create a new Medusa product
224
+ try {
225
+ const { result } = await (0, core_flows_1.createProductsWorkflow)(container).run({
226
+ input: {
227
+ products: [
228
+ {
229
+ title: pp.title,
230
+ description: pp.description || undefined,
231
+ handle: slugify(pp.title),
232
+ status: "published",
233
+ images: printifyImages.map((img) => ({ url: img.src })),
234
+ options: mapped.medusaOptions,
235
+ variants: buildMedusaVariants(enabledVariants, mapped, pp.printify_id, activeCurrencies, rates),
236
+ sales_channels: [{ id: salesChannelId }],
237
+ shipping_profile_id: shippingProfileId,
238
+ },
239
+ ],
240
+ },
241
+ });
242
+ const newProduct = result[0];
243
+ // Create module link: printify_product ↔ product
244
+ await link.create({
245
+ [printify_1.PRINTIFY_MODULE]: { printify_product_id: pp.id },
246
+ [utils_1.Modules.PRODUCT]: { product_id: newProduct.id },
247
+ });
248
+ await associateVariantImages(productModuleService, newProduct.id, mapped.variantImageMap, logger);
249
+ created++;
250
+ logger.info(`[printify] Created Medusa product "${pp.title}" (${newProduct.id})`);
251
+ }
252
+ catch (err) {
253
+ logger.error(`[printify] Failed to create Medusa product for "${pp.title}": ${err instanceof Error ? err.message : JSON.stringify(err)}`);
254
+ }
255
+ }
256
+ else {
257
+ // Update existing linked Medusa product
258
+ try {
259
+ const targetStatus = pp.is_published ? "published" : "draft";
260
+ // Build a map of existing Medusa variant IDs keyed by Printify variant ID
261
+ // so updateProducts can match existing variants instead of trying to create duplicates
262
+ const existingProduct = await productModuleService.retrieveProduct(medusaProductId, {
263
+ relations: ["variants"],
264
+ });
265
+ const existingVariantIdMap = new Map();
266
+ for (const variant of existingProduct.variants ?? []) {
267
+ const printifyVarId = variant.metadata?.printify_variant_id;
268
+ if (printifyVarId != null) {
269
+ const numericId = typeof printifyVarId === "string" ? parseInt(printifyVarId, 10) : printifyVarId;
270
+ existingVariantIdMap.set(numericId, variant.id);
271
+ }
272
+ }
273
+ if (!hasCompletePricing) {
274
+ logger.warn(`[printify] Skipping variant/price update for "${pp.title}" — exchange rates unavailable, preserving existing multi-currency prices`);
275
+ }
276
+ await (0, core_flows_1.updateProductsWorkflow)(container).run({
277
+ input: {
278
+ products: [
279
+ {
280
+ id: medusaProductId,
281
+ title: pp.title,
282
+ description: pp.description || undefined,
283
+ status: targetStatus,
284
+ images: printifyImages.map((img) => ({ url: img.src })),
285
+ sales_channels: [{ id: salesChannelId }],
286
+ ...(hasCompletePricing
287
+ ? {
288
+ options: mapped.medusaOptions,
289
+ variants: buildMedusaVariants(enabledVariants, mapped, pp.printify_id, activeCurrencies, rates, existingVariantIdMap),
290
+ }
291
+ : {}),
292
+ },
293
+ ],
294
+ },
295
+ });
296
+ await associateVariantImages(productModuleService, medusaProductId, mapped.variantImageMap, logger);
297
+ updated++;
298
+ logger.info(`[printify] Updated Medusa product "${pp.title}" (${medusaProductId})`);
299
+ }
300
+ catch (err) {
301
+ logger.error(`[printify] Failed to update Medusa product ${medusaProductId}: ${err instanceof Error ? err.message : JSON.stringify(err)}`);
302
+ }
303
+ }
304
+ }
305
+ return new workflows_sdk_1.StepResponse({ created, updated });
306
+ });
307
+ exports.syncProductsWorkflow = (0, workflows_sdk_1.createWorkflow)("sync-printify-products", (input) => {
308
+ const products = fetchAllProductsStep(input);
309
+ const upsertResult = upsertProductsStep({ products, shopId: input.shopId });
310
+ const medusaResult = createMedusaProductsStep({ shopId: input.shopId, _upsertDone: upsertResult });
311
+ return new workflows_sdk_1.WorkflowResponse(medusaResult);
312
+ });
313
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1wcm9kdWN0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy93b3JrZmxvd3Mvc3luYy1wcm9kdWN0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxRUFLMEM7QUFDMUMscURBQThFO0FBQzlFLDREQUE0RjtBQUU1RixrREFBcUQ7QUFHckQsbURBQW9EO0FBQ3BELG9FQUFvRjtBQUNwRix3RUFBa0U7QUFNbEUsTUFBTSxvQkFBb0IsR0FBRyxJQUFBLDBCQUFVLEVBQ3JDLGtDQUFrQyxFQUNsQyxLQUFLLEVBQUUsRUFBRSxNQUFNLEVBQXFCLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQ3JELE1BQU0sT0FBTyxHQUEwQixTQUFTLENBQUMsT0FBTyxDQUFDLDBCQUFlLENBQUMsQ0FBQTtJQUN6RSxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsWUFBWSxFQUFFLENBQUE7SUFFckMsTUFBTSxRQUFRLEdBQXNCLEVBQUUsQ0FBQTtJQUN0QyxJQUFJLElBQUksR0FBRyxDQUFDLENBQUE7SUFDWixJQUFJLFFBQVEsR0FBRyxDQUFDLENBQUE7SUFFaEIsR0FBRyxDQUFDO1FBQ0YsTUFBTSxRQUFRLEdBQUcsTUFBTSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFDM0QsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUMvQixRQUFRLEdBQUcsUUFBUSxDQUFDLFNBQVMsQ0FBQTtRQUM3QixJQUFJLEVBQUUsQ0FBQTtJQUNSLENBQUMsUUFBUSxJQUFJLElBQUksUUFBUSxFQUFDO0lBRTFCLE9BQU8sSUFBSSw0QkFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0FBQ25DLENBQUMsQ0FDRixDQUFBO0FBRUQsTUFBTSxrQkFBa0IsR0FBRyxJQUFBLDBCQUFVLEVBQ25DLCtCQUErQixFQUMvQixLQUFLLEVB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