@yoryoboy/bi-mcp 1.19.0 → 1.20.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 (53) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/mcp-use.json +6 -3
  3. package/dist/scripts/profile-mercadolibre-billing.js +634 -0
  4. package/dist/scripts/profile-mercadolibre-billing.js.map +7 -0
  5. package/dist/src/config/__tests__/tiendanube-profile-store.test.js +50 -0
  6. package/dist/src/config/__tests__/tiendanube-profile-store.test.js.map +7 -0
  7. package/dist/src/config/tiendanube-profile-store.js +31 -0
  8. package/dist/src/config/tiendanube-profile-store.js.map +7 -0
  9. package/dist/src/google-ads/report-utils.js +78 -0
  10. package/dist/src/google-ads/report-utils.js.map +7 -0
  11. package/dist/src/search-console/search-console-utils.js +275 -0
  12. package/dist/src/search-console/search-console-utils.js.map +7 -0
  13. package/dist/src/services/mercadolibre/__tests__/mercadolibre-sales-report-ventas.test.js +358 -0
  14. package/dist/src/services/mercadolibre/__tests__/mercadolibre-sales-report-ventas.test.js.map +7 -0
  15. package/dist/src/services/mercadolibre/__tests__/mercadolibre-sales-report.test.js +96 -0
  16. package/dist/src/services/mercadolibre/__tests__/mercadolibre-sales-report.test.js.map +7 -0
  17. package/dist/src/services/mercadolibre/mercadolibre-claim-return-lookup.js +15 -0
  18. package/dist/src/services/mercadolibre/mercadolibre-claim-return-lookup.js.map +7 -0
  19. package/dist/src/services/mercadolibre/mercadolibre-observability.js +12 -0
  20. package/dist/src/services/mercadolibre/mercadolibre-observability.js.map +7 -0
  21. package/dist/src/services/mercadolibre/mercadolibre-sale-reference.js +7 -0
  22. package/dist/src/services/mercadolibre/mercadolibre-sale-reference.js.map +7 -0
  23. package/dist/src/services/mercadolibre/mercadolibre-sales-report.js +553 -0
  24. package/dist/src/services/mercadolibre/mercadolibre-sales-report.js.map +7 -0
  25. package/dist/src/services/vtex/__tests__/vtex-catalog-write-batch.test.js +165 -0
  26. package/dist/src/services/vtex/__tests__/vtex-catalog-write-batch.test.js.map +7 -0
  27. package/dist/src/tools/config/__tests__/list-profiles.test.js +144 -1
  28. package/dist/src/tools/config/__tests__/list-profiles.test.js.map +2 -2
  29. package/dist/src/tools/config/list-profiles.js +50 -6
  30. package/dist/src/tools/config/list-profiles.js.map +2 -2
  31. package/dist/src/tools/mercadolibre/__tests__/get-sales-report-foundation.test.js +417 -0
  32. package/dist/src/tools/mercadolibre/__tests__/get-sales-report-foundation.test.js.map +7 -0
  33. package/dist/src/tools/mercadolibre/get-sales-report.js +474 -0
  34. package/dist/src/tools/mercadolibre/get-sales-report.js.map +7 -0
  35. package/dist/src/tools/vtex/__tests__/catalog-admin-batch.test.js +233 -0
  36. package/dist/src/tools/vtex/__tests__/catalog-admin-batch.test.js.map +7 -0
  37. package/dist/src/tools/vtex/catalog-admin-batch.js +298 -0
  38. package/dist/src/tools/vtex/catalog-admin-batch.js.map +7 -0
  39. package/dist/tests/meli/meli-sales-report-buyers-mcp-e2e.test.js +137 -0
  40. package/dist/tests/meli/meli-sales-report-buyers-mcp-e2e.test.js.map +7 -0
  41. package/dist/tests/meli/meli-sales-report-mcp-e2e-server.js +24 -0
  42. package/dist/tests/meli/meli-sales-report-mcp-e2e-server.js.map +7 -0
  43. package/dist/tests/meli/meli-sales-report-mcp-e2e.test.js +207 -0
  44. package/dist/tests/meli/meli-sales-report-mcp-e2e.test.js.map +7 -0
  45. package/dist/tests/meli/meli-sales-report-public-mcp-e2e-server.js +10 -0
  46. package/dist/tests/meli/meli-sales-report-public-mcp-e2e-server.js.map +7 -0
  47. package/dist/tests/meli/meli-sales-report-public-registration.test.js +98 -0
  48. package/dist/tests/meli/meli-sales-report-public-registration.test.js.map +7 -0
  49. package/dist/tests/smoke/process-harness.js +89 -0
  50. package/dist/tests/smoke/process-harness.js.map +7 -0
  51. package/dist/tests/smoke/process-harness.test.js +39 -0
  52. package/dist/tests/smoke/process-harness.test.js.map +7 -0
  53. package/package.json +1 -1
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/services/mercadolibre/mercadolibre-sales-report.ts"],
4
+ "sourcesContent": ["import {\n normalizeMercadoLibrePaging,\n runMercadoLibreBatch,\n type MercadoLibreDocumentsBatchResult,\n} from \"./mercadolibre-api.js\";\nimport {\n searchMercadoLibreOrders,\n searchMercadoLibreOrdersBatch,\n getMercadoLibreOrderDetailsBatch,\n getMercadoLibreOrderShipments,\n} from \"./mercadolibre-orders.js\";\nimport { getMercadoLibrePackBatch } from \"./mercadolibre-packs.js\";\nimport type { BillingProvisionByOrderResult } from \"./mercadolibre-billing.js\";\nimport {\n getMercadoLibreSaleBillingInfo,\n type MercadoLibreOrderBillingInfoResult,\n type MercadoLibreSaleBillingInfoResult,\n} from \"./mercadolibre-order-billing-info.js\";\nimport {\n type SalesReportOperation,\n type SalesReportOrder,\n type SalesReportScopedIncident,\n} from \"../../tools/mercadolibre/get-sales-report.js\";\n\nexport interface MercadoLibreOrderUniverse {\n orders: Record<string, unknown>[];\n paging: { total: number; limit: number; offset: number };\n failedPages: string[];\n}\n\nexport interface MercadoLibreExplicitOrderSelection {\n orders: Record<string, unknown>[];\n requestedIds: string[];\n unavailableRequestedIds: string[];\n incidents: SalesReportScopedIncident[];\n}\n\nconst VENTAS_CODES = new Set([\"CVFV\", \"CVFN\", \"CVFF\", \"CDSD\"]);\nconst record = (value: unknown): Record<string, unknown> =>\n value !== null && typeof value === \"object\" && !Array.isArray(value) ? value as Record<string, unknown> : {};\nconst records = (value: unknown): Record<string, unknown>[] => Array.isArray(value)\n ? value.filter((item) => item && typeof item === \"object\" && !Array.isArray(item)) as Record<string, unknown>[]\n : value !== null && typeof value === \"object\" ? [value as Record<string, unknown>] : [];\nconst numberValue = (value: unknown) => typeof value === \"number\" && Number.isFinite(value) ? value : null;\nconst text = (value: unknown) => typeof value === \"string\" && value.trim() ? value.trim() : null;\n\nfunction orderSellerId(order: Record<string, unknown>): string | null {\n const seller = record(order.seller);\n const id = seller.id;\n return typeof id === \"string\" && id.trim()\n ? id.trim()\n : typeof id === \"number\" && Number.isFinite(id)\n ? String(id)\n : null;\n}\n\nfunction packMemberIds(pack: Record<string, unknown>): string[] {\n const members = Array.isArray(pack.orders) ? pack.orders : [];\n return [...new Set(members.map((member) => {\n const value = record(member).id ?? member;\n return typeof value === \"string\" && value.trim()\n ? value.trim()\n : typeof value === \"number\" && Number.isFinite(value)\n ? String(value)\n : null;\n }).filter((id): id is string => id !== null))];\n}\n\nexport async function selectMercadoLibreOrdersById(\n profileId: string,\n sellerId: string,\n orderIds: string[],\n): Promise<MercadoLibreExplicitOrderSelection> {\n const direct = await getMercadoLibreOrderDetailsBatch(profileId, orderIds, { maxConcurrency: 10 });\n const ownedDirect = direct.successful.filter(({ document }) => orderSellerId(document) === sellerId);\n const ownedDirectIds = new Set(ownedDirect.map(({ id }) => id));\n const directFailures = new Map(direct.failed.map((failure) => [failure.id, failure]));\n const unavailableRequestedIds = orderIds.filter((id) => !ownedDirectIds.has(id));\n const packIds = [...new Set(ownedDirect.map(({ document }) => text(document.pack_id)).filter((id): id is string => id !== null))];\n const packs = packIds.length > 0\n ? await getMercadoLibrePackBatch(profileId, packIds, { maxConcurrency: 10 })\n : { successful: [], failed: [] };\n const selected = new Map(ownedDirect.map(({ id, document }) => [id, document]));\n const missingMemberIds = [...new Set(packs.successful.flatMap(({ document }) => packMemberIds(document)))]\n .filter((id) => !selected.has(id));\n const expanded = missingMemberIds.length > 0\n ? await getMercadoLibreOrderDetailsBatch(profileId, missingMemberIds, { maxConcurrency: 10 })\n : { successful: [], failed: [] };\n for (const { id, document } of expanded.successful) {\n if (orderSellerId(document) === sellerId) selected.set(id, document);\n }\n\n return {\n orders: [...selected.values()],\n requestedIds: orderIds,\n unavailableRequestedIds,\n incidents: [\n ...unavailableRequestedIds.map((id) => {\n const failure = directFailures.get(id);\n return {\n fuente: \"orders\" as const,\n alcance: \"order_selection\",\n identificadores: [id],\n mensaje: failure ? \"The requested order could not be retrieved.\" : \"The requested order is not available for this seller profile.\",\n reintentable: failure?.retryable ?? false,\n estado_http: failure?.statusCode ?? null,\n };\n }),\n ...packs.failed.map((failure) => ({\n fuente: \"packs\" as const,\n alcance: \"pack_expansion\",\n identificadores: [failure.id],\n mensaje: \"The complete pack could not be retrieved.\",\n reintentable: failure.retryable,\n estado_http: failure.statusCode ?? null,\n })),\n ...expanded.failed.map(() => ({\n fuente: \"orders\" as const,\n alcance: \"pack_expansion\",\n identificadores: [],\n mensaje: \"A pack member could not be retrieved and was excluded.\",\n reintentable: true,\n })),\n ...expanded.successful.filter(({ document }) => orderSellerId(document) !== sellerId).map(() => ({\n fuente: \"orders\" as const,\n alcance: \"pack_expansion\",\n identificadores: [],\n mensaje: \"A pack member is not available for this seller profile and was excluded.\",\n reintentable: false,\n })),\n ],\n };\n}\nconst SALES_REPORT_BUYER_EVIDENCE = Symbol(\"sales-report-buyer-evidence\");\ntype SalesReportBuyerEvidence = { sellerId: string | null; nickname: string | null };\ntype SalesReportOrderInternal = SalesReportOrder & { [SALES_REPORT_BUYER_EVIDENCE]?: SalesReportBuyerEvidence };\n\nconst emptyReturns = () => ({ unidades: null, forma_de_entrega: null, fecha_en_camino: null, fecha_entregado: null, transportista: null, numero_de_seguimiento: null, url_de_seguimiento: null, revisado_por_mercado_libre: null, fecha_de_revision: null, dinero_a_favor: null, resultado: null, destino: null, motivo_del_resultado: null });\nconst emptyClaims = () => ({ unidades: null, reclamo_abierto: null, reclamo_cerrado: null, con_mediacion: null });\ntype PostPurchaseEvidence = { returns?: unknown; claims?: unknown; returnFailure?: unknown; claimFailure?: unknown };\n\nfunction memberContext(result: any, reference: string, orderId: string, key: \"return_context\" | \"claim_context\"): any {\n const entry = result?.results?.find((item: any) => item.sale_reference === reference);\n if (!entry) return undefined;\n const member = entry.members?.find((item: any) => item.order_id === orderId || record(item[key]).order_id === orderId);\n const context = member?.[key] ?? (entry.members ? undefined : entry[key]);\n const issues = member?.issues ?? entry.issues ?? [];\n return context || issues.length ? { ...record(context), order_id: record(context).order_id ?? member?.order_id ?? entry.order_id ?? orderId, __memberIssues: issues } : undefined;\n}\n\nexport function buildSalesReportPostPurchaseIncident(source: \"returns\" | \"claims\", error: unknown): SalesReportScopedIncident {\n const rawStatus = record(error).status;\n const status = typeof rawStatus === \"number\" ? rawStatus : null;\n const retryable = status === null ? true : status === 408 || status === 429 || (status >= 500 && status <= 599);\n return { fuente: source, alcance: \"source\", identificadores: [], mensaje: `Mercado Libre ${source} evidence was unavailable${status === null ? \" (transport)\" : ` (HTTP ${status})`}.`, reintentable: retryable, estado_http: status };\n}\n\nexport function enrichSalesReportDevolucionesReclamos(operations: SalesReportOperation[], evidence: PostPurchaseEvidence) {\n const incidents: SalesReportScopedIncident[] = [];\n const returnFields = [\"unidades\", \"revisado_por_mercado_libre\", \"fecha_de_revision\", \"resultado\", \"destino\", \"motivo_del_resultado\"] as const;\n const claimFields = [\"unidades\", \"reclamo_abierto\", \"reclamo_cerrado\", \"con_mediacion\"] as const;\n const coverage = Object.fromEntries([...returnFields.map((field) => [`devoluciones.${field}`, { solicitados: 0, obtenidos: 0 }]), ...claimFields.map((field) => [`reclamos.${field}`, { solicitados: 0, obtenidos: 0 }])]);\n let returnContexts = 0;\n let claimContexts = 0;\n const mapped = operations.map((operation) => ({ ...operation, ordenes: operation.ordenes.map((order, memberIndex) => {\n const returns = memberContext(evidence.returns, operation.pack_id ?? order.order_id, order.order_id, \"return_context\");\n const claims = memberContext(evidence.claims, operation.pack_id ?? order.order_id, order.order_id, \"claim_context\");\n if (returns) returnContexts++;\n if (claims) claimContexts++;\n const returnRows = returns?.return_status === \"with_return\" && returns.return ? [returns] : [];\n const review = record(returnRows[0]?.review);\n const destination = record(review.product_destination);\n const reason = record(review.reason);\n const devoluciones = { ...emptyReturns(), ...(returnRows.length ? { unidades: numberValue(record(returnRows[0].return).quantities), revisado_por_mercado_libre: typeof review.status === \"string\" ? review.status === \"success\" : null, fecha_de_revision: text(review.date_created), resultado: text(review.status), destino: text(destination.code ?? destination.meaning), motivo_del_resultado: text(reason.code ?? reason.description) } : {}) };\n const claimRows: Record<string, unknown>[] = Array.isArray(claims?.claims) ? claims.claims.map(record) : [];\n const quantities = claimRows.map((claim: Record<string, unknown>) => numberValue(claim.claimed_quantity)).filter((value: number | null): value is number => value !== null);\n const reclamos = { ...emptyClaims(), ...(claimRows.length ? { unidades: quantities.length ? quantities.reduce((sum: number, value: number) => sum + value, 0) : null, reclamo_abierto: claimRows.some((claim: Record<string, unknown>) => claim.status === \"opened\"), reclamo_cerrado: claimRows.some((claim: Record<string, unknown>) => claim.status === \"closed\"), con_mediacion: claimRows.some((claim: Record<string, unknown>) => claim.type === \"mediations\") } : {}) };\n for (const field of returnFields) { const key = `devoluciones.${field}`; coverage[key].solicitados++; if (devoluciones[field] !== null) coverage[key].obtenidos++; }\n for (const field of claimFields) { const key = `reclamos.${field}`; coverage[key].solicitados++; if (reclamos[field] !== null) coverage[key].obtenidos++; }\n if (returns?.__memberIssues?.length || returns?.issues?.length) incidents.push({ fuente: \"returns\", alcance: \"order\", identificadores: [order.order_id], mensaje: \"Return evidence is partial; member-level reconciliation issues were preserved.\", reintentable: true });\n if (claims?.__memberIssues?.length || claims?.issues?.length) incidents.push({ fuente: \"claims\", alcance: \"order\", identificadores: [order.order_id], mensaje: \"Claim evidence is partial; member-level reconciliation issues were preserved.\", reintentable: true });\n return { ...order, devoluciones, reclamos };\n }) as [SalesReportOrder, ...SalesReportOrder[]] }));\n if (evidence.returnFailure) incidents.push(buildSalesReportPostPurchaseIncident(\"returns\", evidence.returnFailure));\n if (evidence.claimFailure) incidents.push(buildSalesReportPostPurchaseIncident(\"claims\", evidence.claimFailure));\n return { operations: mapped, incidents, coverage, returnContexts, claimContexts };\n}\n\nexport interface SalesReportShipmentEvidence {\n order_id: string;\n shipment: unknown;\n}\n\nexport const SALES_REPORT_ENVIOS_FIELDS = [\n \"forma_de_entrega\", \"fecha_en_camino\", \"fecha_entregado\", \"transportista\",\n \"numero_de_seguimiento\", \"url_de_seguimiento\",\n] as const;\n\nexport interface SalesReportFiscalEvidence {\n orderId: string;\n result?: MercadoLibreOrderBillingInfoResult;\n unavailableReason?: string;\n statusCode?: number;\n retryable?: boolean;\n}\n\nexport interface SalesReportFiscalRequestFailure {\n orderId: string;\n statusCode?: number;\n retryable: boolean;\n reason?: string;\n}\n\nexport const SALES_REPORT_FACTURACION_FIELDS = [\n \"factura_adjunta\", \"datos_personales_o_de_empresa\", \"tipo_y_numero_de_documento\",\n \"direccion\", \"condicion_fiscal_iva\", \"numero_iibb\",\n] as const;\n\nfunction fiscalResultEntries(orderId: string, result: MercadoLibreSaleBillingInfoResult): SalesReportFiscalEvidence[] {\n if (result.resolutionKind === \"order\") return [{ orderId, result: result.result }];\n return result.members.flatMap((member) => {\n if (!(\"orderId\" in member)) return [];\n return [member.accessible\n ? { orderId: member.orderId, result: member.result }\n : { orderId: member.orderId, unavailableReason: member.failureReason, statusCode: member.statusCode, retryable: member.retryable }];\n });\n}\n\nexport function buildSalesReportFiscalIncident(\n orderId: string,\n statusCode: number | undefined,\n retryable: boolean,\n reason = \"Fiscal billing-info request failed.\",\n): SalesReportScopedIncident {\n const statusText = statusCode === undefined ? \"transport\" : `HTTP ${statusCode}`;\n const statusRetryable = statusCode !== undefined && [401, 403, 404].includes(statusCode) ? false : retryable;\n return {\n fuente: \"billing_info\",\n alcance: \"order\",\n identificadores: [orderId],\n mensaje: `${reason} (${statusText}).`,\n reintentable: statusRetryable,\n estado_http: statusCode ?? null,\n };\n}\n\nexport async function fetchMercadoLibreFiscalEvidence(profileId: string, orderIds: string[]) {\n const batch = await runMercadoLibreBatch(\n [...new Set(orderIds)],\n (orderId) => getMercadoLibreSaleBillingInfo(profileId, orderId),\n );\n return {\n successful: batch.successful.flatMap(({ id, document }) => fiscalResultEntries(id, document)),\n failed: batch.failed.map((failure) => ({ orderId: failure.id, statusCode: failure.statusCode, retryable: failure.retryable, reason: \"Fiscal billing-info request failed.\" })),\n };\n}\n\nfunction fiscalField(value: unknown): string | null {\n if (typeof value === \"string\" && value.trim()) return value.trim();\n if (typeof value === \"number\" && Number.isFinite(value)) return String(value);\n return null;\n}\n\nfunction fiscalAddress(value: unknown): string | null {\n const address = record(value);\n const street = [fiscalField(address.street_name), fiscalField(address.street_number)].filter((part): part is string => part !== null).join(\" \");\n const parts = [street || null, fiscalField(address.city_name), fiscalField(address.state), fiscalField(address.zip_code), fiscalField(address.country_id)]\n .filter((part): part is string => part !== null);\n return parts.length ? parts.join(\", \") : null;\n}\n\nexport function enrichSalesReportFacturacion(\n operations: SalesReportOperation[],\n evidence: SalesReportFiscalEvidence[],\n failedOrderIds: SalesReportFiscalRequestFailure[] = [],\n) {\n const byOrder = new Map(evidence.map((entry) => [entry.orderId, entry]));\n const incidents: SalesReportScopedIncident[] = failedOrderIds.map(({ orderId, statusCode, retryable, reason }) =>\n buildSalesReportFiscalIncident(orderId, statusCode, retryable, reason));\n const fieldCoverage = Object.fromEntries(SALES_REPORT_FACTURACION_FIELDS.map((field) => [field, { solicitados: 0, obtenidos: 0 }])) as Record<typeof SALES_REPORT_FACTURACION_FIELDS[number], { solicitados: number; obtenidos: number }>;\n const mapped = operations.map((operation) => ({\n ...operation,\n ordenes: operation.ordenes.map((order) => {\n const entry = byOrder.get(order.order_id);\n const billing = entry?.result?.available ? record(record(entry.result.billingInfo).buyer).billing_info : null;\n const info = record(billing);\n const identification = record(info.identification);\n const taxpayer = record(record(info.taxes).taxpayer_type);\n const fields: Record<typeof SALES_REPORT_FACTURACION_FIELDS[number], string | null> = {\n factura_adjunta: null,\n datos_personales_o_de_empresa: [fiscalField(info.name), fiscalField(info.last_name)].filter((part): part is string => part !== null).join(\" \") || null,\n tipo_y_numero_de_documento: [fiscalField(identification.type), fiscalField(identification.number)].filter((part): part is string => part !== null).join(\" \") || null,\n direccion: fiscalAddress(info.address),\n condicion_fiscal_iva: fiscalField(taxpayer.description),\n numero_iibb: null,\n };\n for (const field of SALES_REPORT_FACTURACION_FIELDS) {\n fieldCoverage[field].solicitados++;\n if (fields[field] !== null) fieldCoverage[field].obtenidos++;\n if (fields[field] === null && field !== \"factura_adjunta\" && field !== \"numero_iibb\") {\n incidents.push({ ...buildSalesReportFiscalIncident(order.order_id, entry?.statusCode, entry?.retryable ?? false, entry?.unavailableReason ?? \"Fiscal field evidence was unavailable for this order.\"), alcance: `order.${field}` });\n }\n }\n return { ...order, facturacion_al_comprador: fields };\n }) as [SalesReportOrder, ...SalesReportOrder[]],\n }));\n return { operations: mapped, incidents, fieldCoverage };\n}\n\nexport function enrichSalesReportCompradores(\n operations: SalesReportOperation[],\n expectedSellerId: string,\n) {\n const incidents: SalesReportScopedIncident[] = [];\n const empty = { comprador: null, negocio: null, dni: null, domicilio: null, ciudad: null, estado: null, codigo_postal: null, pais: null };\n const mapped = operations.map((operation) => ({\n ...operation,\n ordenes: operation.ordenes.map((order) => {\n const evidence = (order as SalesReportOrderInternal)[SALES_REPORT_BUYER_EVIDENCE];\n if (!evidence || evidence.sellerId !== expectedSellerId) {\n incidents.push({ fuente: \"orders\", alcance: \"order\", identificadores: [order.order_id], mensaje: \"Buyer disclosure was blocked because seller ownership could not be verified.\", reintentable: false });\n return { ...order, compradores: empty };\n }\n if (!evidence.nickname) {\n incidents.push({ fuente: \"orders\", alcance: \"order\", identificadores: [order.order_id], mensaje: \"Buyer nickname was missing or malformed; buyer disclosure was blocked.\", reintentable: false });\n return { ...order, compradores: empty };\n }\n return { ...order, compradores: { ...empty, comprador: evidence.nickname } };\n }) as [SalesReportOrder, ...SalesReportOrder[]],\n }));\n return { operations: mapped, incidents };\n}\n\nexport function enrichSalesReportEnvios(\n operations: SalesReportOperation[],\n evidence: SalesReportShipmentEvidence[],\n) {\n const byOrder = new Map(evidence.map((entry) => [entry.order_id, entry.shipment]));\n const incidents: SalesReportScopedIncident[] = [];\n const fieldCoverage = Object.fromEntries(SALES_REPORT_ENVIOS_FIELDS.map((field) => [field, { solicitados: operations.reduce((total, operation) => total + operation.ordenes.length, 0), obtenidos: 0 }])) as Record<typeof SALES_REPORT_ENVIOS_FIELDS[number], { solicitados: number; obtenidos: number }>;\n const fields = (orderId: string) => {\n const shipment = record(byOrder.get(orderId));\n const shipmentOrderId = text(shipment.order_id);\n if (!Object.keys(shipment).length || shipmentOrderId !== orderId) {\n incidents.push({ fuente: \"shipments\", alcance: \"order\", identificadores: [orderId], mensaje: shipmentOrderId ? \"Shipment evidence belongs to a different order.\" : \"No shipment evidence was returned for this order.\", reintentable: false });\n return { forma_de_entrega: null, fecha_en_camino: null, fecha_entregado: null, transportista: null, numero_de_seguimiento: null, url_de_seguimiento: null };\n }\n const statusHistory = record(shipment.status_history);\n const shippingOption = record(shipment.shipping_option);\n const carrier = record(shipment.carrier_info);\n const mapped = {\n forma_de_entrega: text(shippingOption.name) ?? text(shipment.mode),\n fecha_en_camino: text(statusHistory.date_shipped),\n fecha_entregado: text(statusHistory.date_delivered),\n transportista: text(carrier.name),\n numero_de_seguimiento: text(shipment.tracking_number),\n url_de_seguimiento: text(carrier.url),\n };\n for (const field of SALES_REPORT_ENVIOS_FIELDS) {\n if (mapped[field] !== null) fieldCoverage[field].obtenidos++;\n else incidents.push({ fuente: \"shipments\", alcance: `order.${field}`, identificadores: [orderId], mensaje: \"Shipment field evidence was unavailable for this order.\", reintentable: false });\n }\n return mapped;\n };\n return {\n operations: operations.map((operation) => ({\n ...operation,\n ordenes: operation.ordenes.map((order) => ({ ...order, envios: fields(order.order_id) })) as [SalesReportOrder, ...SalesReportOrder[]],\n })),\n incidents,\n fieldCoverage,\n };\n}\n\nexport async function fetchMercadoLibreShipmentEvidence(profileId: string, orderIds: string[]) {\n return runMercadoLibreBatch(\n [...new Set(orderIds)],\n (orderId) => getMercadoLibreOrderShipments(profileId, orderId),\n );\n}\n\nfunction formatVariation(item: Record<string, unknown>): string | null {\n const attributes = records(item.variation_attributes);\n const values = attributes.map((attribute) => {\n const name = text(attribute.name);\n const value = text(attribute.value_name);\n return name && value ? `${name}: ${value}` : null;\n }).filter((value): value is string => value !== null);\n return values.length ? values.join(\", \") : null;\n}\n\nexport function enrichSalesReportVentas(\n operations: SalesReportOperation[],\n billing: BillingProvisionByOrderResult,\n) {\n const byOrder = new Map<string, Record<string, unknown>[]>();\n const unknownConcepts = new Set<string>();\n const currencies = new Set<string>();\n for (const row of billing.results) {\n const fallback = String(row.order_id ?? \"\");\n for (const detail of records(row.details)) {\n const charge = record(detail.charge_info);\n const code = String(charge.detail_sub_type ?? detail.detail_sub_type ?? \"\");\n const currency = String(record(detail.currency_info).currency_id ?? row.currency_id ?? \"\");\n if (currency) currencies.add(currency);\n if (!VENTAS_CODES.has(code)) { if (code) unknownConcepts.add(code); continue; }\n const amount = numberValue(charge.detail_amount ?? detail.detail_amount);\n if (currency !== \"ARS\" || amount === null || String(charge.detail_type ?? detail.detail_type ?? \"\") !== \"CHARGE\") continue;\n const sales = records(detail.sales_info ?? detail.details_sales);\n const orderIds = sales.map((sale) => String(sale.order_id ?? \"\")).filter(Boolean);\n for (const orderId of (orderIds.length ? orderIds : [fallback])) {\n const list = byOrder.get(orderId) ?? [];\n list.push({ code, amount, date: String(charge.creation_date_time ?? detail.creation_date_time ?? \"\") });\n byOrder.set(orderId, list);\n }\n }\n }\n const result = operations.map((operation) => {\n const entries = operation.ordenes.flatMap((order) => byOrder.get(order.order_id) ?? []);\n const sum = (code: string) => entries.filter((entry) => entry.code === code).reduce((total, entry) => total - Number(entry.amount), 0);\n const value = (code: string) => entries.some((entry) => entry.code === code) ? sum(code) : null;\n const periods = [...new Set(entries.map((entry) => String(entry.date).slice(0, 7)).filter((period) => /^\\d{4}-\\d{2}$/.test(period)))].sort();\n const known = entries.reduce((total, entry) => total - Number(entry.amount), 0);\n return { ...operation, ventas: { ...operation.ventas, cargo_por_venta: value(\"CVFV\"), costo_fijo: value(\"CVFF\"), costo_por_ofrecer_cuotas: value(\"CVFN\"), anulaciones_y_reembolsos_ars: value(\"CDSD\"), total_ars: entries.length ? known : null, cargo_por_diferencias_en_medidas_y_peso_del_paquete: null, periodos_de_facturacion: periods } };\n });\n return {\n operations: result,\n unknownConcepts: [...unknownConcepts].sort(),\n currencies: [...currencies].sort(),\n incidents: billing.order_ids_not_found.map((orderId) => ({ fuente: \"billing\" as const, alcance: \"order\", identificadores: [orderId], mensaje: \"Billing-by-order returned no result for this order.\", reintentable: false })),\n failures: billing.failures,\n };\n}\n\nexport function buildOrderUniversePagePlan(\n paging: { total: number; limit: number; offset: number },\n target: number,\n maxPages = 20,\n): number[] {\n const effectiveLimit = paging.limit > 0 ? paging.limit : target;\n const end = Math.min(\n paging.total,\n paging.offset + Math.max(0, target) + effectiveLimit,\n );\n const offsets: number[] = [];\n for (let offset = paging.offset + effectiveLimit; offset < end && offsets.length < maxPages; offset += effectiveLimit) {\n offsets.push(offset);\n }\n return offsets;\n}\n\nfunction value(record: Record<string, unknown>, key: string): unknown {\n return Object.prototype.hasOwnProperty.call(record, key) ? record[key] ?? null : null;\n}\n\nexport function normalizeMercadoLibreOrder(input: Record<string, unknown>): SalesReportOrder {\n const id = String(input.id ?? \"\");\n const date = String(input.date_created ?? input.date_closed ?? \"\");\n const items = Array.isArray(input.order_items) ? input.order_items : [];\n const firstItem = (items[0] ?? {}) as Record<string, unknown>;\n const item = (firstItem.item ?? {}) as Record<string, unknown>;\n const total = typeof input.total_amount === \"number\" ? input.total_amount : null;\n\n const normalized: SalesReportOrderInternal = {\n order_id: id,\n ventas: {\n fecha_de_venta: date,\n estado: (value(input, \"status\") as string | null),\n descripcion_del_estado: (value(input, \"status_detail\") as string | null),\n pertenece_a_un_kit: null,\n unidades: typeof firstItem.quantity === \"number\" ? firstItem.quantity : null,\n ingresos_por_productos_ars: null,\n orden_de_compra: null,\n },\n publicidad: { venta_por_publicidad: null },\n publicaciones: {\n sku: (value(item, \"seller_sku\") as string | null),\n numero_de_publicacion: (value(item, \"id\") as string | null),\n canal_de_venta: null,\n titulo_de_la_publicacion: (value(item, \"title\") as string | null),\n variante: formatVariation(item),\n precio_unitario_de_venta_de_la_publicacion_ars:\n typeof firstItem.unit_price === \"number\" ? firstItem.unit_price : null,\n tiene_cuotas_agregadas: null,\n },\n facturacion_al_comprador: {\n factura_adjunta: null,\n datos_personales_o_de_empresa: null,\n tipo_y_numero_de_documento: null,\n direccion: null,\n condicion_fiscal_iva: null,\n numero_iibb: null,\n },\n compradores: {\n comprador: null, negocio: null, dni: null, domicilio: null,\n ciudad: null, estado: null, codigo_postal: null, pais: null,\n },\n envios: {\n forma_de_entrega: null, fecha_en_camino: null, fecha_entregado: null,\n transportista: null, numero_de_seguimiento: null, url_de_seguimiento: null,\n },\n devoluciones: {\n unidades: null, forma_de_entrega: null, fecha_en_camino: null,\n fecha_entregado: null, transportista: null, numero_de_seguimiento: null,\n url_de_seguimiento: null, revisado_por_mercado_libre: null,\n fecha_de_revision: null, dinero_a_favor: null, resultado: null,\n destino: null, motivo_del_resultado: null,\n },\n reclamos: { unidades: null, reclamo_abierto: null, reclamo_cerrado: null, con_mediacion: null },\n };\n const seller = record(input.seller);\n const buyer = record(input.buyer);\n normalized[SALES_REPORT_BUYER_EVIDENCE] = { sellerId: text(seller.id), nickname: text(buyer.nickname) };\n return normalized;\n}\n\nexport function enrichSalesReportPublicaciones(\n operations: SalesReportOperation[],\n billing: BillingProvisionByOrderResult,\n) {\n const byOrder = new Map<string, { channel: string | null; item: Record<string, unknown> }[]>();\n for (const row of billing.results) {\n const fallback = String(row.order_id ?? \"\");\n for (const detail of records(row.details)) {\n const sales = records(detail.sales_info ?? detail.details_sales);\n const items = records(detail.items_info ?? detail.details_items);\n const orderIds = sales.map((sale) => text(sale.order_id)).filter((id): id is string => id !== null);\n for (const orderId of (orderIds.length ? orderIds : [fallback]).filter(Boolean)) {\n const channel = text(sales.find((sale) => text(sale.order_id) === orderId)?.sales_channel);\n const list = byOrder.get(orderId) ?? [];\n list.push(...items.map((item) => ({ channel, item })));\n byOrder.set(orderId, list);\n }\n }\n }\n const result = operations.map((operation) => ({\n ...operation,\n ordenes: operation.ordenes.map((order) => {\n const item = record((order as unknown as { publicaciones?: unknown }).publicaciones);\n const orderEvidence = byOrder.get(order.order_id) ?? [];\n const evidence = orderEvidence.find(({ item: candidate }) => text(candidate.item_id) === item.numero_de_publicacion) ?? orderEvidence[0];\n const billingItem = evidence?.item;\n const hasFees = billingItem && Object.prototype.hasOwnProperty.call(billingItem, \"fees_added_in_publication\");\n const feeValue = hasFees && (billingItem.fees_added_in_publication === \"Si\" || billingItem.fees_added_in_publication === \"No\")\n ? billingItem.fees_added_in_publication === \"Si\" : null;\n const kitId = billingItem && Object.prototype.hasOwnProperty.call(billingItem, \"item_kit_id\") ? text(billingItem.item_kit_id) : null;\n return {\n ...order,\n ventas: { ...order.ventas, pertenece_a_un_kit: billingItem && Object.prototype.hasOwnProperty.call(billingItem, \"item_kit_id\") ? kitId !== null : null },\n publicaciones: {\n ...order.publicaciones,\n canal_de_venta: evidence?.channel ?? null,\n titulo_de_la_publicacion: order.publicaciones.titulo_de_la_publicacion ?? text(billingItem?.item_title),\n precio_unitario_de_venta_de_la_publicacion_ars: order.publicaciones.precio_unitario_de_venta_de_la_publicacion_ars ?? numberValue(billingItem?.item_price),\n tiene_cuotas_agregadas: feeValue,\n },\n };\n }) as [SalesReportOrder, ...SalesReportOrder[]],\n }));\n return { operations: result, incidents: billing.order_ids_not_found.map((orderId) => ({ fuente: \"billing\" as const, alcance: \"order\", identificadores: [orderId], mensaje: \"Billing-by-order returned no result for this order.\", reintentable: false })) };\n}\n\nfunction operation(packId: string | null, orders: [SalesReportOrder, ...SalesReportOrder[]]): SalesReportOperation {\n return {\n pack_id: packId,\n ventas: {\n paquete_de_varios_productos: packId !== null,\n cargo_por_venta: null, costo_fijo: null, costo_por_ofrecer_cuotas: null,\n ingresos_por_envio_ars: null, costos_de_envio_ars: null,\n costo_de_envio_por_cambio_de_producto: null,\n costo_de_envio_basado_en_medidas_y_peso_declarados: null,\n cargo_por_diferencias_en_medidas_y_peso_del_paquete: null, impuestos: null,\n descuentos_y_bonificaciones: null, anulaciones_y_reembolsos_ars: null,\n total_ars: null, periodos_de_facturacion: [],\n },\n ordenes: orders,\n };\n}\n\nexport function groupMercadoLibreOrders(records: Record<string, unknown>[]): SalesReportOperation[] {\n const groups = new Map<string, SalesReportOrder[]>();\n for (const record of records) {\n const normalized = normalizeMercadoLibreOrder(record);\n const packId = record.pack_id == null ? null : String(record.pack_id);\n const key = packId ?? `order:${normalized.order_id}`;\n const group = groups.get(key) ?? [];\n group.push(normalized);\n groups.set(key, group);\n }\n return [...groups.entries()].map(([key, orders]) =>\n operation(\n key.startsWith(\"order:\") ? null : key,\n orders as [SalesReportOrder, ...SalesReportOrder[]],\n )\n ).sort((left, right) => {\n const leftDate = left.ordenes.reduce((latest, order) => order.ventas.fecha_de_venta > latest ? order.ventas.fecha_de_venta : latest, left.ordenes[0].ventas.fecha_de_venta);\n const rightDate = right.ordenes.reduce((latest, order) => order.ventas.fecha_de_venta > latest ? order.ventas.fecha_de_venta : latest, right.ordenes[0].ventas.fecha_de_venta);\n return Date.parse(rightDate) - Date.parse(leftDate) ||\n (right.pack_id ?? right.ordenes[0].order_id).localeCompare(left.pack_id ?? left.ordenes[0].order_id);\n });\n}\n\nexport async function fetchMercadoLibreOrderUniverse(\n profileId: string,\n from: string,\n to: string,\n target: number,\n): Promise<MercadoLibreOrderUniverse> {\n const seed = await searchMercadoLibreOrders(profileId, { seller: \"\", from, to, sort: \"date_desc\", limit: 50, offset: 0 });\n const paging = normalizeMercadoLibrePaging(seed.paging as Record<string, unknown>);\n const seedOrders = Array.isArray(seed.results) ? seed.results : Array.isArray(seed.orders) ? seed.orders : [];\n const offsets = buildOrderUniversePagePlan(paging, target);\n const remaining: MercadoLibreDocumentsBatchResult<Record<string, unknown>> = offsets.length\n ? await searchMercadoLibreOrdersBatch(profileId, { seller: \"\", from, to, sort: \"date_desc\", limit: paging.limit }, offsets)\n : { successful: [], failed: [] };\n return {\n orders: [...seedOrders, ...remaining.successful.flatMap((page) => {\n const data = page.document;\n return Array.isArray(data.results) ? data.results : Array.isArray(data.orders) ? data.orders : [];\n })] as Record<string, unknown>[],\n paging,\n failedPages: remaining.failed.map((failure) => failure.id),\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["value", "operation", "record", "records"]
7
+ }
@@ -0,0 +1,165 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ const getMock = vi.fn();
3
+ const postMock = vi.fn();
4
+ const putMock = vi.fn();
5
+ const deleteMock = vi.fn();
6
+ vi.mock("../vtex-api.js", () => ({
7
+ getVtexApiClients: vi.fn(async () => ({
8
+ vtexApi: {
9
+ get: getMock,
10
+ post: postMock,
11
+ put: putMock,
12
+ delete: deleteMock
13
+ }
14
+ }))
15
+ }));
16
+ const catalogWrite = await import("../vtex-catalog-write.js");
17
+ describe("VTEX catalog write batch planning and execution", () => {
18
+ beforeEach(() => {
19
+ vi.clearAllMocks();
20
+ });
21
+ it("builds batch preflight summaries and destructive warnings from mixed operations", async () => {
22
+ const operations = [
23
+ {
24
+ type: "update_product_basic_fields",
25
+ productId: "product-1",
26
+ updates: { name: "New Product Name" }
27
+ },
28
+ {
29
+ type: "update_sku_basic_fields",
30
+ skuId: "sku-1",
31
+ updates: { measurementUnit: "un", unitMultiplier: 1 }
32
+ },
33
+ {
34
+ type: "replace_sku_eans",
35
+ skuId: "sku-2",
36
+ eans: ["111", "222"]
37
+ }
38
+ ];
39
+ await expect(catalogWrite.planCatalogBatch("profile-1", operations)).resolves.toEqual({
40
+ preflight: {
41
+ entities: 3,
42
+ entityTypes: ["product", "sku"],
43
+ destructive: true,
44
+ hasDeleteOrReplaceAll: true,
45
+ dependencyFailureCount: 0,
46
+ multiEntityCriticalReassignment: false
47
+ },
48
+ warnings: ["destructive_operation_detected"],
49
+ impactedEntityTypes: ["product", "sku"],
50
+ before: [
51
+ {
52
+ operation_index: 0,
53
+ operation_type: "update_product_basic_fields",
54
+ resource_id: "product-1"
55
+ },
56
+ {
57
+ operation_index: 1,
58
+ operation_type: "update_sku_basic_fields",
59
+ resource_id: "sku-1"
60
+ },
61
+ {
62
+ operation_index: 2,
63
+ operation_type: "replace_sku_eans",
64
+ resource_id: "sku-2"
65
+ }
66
+ ],
67
+ after: [
68
+ {
69
+ operation_index: 0,
70
+ operation_type: "update_product_basic_fields",
71
+ resource_id: "product-1",
72
+ updates: { name: "New Product Name" }
73
+ },
74
+ {
75
+ operation_index: 1,
76
+ operation_type: "update_sku_basic_fields",
77
+ resource_id: "sku-1",
78
+ updates: { measurementUnit: "un", unitMultiplier: 1 }
79
+ },
80
+ {
81
+ operation_index: 2,
82
+ operation_type: "replace_sku_eans",
83
+ resource_id: "sku-2",
84
+ planned_eans: ["111", "222"]
85
+ }
86
+ ]
87
+ });
88
+ });
89
+ it("aggregates batch successes and failures without aborting later operations", async () => {
90
+ const operations = [
91
+ {
92
+ type: "update_product_basic_fields",
93
+ productId: "product-1",
94
+ updates: { name: "Updated Product" }
95
+ },
96
+ {
97
+ type: "update_sku_basic_fields",
98
+ skuId: "sku-1",
99
+ updates: { name: "Updated SKU" }
100
+ },
101
+ {
102
+ type: "replace_sku_eans",
103
+ skuId: "sku-2",
104
+ eans: ["111", "222", "111"]
105
+ }
106
+ ];
107
+ getMock.mockResolvedValueOnce({
108
+ data: {
109
+ Name: "Original Product",
110
+ CategoryId: 10,
111
+ BrandId: 20
112
+ }
113
+ });
114
+ putMock.mockResolvedValueOnce({
115
+ data: {
116
+ Id: "product-1",
117
+ Name: "Updated Product"
118
+ }
119
+ });
120
+ getMock.mockRejectedValueOnce(new Error("sku fetch failed"));
121
+ deleteMock.mockResolvedValueOnce({});
122
+ postMock.mockResolvedValue({});
123
+ getMock.mockResolvedValueOnce({ data: ["111", "222"] });
124
+ await expect(catalogWrite.executeCatalogBatch("profile-1", operations)).resolves.toEqual({
125
+ successful: [
126
+ {
127
+ operation_index: 0,
128
+ operation_type: "update_product_basic_fields",
129
+ resource_id: "product-1",
130
+ result: {
131
+ Id: "product-1",
132
+ Name: "Updated Product"
133
+ }
134
+ },
135
+ {
136
+ operation_index: 2,
137
+ operation_type: "replace_sku_eans",
138
+ resource_id: "sku-2",
139
+ result: {
140
+ eans: ["111", "222"]
141
+ }
142
+ }
143
+ ],
144
+ failed: [
145
+ {
146
+ operation_index: 1,
147
+ operation_type: "update_sku_basic_fields",
148
+ resource_id: "sku-1",
149
+ message: "sku fetch failed"
150
+ }
151
+ ]
152
+ });
153
+ expect(deleteMock).toHaveBeenCalledWith("/api/catalog/pvt/stockkeepingunit/sku-2/ean");
154
+ expect(postMock).toHaveBeenNthCalledWith(
155
+ 1,
156
+ "/api/catalog/pvt/stockkeepingunit/sku-2/ean/111"
157
+ );
158
+ expect(postMock).toHaveBeenNthCalledWith(
159
+ 2,
160
+ "/api/catalog/pvt/stockkeepingunit/sku-2/ean/222"
161
+ );
162
+ expect(postMock).toHaveBeenCalledTimes(2);
163
+ });
164
+ });
165
+ //# sourceMappingURL=vtex-catalog-write-batch.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/services/vtex/__tests__/vtex-catalog-write-batch.test.ts"],
4
+ "sourcesContent": ["import { beforeEach, describe, expect, it, vi } from \"vitest\";\n\nconst getMock = vi.fn();\nconst postMock = vi.fn();\nconst putMock = vi.fn();\nconst deleteMock = vi.fn();\n\nvi.mock(\"../vtex-api.js\", () => ({\n getVtexApiClients: vi.fn(async () => ({\n vtexApi: {\n get: getMock,\n post: postMock,\n put: putMock,\n delete: deleteMock,\n },\n })),\n}));\n\nconst catalogWrite = await import(\"../vtex-catalog-write.js\");\n\ndescribe(\"VTEX catalog write batch planning and execution\", () => {\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n it(\"builds batch preflight summaries and destructive warnings from mixed operations\", async () => {\n const operations = [\n {\n type: \"update_product_basic_fields\" as const,\n productId: \"product-1\",\n updates: { name: \"New Product Name\" },\n },\n {\n type: \"update_sku_basic_fields\" as const,\n skuId: \"sku-1\",\n updates: { measurementUnit: \"un\", unitMultiplier: 1 },\n },\n {\n type: \"replace_sku_eans\" as const,\n skuId: \"sku-2\",\n eans: [\"111\", \"222\"],\n },\n ];\n\n await expect(catalogWrite.planCatalogBatch(\"profile-1\", operations)).resolves.toEqual({\n preflight: {\n entities: 3,\n entityTypes: [\"product\", \"sku\"],\n destructive: true,\n hasDeleteOrReplaceAll: true,\n dependencyFailureCount: 0,\n multiEntityCriticalReassignment: false,\n },\n warnings: [\"destructive_operation_detected\"],\n impactedEntityTypes: [\"product\", \"sku\"],\n before: [\n {\n operation_index: 0,\n operation_type: \"update_product_basic_fields\",\n resource_id: \"product-1\",\n },\n {\n operation_index: 1,\n operation_type: \"update_sku_basic_fields\",\n resource_id: \"sku-1\",\n },\n {\n operation_index: 2,\n operation_type: \"replace_sku_eans\",\n resource_id: \"sku-2\",\n },\n ],\n after: [\n {\n operation_index: 0,\n operation_type: \"update_product_basic_fields\",\n resource_id: \"product-1\",\n updates: { name: \"New Product Name\" },\n },\n {\n operation_index: 1,\n operation_type: \"update_sku_basic_fields\",\n resource_id: \"sku-1\",\n updates: { measurementUnit: \"un\", unitMultiplier: 1 },\n },\n {\n operation_index: 2,\n operation_type: \"replace_sku_eans\",\n resource_id: \"sku-2\",\n planned_eans: [\"111\", \"222\"],\n },\n ],\n });\n });\n\n it(\"aggregates batch successes and failures without aborting later operations\", async () => {\n const operations = [\n {\n type: \"update_product_basic_fields\" as const,\n productId: \"product-1\",\n updates: { name: \"Updated Product\" },\n },\n {\n type: \"update_sku_basic_fields\" as const,\n skuId: \"sku-1\",\n updates: { name: \"Updated SKU\" },\n },\n {\n type: \"replace_sku_eans\" as const,\n skuId: \"sku-2\",\n eans: [\"111\", \"222\", \"111\"],\n },\n ];\n\n getMock.mockResolvedValueOnce({\n data: {\n Name: \"Original Product\",\n CategoryId: 10,\n BrandId: 20,\n },\n });\n putMock.mockResolvedValueOnce({\n data: {\n Id: \"product-1\",\n Name: \"Updated Product\",\n },\n });\n getMock.mockRejectedValueOnce(new Error(\"sku fetch failed\"));\n deleteMock.mockResolvedValueOnce({});\n postMock.mockResolvedValue({});\n getMock.mockResolvedValueOnce({ data: [\"111\", \"222\"] });\n\n await expect(catalogWrite.executeCatalogBatch(\"profile-1\", operations)).resolves.toEqual({\n successful: [\n {\n operation_index: 0,\n operation_type: \"update_product_basic_fields\",\n resource_id: \"product-1\",\n result: {\n Id: \"product-1\",\n Name: \"Updated Product\",\n },\n },\n {\n operation_index: 2,\n operation_type: \"replace_sku_eans\",\n resource_id: \"sku-2\",\n result: {\n eans: [\"111\", \"222\"],\n },\n },\n ],\n failed: [\n {\n operation_index: 1,\n operation_type: \"update_sku_basic_fields\",\n resource_id: \"sku-1\",\n message: \"sku fetch failed\",\n },\n ],\n });\n\n expect(deleteMock).toHaveBeenCalledWith(\"/api/catalog/pvt/stockkeepingunit/sku-2/ean\");\n expect(postMock).toHaveBeenNthCalledWith(\n 1,\n \"/api/catalog/pvt/stockkeepingunit/sku-2/ean/111\"\n );\n expect(postMock).toHaveBeenNthCalledWith(\n 2,\n \"/api/catalog/pvt/stockkeepingunit/sku-2/ean/222\"\n );\n expect(postMock).toHaveBeenCalledTimes(2);\n });\n});\n"],
5
+ "mappings": "AAAA,SAAS,YAAY,UAAU,QAAQ,IAAI,UAAU;AAErD,MAAM,UAAU,GAAG,GAAG;AACtB,MAAM,WAAW,GAAG,GAAG;AACvB,MAAM,UAAU,GAAG,GAAG;AACtB,MAAM,aAAa,GAAG,GAAG;AAEzB,GAAG,KAAK,kBAAkB,OAAO;AAAA,EAC/B,mBAAmB,GAAG,GAAG,aAAa;AAAA,IACpC,SAAS;AAAA,MACP,KAAK;AAAA,MACL,MAAM;AAAA,MACN,KAAK;AAAA,MACL,QAAQ;AAAA,IACV;AAAA,EACF,EAAE;AACJ,EAAE;AAEF,MAAM,eAAe,MAAM,OAAO,0BAA0B;AAE5D,SAAS,mDAAmD,MAAM;AAChE,aAAW,MAAM;AACf,OAAG,cAAc;AAAA,EACnB,CAAC;AAED,KAAG,mFAAmF,YAAY;AAChG,UAAM,aAAa;AAAA,MACjB;AAAA,QACE,MAAM;AAAA,QACN,WAAW;AAAA,QACX,SAAS,EAAE,MAAM,mBAAmB;AAAA,MACtC;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS,EAAE,iBAAiB,MAAM,gBAAgB,EAAE;AAAA,MACtD;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM,CAAC,OAAO,KAAK;AAAA,MACrB;AAAA,IACF;AAEA,UAAM,OAAO,aAAa,iBAAiB,aAAa,UAAU,CAAC,EAAE,SAAS,QAAQ;AAAA,MACpF,WAAW;AAAA,QACT,UAAU;AAAA,QACV,aAAa,CAAC,WAAW,KAAK;AAAA,QAC9B,aAAa;AAAA,QACb,uBAAuB;AAAA,QACvB,wBAAwB;AAAA,QACxB,iCAAiC;AAAA,MACnC;AAAA,MACA,UAAU,CAAC,gCAAgC;AAAA,MAC3C,qBAAqB,CAAC,WAAW,KAAK;AAAA,MACtC,QAAQ;AAAA,QACN;AAAA,UACE,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,QACf;AAAA,QACA;AAAA,UACE,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,QACf;AAAA,QACA;AAAA,UACE,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL;AAAA,UACE,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,UACb,SAAS,EAAE,MAAM,mBAAmB;AAAA,QACtC;AAAA,QACA;AAAA,UACE,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,UACb,SAAS,EAAE,iBAAiB,MAAM,gBAAgB,EAAE;AAAA,QACtD;AAAA,QACA;AAAA,UACE,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,UACb,cAAc,CAAC,OAAO,KAAK;AAAA,QAC7B;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,KAAG,6EAA6E,YAAY;AAC1F,UAAM,aAAa;AAAA,MACjB;AAAA,QACE,MAAM;AAAA,QACN,WAAW;AAAA,QACX,SAAS,EAAE,MAAM,kBAAkB;AAAA,MACrC;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS,EAAE,MAAM,cAAc;AAAA,MACjC;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM,CAAC,OAAO,OAAO,KAAK;AAAA,MAC5B;AAAA,IACF;AAEA,YAAQ,sBAAsB;AAAA,MAC5B,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AACD,YAAQ,sBAAsB;AAAA,MAC5B,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AACD,YAAQ,sBAAsB,IAAI,MAAM,kBAAkB,CAAC;AAC3D,eAAW,sBAAsB,CAAC,CAAC;AACnC,aAAS,kBAAkB,CAAC,CAAC;AAC7B,YAAQ,sBAAsB,EAAE,MAAM,CAAC,OAAO,KAAK,EAAE,CAAC;AAEtD,UAAM,OAAO,aAAa,oBAAoB,aAAa,UAAU,CAAC,EAAE,SAAS,QAAQ;AAAA,MACvF,YAAY;AAAA,QACV;AAAA,UACE,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,UACb,QAAQ;AAAA,YACN,IAAI;AAAA,YACJ,MAAM;AAAA,UACR;AAAA,QACF;AAAA,QACA;AAAA,UACE,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,UACb,QAAQ;AAAA,YACN,MAAM,CAAC,OAAO,KAAK;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN;AAAA,UACE,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,UACb,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO,UAAU,EAAE,qBAAqB,6CAA6C;AACrF,WAAO,QAAQ,EAAE;AAAA,MACf;AAAA,MACA;AAAA,IACF;AACA,WAAO,QAAQ,EAAE;AAAA,MACf;AAAA,MACA;AAAA,IACF;AACA,WAAO,QAAQ,EAAE,sBAAsB,CAAC;AAAA,EAC1C,CAAC;AACH,CAAC;",
6
+ "names": []
7
+ }
@@ -8,6 +8,7 @@ const getGoogleOAuthConnectionMock = vi.fn();
8
8
  const listVtexConnectionsMock = vi.fn();
9
9
  const listMercadolibreConnectionsMock = vi.fn();
10
10
  const listMetaMappingsMock = vi.fn();
11
+ const listTiendanubeConnectionsMock = vi.fn();
11
12
  vi.mock("mcp-use/server", () => ({ object: objectMock, error: errorMock }));
12
13
  vi.mock("../../../config/profile-store.js", () => ({
13
14
  listProfiles: listProfilesMock
@@ -26,6 +27,9 @@ vi.mock("../../../config/mercadolibre-profile-store.js", () => ({
26
27
  vi.mock("../../../config/meta-store.js", () => ({
27
28
  listProfileMetaMappings: listMetaMappingsMock
28
29
  }));
30
+ vi.mock("../../../config/tiendanube-profile-store.js", () => ({
31
+ listTiendanubeConnections: listTiendanubeConnectionsMock
32
+ }));
29
33
  const { listProfilesHandler } = await import("../list-profiles.js");
30
34
  const requiredScopes = [
31
35
  "tagmanager.manage.accounts",
@@ -72,6 +76,7 @@ describe("config_list_profiles GTM readiness", () => {
72
76
  listVtexConnectionsMock.mockResolvedValue([]);
73
77
  listMercadolibreConnectionsMock.mockResolvedValue([]);
74
78
  listMetaMappingsMock.mockResolvedValue([]);
79
+ listTiendanubeConnectionsMock.mockResolvedValue([]);
75
80
  });
76
81
  it("adds active GTM readiness without leaking mapped resource identifiers", async () => {
77
82
  const response = await listProfilesHandler();
@@ -106,7 +111,22 @@ describe("config_list_profiles GTM readiness", () => {
106
111
  status: "not_configured",
107
112
  raw_status: null
108
113
  },
109
- meta: { configured: false, status: "not_configured", raw_status: null }
114
+ meta: { configured: false, status: "not_configured", raw_status: null },
115
+ tiendanube: {
116
+ available: true,
117
+ external_mcp: true,
118
+ configured: false,
119
+ status: "not_configured",
120
+ raw_status: null,
121
+ validation_status: "not_configured",
122
+ last_validated_at: null,
123
+ store_id: null,
124
+ capabilities: {
125
+ connection_reporting: true,
126
+ operational_tools: "external_mcp",
127
+ provider_surface: "provisional"
128
+ }
129
+ }
110
130
  }
111
131
  });
112
132
  expect(
@@ -150,5 +170,128 @@ describe("config_list_profiles GTM readiness", () => {
150
170
  raw_status: oauthConnection ? "active" : null
151
171
  });
152
172
  });
173
+ it("reports a profile-scoped active Tiendanube connection without secret fields", async () => {
174
+ listTiendanubeConnectionsMock.mockResolvedValue([
175
+ {
176
+ profileId: "profile-1",
177
+ storeId: "store-42",
178
+ status: "active",
179
+ lastValidatedAt: /* @__PURE__ */ new Date("2026-01-03T00:00:00.000Z")
180
+ }
181
+ ]);
182
+ const response = await listProfilesHandler();
183
+ const profile = response.value.profiles[0];
184
+ expect(profile.services).toMatchObject({
185
+ tiendanube: {
186
+ available: true,
187
+ external_mcp: true,
188
+ configured: true,
189
+ status: "active",
190
+ raw_status: "active",
191
+ validation_status: "validated",
192
+ last_validated_at: "2026-01-03T00:00:00.000Z",
193
+ store_id: "store-42",
194
+ capabilities: {
195
+ connection_reporting: true,
196
+ operational_tools: "external_mcp",
197
+ provider_surface: "provisional"
198
+ }
199
+ }
200
+ });
201
+ expect(JSON.stringify(profile)).not.toContain("encrypted");
202
+ expect(JSON.stringify(profile)).not.toContain("last_error");
203
+ });
204
+ it.each([
205
+ ["disabled", null, "not_validated"],
206
+ ["expired", /* @__PURE__ */ new Date("2026-01-03T00:00:00.000Z"), "failed"],
207
+ ["pending", null, "pending"],
208
+ ["error", /* @__PURE__ */ new Date("2026-01-03T00:00:00.000Z"), "failed"]
209
+ ])(
210
+ "preserves Tiendanube status %s and reports validation state",
211
+ async (status, lastValidatedAt, validationStatus) => {
212
+ listTiendanubeConnectionsMock.mockResolvedValue([
213
+ {
214
+ profileId: "profile-1",
215
+ storeId: "store-42",
216
+ status,
217
+ lastValidatedAt
218
+ }
219
+ ]);
220
+ await expect(getTiendanubeService()).resolves.toMatchObject({
221
+ configured: true,
222
+ status,
223
+ raw_status: status,
224
+ validation_status: validationStatus,
225
+ last_validated_at: lastValidatedAt?.toISOString() ?? null,
226
+ store_id: "store-42"
227
+ });
228
+ }
229
+ );
230
+ it("keeps Tiendanube readiness isolated by profile", async () => {
231
+ listProfilesMock.mockResolvedValue([
232
+ {
233
+ id: "profile-1",
234
+ name: "Alpha",
235
+ isActive: true,
236
+ createdAt: /* @__PURE__ */ new Date("2026-01-01T00:00:00.000Z"),
237
+ updatedAt: /* @__PURE__ */ new Date("2026-01-02T00:00:00.000Z")
238
+ },
239
+ {
240
+ id: "profile-2",
241
+ name: "Beta",
242
+ isActive: true,
243
+ createdAt: /* @__PURE__ */ new Date("2026-01-01T00:00:00.000Z"),
244
+ updatedAt: /* @__PURE__ */ new Date("2026-01-02T00:00:00.000Z")
245
+ }
246
+ ]);
247
+ listTiendanubeConnectionsMock.mockResolvedValue([
248
+ {
249
+ profileId: "profile-2",
250
+ storeId: "store-2",
251
+ status: "active",
252
+ lastValidatedAt: null
253
+ }
254
+ ]);
255
+ const response = await listProfilesHandler();
256
+ const profiles = response.value.profiles;
257
+ expect(profiles[0].services.tiendanube).toMatchObject({
258
+ configured: false,
259
+ status: "not_configured",
260
+ store_id: null
261
+ });
262
+ expect(profiles[1].services.tiendanube).toMatchObject({
263
+ configured: true,
264
+ status: "active",
265
+ store_id: "store-2"
266
+ });
267
+ });
268
+ it("omits an unsafe public store identifier", async () => {
269
+ listTiendanubeConnectionsMock.mockResolvedValue([
270
+ {
271
+ profileId: "profile-1",
272
+ storeId: " store-42\nprivate-value ",
273
+ status: "active",
274
+ lastValidatedAt: null
275
+ }
276
+ ]);
277
+ await expect(getTiendanubeService()).resolves.toMatchObject({
278
+ configured: true,
279
+ status: "active",
280
+ store_id: null
281
+ });
282
+ });
283
+ it("returns a safe error response when a connection read fails", async () => {
284
+ listTiendanubeConnectionsMock.mockRejectedValue(
285
+ new Error("unexpected database failure")
286
+ );
287
+ await expect(listProfilesHandler()).resolves.toEqual({
288
+ kind: "error",
289
+ message: "Failed to list profiles"
290
+ });
291
+ });
153
292
  });
293
+ async function getTiendanubeService() {
294
+ const response = await listProfilesHandler();
295
+ return response.value.profiles[0].services.tiendanube;
296
+ }
154
297
  //# sourceMappingURL=list-profiles.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/tools/config/__tests__/list-profiles.test.ts"],
4
- "sourcesContent": ["import { beforeEach, describe, expect, it, vi } from \"vitest\";\n\nconst objectMock = vi.fn((value) => ({ kind: \"object\", value }));\nconst errorMock = vi.fn((message) => ({ kind: \"error\", message }));\nconst listProfilesMock = vi.fn();\nconst listGoogleMappingsMock = vi.fn();\nconst listGtmSummariesMock = vi.fn();\nconst getGoogleOAuthConnectionMock = vi.fn();\nconst listVtexConnectionsMock = vi.fn();\nconst listMercadolibreConnectionsMock = vi.fn();\nconst listMetaMappingsMock = vi.fn();\n\nvi.mock(\"mcp-use/server\", () => ({ object: objectMock, error: errorMock }));\nvi.mock(\"../../../config/profile-store.js\", () => ({\n listProfiles: listProfilesMock,\n}));\nvi.mock(\"../../../config/google-store.js\", () => ({\n listProfileGoogleServiceMappings: listGoogleMappingsMock,\n listActiveProfileGtmMappingSummaries: listGtmSummariesMock,\n getGoogleOAuthConnection: getGoogleOAuthConnectionMock,\n}));\nvi.mock(\"../../../config/vtex-profile-store.js\", () => ({\n listVtexConnections: listVtexConnectionsMock,\n}));\nvi.mock(\"../../../config/mercadolibre-profile-store.js\", () => ({\n listMercadoLibreConnections: listMercadolibreConnectionsMock,\n}));\nvi.mock(\"../../../config/meta-store.js\", () => ({\n listProfileMetaMappings: listMetaMappingsMock,\n}));\n\nconst { listProfilesHandler } = await import(\"../list-profiles.js\");\nconst requiredScopes = [\n \"tagmanager.manage.accounts\",\n \"tagmanager.edit.containers\",\n \"tagmanager.delete.containers\",\n \"tagmanager.edit.containerversions\",\n \"tagmanager.manage.users\",\n \"tagmanager.publish\",\n \"tagmanager.readonly\",\n].map((scope) => `https://www.googleapis.com/auth/${scope}`);\n\nfunction connection(overrides: Record<string, unknown> = {}) {\n return {\n id: \"global\",\n encryptedRefreshToken: \"encrypted-token\",\n scopes: requiredScopes,\n status: \"active\",\n googleAccountEmail: null,\n lastValidatedAt: null,\n lastError: null,\n ...overrides,\n };\n}\n\nasync function getGtmService() {\n const response = await listProfilesHandler();\n return (\n response as unknown as {\n value: { profiles: Array<{ services: { google: { gtm: unknown } } }> };\n }\n ).value.profiles[0].services.google.gtm;\n}\n\ndescribe(\"config_list_profiles GTM readiness\", () => {\n beforeEach(() => {\n vi.clearAllMocks();\n listProfilesMock.mockResolvedValue([\n {\n id: \"profile-1\",\n name: \"Alpha\",\n isActive: true,\n createdAt: new Date(\"2026-01-01T00:00:00.000Z\"),\n updatedAt: new Date(\"2026-01-02T00:00:00.000Z\"),\n },\n ]);\n listGoogleMappingsMock.mockResolvedValue([]);\n listGtmSummariesMock.mockResolvedValue([\n { profileId: \"profile-1\", activeMappingCount: 2 },\n ]);\n getGoogleOAuthConnectionMock.mockResolvedValue(connection());\n listVtexConnectionsMock.mockResolvedValue([]);\n listMercadolibreConnectionsMock.mockResolvedValue([]);\n listMetaMappingsMock.mockResolvedValue([]);\n });\n\n it(\"adds active GTM readiness without leaking mapped resource identifiers\", async () => {\n const response = await listProfilesHandler();\n const profile = (\n response as unknown as {\n value: { profiles: Array<Record<string, unknown>> };\n }\n ).value.profiles[0];\n\n expect(profile).toMatchObject({\n profile_id: \"profile-1\",\n name: \"Alpha\",\n is_active: true,\n created_at: \"2026-01-01T00:00:00.000Z\",\n updated_at: \"2026-01-02T00:00:00.000Z\",\n services: {\n google: {\n google_ads: {\n configured: false,\n status: \"not_configured\",\n raw_status: null,\n },\n ga4: {\n configured: false,\n status: \"not_configured\",\n raw_status: null,\n },\n search_console: {\n configured: false,\n status: \"not_configured\",\n raw_status: null,\n },\n },\n vtex: { configured: false, status: \"not_configured\", raw_status: null },\n mercadolibre: {\n configured: false,\n status: \"not_configured\",\n raw_status: null,\n },\n meta: { configured: false, status: \"not_configured\", raw_status: null },\n },\n });\n expect(\n (profile.services as { google: { gtm: unknown } }).google.gtm,\n ).toEqual({\n configured: true,\n status: \"active\",\n raw_status: \"active\",\n });\n expect(JSON.stringify(profile)).not.toContain(\"account\");\n expect(JSON.stringify(profile)).not.toContain(\"container\");\n });\n\n it(\"reports not_configured and hides OAuth raw status without active mappings\", async () => {\n listGtmSummariesMock.mockResolvedValue([]);\n\n await expect(getGtmService()).resolves.toEqual({\n configured: false,\n status: \"not_configured\",\n raw_status: null,\n });\n });\n\n it.each([\"disabled\", \"expired\", \"pending\", \"error\"])(\n \"normalizes an eligible mapping with OAuth status %s\",\n async (status) => {\n getGoogleOAuthConnectionMock.mockResolvedValue(connection({ status }));\n\n await expect(getGtmService()).resolves.toEqual({\n configured: true,\n status,\n raw_status: status,\n });\n },\n );\n\n it.each([\n [\"missing connection\", null],\n [\"missing token\", connection({ encryptedRefreshToken: null })],\n [\"incomplete scopes\", connection({ scopes: requiredScopes.slice(0, -1) })],\n ])(\"reports error for %s\", async (_case, oauthConnection) => {\n getGoogleOAuthConnectionMock.mockResolvedValue(oauthConnection);\n\n await expect(getGtmService()).resolves.toEqual({\n configured: true,\n status: \"error\",\n raw_status: oauthConnection ? \"active\" : null,\n });\n });\n});\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { beforeEach, describe, expect, it, vi } from \"vitest\";\n\nconst objectMock = vi.fn((value) => ({ kind: \"object\", value }));\nconst errorMock = vi.fn((message) => ({ kind: \"error\", message }));\nconst listProfilesMock = vi.fn();\nconst listGoogleMappingsMock = vi.fn();\nconst listGtmSummariesMock = vi.fn();\nconst getGoogleOAuthConnectionMock = vi.fn();\nconst listVtexConnectionsMock = vi.fn();\nconst listMercadolibreConnectionsMock = vi.fn();\nconst listMetaMappingsMock = vi.fn();\nconst listTiendanubeConnectionsMock = vi.fn();\n\nvi.mock(\"mcp-use/server\", () => ({ object: objectMock, error: errorMock }));\nvi.mock(\"../../../config/profile-store.js\", () => ({\n listProfiles: listProfilesMock,\n}));\nvi.mock(\"../../../config/google-store.js\", () => ({\n listProfileGoogleServiceMappings: listGoogleMappingsMock,\n listActiveProfileGtmMappingSummaries: listGtmSummariesMock,\n getGoogleOAuthConnection: getGoogleOAuthConnectionMock,\n}));\nvi.mock(\"../../../config/vtex-profile-store.js\", () => ({\n listVtexConnections: listVtexConnectionsMock,\n}));\nvi.mock(\"../../../config/mercadolibre-profile-store.js\", () => ({\n listMercadoLibreConnections: listMercadolibreConnectionsMock,\n}));\nvi.mock(\"../../../config/meta-store.js\", () => ({\n listProfileMetaMappings: listMetaMappingsMock,\n}));\nvi.mock(\"../../../config/tiendanube-profile-store.js\", () => ({\n listTiendanubeConnections: listTiendanubeConnectionsMock,\n}));\n\nconst { listProfilesHandler } = await import(\"../list-profiles.js\");\nconst requiredScopes = [\n \"tagmanager.manage.accounts\",\n \"tagmanager.edit.containers\",\n \"tagmanager.delete.containers\",\n \"tagmanager.edit.containerversions\",\n \"tagmanager.manage.users\",\n \"tagmanager.publish\",\n \"tagmanager.readonly\",\n].map((scope) => `https://www.googleapis.com/auth/${scope}`);\n\nfunction connection(overrides: Record<string, unknown> = {}) {\n return {\n id: \"global\",\n encryptedRefreshToken: \"encrypted-token\",\n scopes: requiredScopes,\n status: \"active\",\n googleAccountEmail: null,\n lastValidatedAt: null,\n lastError: null,\n ...overrides,\n };\n}\n\nasync function getGtmService() {\n const response = await listProfilesHandler();\n return (\n response as unknown as {\n value: { profiles: Array<{ services: { google: { gtm: unknown } } }> };\n }\n ).value.profiles[0].services.google.gtm;\n}\n\ndescribe(\"config_list_profiles GTM readiness\", () => {\n beforeEach(() => {\n vi.clearAllMocks();\n listProfilesMock.mockResolvedValue([\n {\n id: \"profile-1\",\n name: \"Alpha\",\n isActive: true,\n createdAt: new Date(\"2026-01-01T00:00:00.000Z\"),\n updatedAt: new Date(\"2026-01-02T00:00:00.000Z\"),\n },\n ]);\n listGoogleMappingsMock.mockResolvedValue([]);\n listGtmSummariesMock.mockResolvedValue([\n { profileId: \"profile-1\", activeMappingCount: 2 },\n ]);\n getGoogleOAuthConnectionMock.mockResolvedValue(connection());\n listVtexConnectionsMock.mockResolvedValue([]);\n listMercadolibreConnectionsMock.mockResolvedValue([]);\n listMetaMappingsMock.mockResolvedValue([]);\n listTiendanubeConnectionsMock.mockResolvedValue([]);\n });\n\n it(\"adds active GTM readiness without leaking mapped resource identifiers\", async () => {\n const response = await listProfilesHandler();\n const profile = (\n response as unknown as {\n value: { profiles: Array<Record<string, unknown>> };\n }\n ).value.profiles[0];\n\n expect(profile).toMatchObject({\n profile_id: \"profile-1\",\n name: \"Alpha\",\n is_active: true,\n created_at: \"2026-01-01T00:00:00.000Z\",\n updated_at: \"2026-01-02T00:00:00.000Z\",\n services: {\n google: {\n google_ads: {\n configured: false,\n status: \"not_configured\",\n raw_status: null,\n },\n ga4: {\n configured: false,\n status: \"not_configured\",\n raw_status: null,\n },\n search_console: {\n configured: false,\n status: \"not_configured\",\n raw_status: null,\n },\n },\n vtex: { configured: false, status: \"not_configured\", raw_status: null },\n mercadolibre: {\n configured: false,\n status: \"not_configured\",\n raw_status: null,\n },\n meta: { configured: false, status: \"not_configured\", raw_status: null },\n tiendanube: {\n available: true,\n external_mcp: true,\n configured: false,\n status: \"not_configured\",\n raw_status: null,\n validation_status: \"not_configured\",\n last_validated_at: null,\n store_id: null,\n capabilities: {\n connection_reporting: true,\n operational_tools: \"external_mcp\",\n provider_surface: \"provisional\",\n },\n },\n },\n });\n expect(\n (profile.services as { google: { gtm: unknown } }).google.gtm,\n ).toEqual({\n configured: true,\n status: \"active\",\n raw_status: \"active\",\n });\n expect(JSON.stringify(profile)).not.toContain(\"account\");\n expect(JSON.stringify(profile)).not.toContain(\"container\");\n });\n\n it(\"reports not_configured and hides OAuth raw status without active mappings\", async () => {\n listGtmSummariesMock.mockResolvedValue([]);\n\n await expect(getGtmService()).resolves.toEqual({\n configured: false,\n status: \"not_configured\",\n raw_status: null,\n });\n });\n\n it.each([\"disabled\", \"expired\", \"pending\", \"error\"])(\n \"normalizes an eligible mapping with OAuth status %s\",\n async (status) => {\n getGoogleOAuthConnectionMock.mockResolvedValue(connection({ status }));\n\n await expect(getGtmService()).resolves.toEqual({\n configured: true,\n status,\n raw_status: status,\n });\n },\n );\n\n it.each([\n [\"missing connection\", null],\n [\"missing token\", connection({ encryptedRefreshToken: null })],\n [\"incomplete scopes\", connection({ scopes: requiredScopes.slice(0, -1) })],\n ])(\"reports error for %s\", async (_case, oauthConnection) => {\n getGoogleOAuthConnectionMock.mockResolvedValue(oauthConnection);\n\n await expect(getGtmService()).resolves.toEqual({\n configured: true,\n status: \"error\",\n raw_status: oauthConnection ? \"active\" : null,\n });\n });\n\n it(\"reports a profile-scoped active Tiendanube connection without secret fields\", async () => {\n listTiendanubeConnectionsMock.mockResolvedValue([\n {\n profileId: \"profile-1\",\n storeId: \"store-42\",\n status: \"active\",\n lastValidatedAt: new Date(\"2026-01-03T00:00:00.000Z\"),\n },\n ]);\n\n const response = await listProfilesHandler();\n const profile = (\n response as unknown as { value: { profiles: Array<Record<string, unknown>> } }\n ).value.profiles[0];\n\n expect(profile.services).toMatchObject({\n tiendanube: {\n available: true,\n external_mcp: true,\n configured: true,\n status: \"active\",\n raw_status: \"active\",\n validation_status: \"validated\",\n last_validated_at: \"2026-01-03T00:00:00.000Z\",\n store_id: \"store-42\",\n capabilities: {\n connection_reporting: true,\n operational_tools: \"external_mcp\",\n provider_surface: \"provisional\",\n },\n },\n });\n expect(JSON.stringify(profile)).not.toContain(\"encrypted\");\n expect(JSON.stringify(profile)).not.toContain(\"last_error\");\n });\n\n it.each([\n [\"disabled\", null, \"not_validated\"],\n [\"expired\", new Date(\"2026-01-03T00:00:00.000Z\"), \"failed\"],\n [\"pending\", null, \"pending\"],\n [\"error\", new Date(\"2026-01-03T00:00:00.000Z\"), \"failed\"],\n ] as const)(\n \"preserves Tiendanube status %s and reports validation state\",\n async (status, lastValidatedAt, validationStatus) => {\n listTiendanubeConnectionsMock.mockResolvedValue([\n {\n profileId: \"profile-1\",\n storeId: \"store-42\",\n status,\n lastValidatedAt,\n },\n ]);\n\n await expect(getTiendanubeService()).resolves.toMatchObject({\n configured: true,\n status,\n raw_status: status,\n validation_status: validationStatus,\n last_validated_at: lastValidatedAt?.toISOString() ?? null,\n store_id: \"store-42\",\n });\n },\n );\n\n it(\"keeps Tiendanube readiness isolated by profile\", async () => {\n listProfilesMock.mockResolvedValue([\n {\n id: \"profile-1\",\n name: \"Alpha\",\n isActive: true,\n createdAt: new Date(\"2026-01-01T00:00:00.000Z\"),\n updatedAt: new Date(\"2026-01-02T00:00:00.000Z\"),\n },\n {\n id: \"profile-2\",\n name: \"Beta\",\n isActive: true,\n createdAt: new Date(\"2026-01-01T00:00:00.000Z\"),\n updatedAt: new Date(\"2026-01-02T00:00:00.000Z\"),\n },\n ]);\n listTiendanubeConnectionsMock.mockResolvedValue([\n {\n profileId: \"profile-2\",\n storeId: \"store-2\",\n status: \"active\",\n lastValidatedAt: null,\n },\n ]);\n\n const response = await listProfilesHandler();\n const profiles = (\n response as unknown as {\n value: {\n profiles: Array<{\n services: { tiendanube: Record<string, unknown> };\n }>;\n };\n }\n ).value.profiles;\n\n expect(profiles[0].services.tiendanube).toMatchObject({\n configured: false,\n status: \"not_configured\",\n store_id: null,\n });\n expect(profiles[1].services.tiendanube).toMatchObject({\n configured: true,\n status: \"active\",\n store_id: \"store-2\",\n });\n });\n\n it(\"omits an unsafe public store identifier\", async () => {\n listTiendanubeConnectionsMock.mockResolvedValue([\n {\n profileId: \"profile-1\",\n storeId: \" store-42\\nprivate-value \",\n status: \"active\",\n lastValidatedAt: null,\n },\n ]);\n\n await expect(getTiendanubeService()).resolves.toMatchObject({\n configured: true,\n status: \"active\",\n store_id: null,\n });\n });\n\n it(\"returns a safe error response when a connection read fails\", async () => {\n listTiendanubeConnectionsMock.mockRejectedValue(\n new Error(\"unexpected database failure\"),\n );\n\n await expect(listProfilesHandler()).resolves.toEqual({\n kind: \"error\",\n message: \"Failed to list profiles\",\n });\n });\n});\n\nasync function getTiendanubeService() {\n const response = await listProfilesHandler();\n return (\n response as unknown as {\n value: { profiles: Array<{ services: { tiendanube: unknown } }> };\n }\n ).value.profiles[0].services.tiendanube;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }