@fluentcommerce/fc-connect-sdk 0.1.53 → 0.1.55

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 (495) hide show
  1. package/CHANGELOG.md +30 -2
  2. package/README.md +39 -0
  3. package/dist/cjs/auth/index.d.ts +3 -0
  4. package/dist/cjs/auth/index.js +13 -0
  5. package/dist/cjs/auth/profile-loader.d.ts +18 -0
  6. package/dist/cjs/auth/profile-loader.js +208 -0
  7. package/dist/cjs/client-factory.d.ts +4 -0
  8. package/dist/cjs/client-factory.js +10 -0
  9. package/dist/cjs/clients/fluent-client.js +13 -6
  10. package/dist/cjs/index.d.ts +3 -1
  11. package/dist/cjs/index.js +8 -2
  12. package/dist/cjs/utils/pagination-helpers.js +38 -2
  13. package/dist/cjs/versori/fluent-versori-client.js +11 -5
  14. package/dist/esm/auth/index.d.ts +3 -0
  15. package/dist/esm/auth/index.js +2 -0
  16. package/dist/esm/auth/profile-loader.d.ts +18 -0
  17. package/dist/esm/auth/profile-loader.js +169 -0
  18. package/dist/esm/client-factory.d.ts +4 -0
  19. package/dist/esm/client-factory.js +9 -0
  20. package/dist/esm/clients/fluent-client.js +13 -6
  21. package/dist/esm/index.d.ts +3 -1
  22. package/dist/esm/index.js +2 -1
  23. package/dist/esm/utils/pagination-helpers.js +38 -2
  24. package/dist/esm/versori/fluent-versori-client.js +11 -5
  25. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  26. package/dist/tsconfig.tsbuildinfo +1 -1
  27. package/dist/tsconfig.types.tsbuildinfo +1 -1
  28. package/dist/types/auth/index.d.ts +3 -0
  29. package/dist/types/auth/profile-loader.d.ts +18 -0
  30. package/dist/types/client-factory.d.ts +4 -0
  31. package/dist/types/index.d.ts +3 -1
  32. package/docs/00-START-HERE/EXPORT-VALIDATION.md +158 -158
  33. package/docs/00-START-HERE/cli-analyze-source-structure-guide.md +655 -655
  34. package/docs/00-START-HERE/cli-documentation-index.md +202 -202
  35. package/docs/00-START-HERE/cli-quick-reference.md +252 -252
  36. package/docs/00-START-HERE/decision-tree.md +552 -552
  37. package/docs/00-START-HERE/getting-started.md +1070 -1070
  38. package/docs/00-START-HERE/mapper-quick-decision-guide.md +235 -235
  39. package/docs/00-START-HERE/readme.md +237 -237
  40. package/docs/00-START-HERE/retailerid-configuration.md +404 -404
  41. package/docs/00-START-HERE/sdk-philosophy.md +794 -794
  42. package/docs/00-START-HERE/troubleshooting-quick-reference.md +1086 -1086
  43. package/docs/01-TEMPLATES/faq.md +686 -686
  44. package/docs/01-TEMPLATES/patterns/pattern-templates-guide.md +68 -68
  45. package/docs/01-TEMPLATES/patterns/patterns-csv-schema-validation-and-rejection-report.md +233 -233
  46. package/docs/01-TEMPLATES/patterns/patterns-custom-resolvers.md +407 -407
  47. package/docs/01-TEMPLATES/patterns/patterns-error-handling-retry.md +511 -511
  48. package/docs/01-TEMPLATES/patterns/patterns-field-mapping-universal.md +701 -701
  49. package/docs/01-TEMPLATES/patterns/patterns-large-file-splitting.md +1430 -1430
  50. package/docs/01-TEMPLATES/patterns/patterns-master-data-etl.md +2399 -2399
  51. package/docs/01-TEMPLATES/patterns/patterns-pagination-streaming.md +447 -447
  52. package/docs/01-TEMPLATES/patterns/patterns-state-duplicate-prevention.md +385 -385
  53. package/docs/01-TEMPLATES/readme.md +957 -957
  54. package/docs/01-TEMPLATES/standalone/standalone-asn-inbound-processing.md +1209 -1209
  55. package/docs/01-TEMPLATES/standalone/standalone-graphql-query-export.md +1140 -1140
  56. package/docs/01-TEMPLATES/standalone/standalone-graphql-to-parquet-partitioned-s3.md +432 -432
  57. package/docs/01-TEMPLATES/standalone/standalone-multi-channel-inventory-sync.md +1185 -1185
  58. package/docs/01-TEMPLATES/standalone/standalone-multi-source-aggregation.md +1462 -1462
  59. package/docs/01-TEMPLATES/standalone/standalone-s3-csv-batch-api.md +1390 -1390
  60. package/docs/01-TEMPLATES/standalone/standalone-s3-csv-inventory-to-batch.md +330 -330
  61. package/docs/01-TEMPLATES/standalone/standalone-scripts-guide.md +87 -87
  62. package/docs/01-TEMPLATES/standalone/standalone-sftp-xml-graphql.md +1444 -1444
  63. package/docs/01-TEMPLATES/standalone/standalone-webhook-payload-processing.md +688 -688
  64. package/docs/01-TEMPLATES/versori/business-examples/business-examples-dropship-order-routing.md +193 -193
  65. package/docs/01-TEMPLATES/versori/business-examples/business-examples-graphql-parquet-extraction.md +518 -518
  66. package/docs/01-TEMPLATES/versori/business-examples/business-examples-inter-location-transfers.md +2162 -2162
  67. package/docs/01-TEMPLATES/versori/business-examples/business-examples-pre-order-allocation.md +2226 -2226
  68. package/docs/01-TEMPLATES/versori/business-examples/business-scenarios-guide.md +87 -87
  69. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-connection-validation-pattern.md +656 -656
  70. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-dual-workflow-connector.md +835 -835
  71. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-guide.md +108 -108
  72. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-kv-state-management.md +1533 -1533
  73. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-xml-response-patterns.md +1160 -1160
  74. package/docs/01-TEMPLATES/versori/versori-platform-guide.md +201 -201
  75. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-asn-purchase-order.md +1906 -1906
  76. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-dropship-routing.md +1074 -1074
  77. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-flash-sale-reserve.md +1395 -1395
  78. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-generic-xml-order.md +888 -888
  79. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-payment-gateway-integration.md +2478 -2478
  80. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-rma-returns-comprehensive.md +2240 -2240
  81. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-xml-order-ingestion.md +2029 -2029
  82. package/docs/01-TEMPLATES/versori/webhooks/webhook-templates-guide.md +140 -140
  83. package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/inventory-mapping.json +20 -20
  84. package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/products_2025-01-22.csv +11 -11
  85. package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/sample-data-guide.md +34 -34
  86. package/docs/01-TEMPLATES/versori/workflows/_examples/workflow-examples-guide.md +36 -36
  87. package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-modes-guide.md +1038 -1038
  88. package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-workflows-guide.md +138 -138
  89. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/graphql-extraction-guide.md +63 -63
  90. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-csv.md +2062 -2062
  91. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-xml.md +2294 -2294
  92. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-s3-csv.md +2461 -2461
  93. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-sftp-xml.md +2529 -2529
  94. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-csv.md +2464 -2464
  95. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-json.md +1959 -1959
  96. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-s3-csv.md +1953 -1953
  97. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-sftp-xml.md +2541 -2541
  98. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-s3-json.md +2384 -2384
  99. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-sftp-xml.md +2445 -2445
  100. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-csv.md +2355 -2355
  101. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-json.md +2042 -2042
  102. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-sftp-xml.md +2726 -2726
  103. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/batch-api-guide.md +206 -206
  104. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-cycle-count-reconciliation.md +2030 -2030
  105. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-multi-channel-inventory-sync.md +1882 -1882
  106. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-csv-inventory-batch.md +2827 -2827
  107. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-json-inventory-batch.md +1952 -1952
  108. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-xml-inventory-batch.md +3289 -3289
  109. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-csv-inventory-batch.md +3064 -3064
  110. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-json-inventory-batch.md +3238 -3238
  111. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-xml-inventory-batch.md +2977 -2977
  112. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/event-api-guide.md +321 -321
  113. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-json-order-cancel-event.md +959 -959
  114. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-xml-order-cancel-event.md +1170 -1170
  115. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-csv-product-event.md +2312 -2312
  116. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-json-product-event.md +2999 -2999
  117. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-parquet-product-event.md +2836 -2836
  118. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-xml-product-event.md +2395 -2395
  119. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-csv-product-event.md +2295 -2295
  120. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-json-product-event.md +2602 -2602
  121. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-parquet-product-event.md +2589 -2589
  122. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-xml-product-event.md +3578 -3578
  123. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/graphql-mutations-guide.md +93 -93
  124. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-json-order-update-graphql.md +1260 -1260
  125. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-xml-order-update-graphql.md +1472 -1472
  126. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-control-graphql.md +2417 -2417
  127. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-location-graphql.md +2811 -2811
  128. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-price-graphql.md +2619 -2619
  129. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-json-location-graphql.md +2807 -2807
  130. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-xml-location-graphql.md +2373 -2373
  131. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-control-graphql.md +2740 -2740
  132. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-location-graphql.md +2760 -2760
  133. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-json-location-graphql.md +1710 -1710
  134. package/docs/01-TEMPLATES/versori/workflows/ingestion/ingestion-workflows-guide.md +136 -136
  135. package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/rubix-webhooks-guide.md +520 -520
  136. package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-inline.md +1418 -1418
  137. package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-universal-mapper.md +1785 -1785
  138. package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-order-attribute-update.md +824 -824
  139. package/docs/01-TEMPLATES/versori/workflows/workflows-overview-guide.md +646 -646
  140. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-batch-archival.md +724 -724
  141. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-job-tracker.md +627 -627
  142. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-partial-batch-recovery.md +561 -561
  143. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-quick-reference.md +367 -367
  144. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-readme.md +407 -407
  145. package/docs/02-CORE-GUIDES/advanced-services/readme.md +49 -49
  146. package/docs/02-CORE-GUIDES/api-reference/api-reference-quick-reference.md +548 -548
  147. package/docs/02-CORE-GUIDES/api-reference/event-api-input-output-reference.md +702 -1171
  148. package/docs/02-CORE-GUIDES/api-reference/examples/client-initialization.ts +286 -286
  149. package/docs/02-CORE-GUIDES/api-reference/graphql-error-classification.md +337 -337
  150. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-01-client-api.md +399 -482
  151. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-03-authentication.md +199 -199
  152. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-04-graphql-mapping.md +925 -925
  153. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-05-services.md +1198 -1198
  154. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-06-data-sources.md +1083 -1083
  155. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-07-parsers.md +1097 -1097
  156. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-pagination.md +513 -513
  157. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-types.md +545 -597
  158. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-error-handling.md +527 -527
  159. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-webhook-validation.md +514 -514
  160. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-extraction.md +557 -557
  161. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-utilities.md +412 -412
  162. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-cli-tools.md +423 -423
  163. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-error-handling.md +716 -716
  164. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-analyze-source-structure.md +518 -518
  165. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-partial-responses.md +212 -212
  166. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-testing.md +300 -300
  167. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-13-resolver-builder.md +322 -322
  168. package/docs/02-CORE-GUIDES/api-reference/readme.md +279 -279
  169. package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-quick-reference.md +351 -351
  170. package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-readme.md +277 -277
  171. package/docs/02-CORE-GUIDES/auto-pagination/examples/auto-pagination-readme.md +178 -178
  172. package/docs/02-CORE-GUIDES/auto-pagination/examples/common-patterns.ts +351 -351
  173. package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-products.ts +384 -384
  174. package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-virtual-positions.ts +308 -308
  175. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-01-foundations.md +470 -470
  176. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-02-quick-start.md +713 -713
  177. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-03-configuration.md +754 -754
  178. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-04-advanced-patterns.md +732 -732
  179. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-05-sdk-integration.md +847 -847
  180. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-06-troubleshooting.md +359 -359
  181. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-07-api-reference.md +462 -462
  182. package/docs/02-CORE-GUIDES/auto-pagination/readme.md +54 -54
  183. package/docs/02-CORE-GUIDES/data-sources/data-sources-file-operations-error-handling.md +1487 -1487
  184. package/docs/02-CORE-GUIDES/data-sources/data-sources-quick-reference.md +836 -836
  185. package/docs/02-CORE-GUIDES/data-sources/data-sources-readme.md +276 -276
  186. package/docs/02-CORE-GUIDES/data-sources/data-sources-sftp-credential-access-security.md +553 -553
  187. package/docs/02-CORE-GUIDES/data-sources/examples/common-patterns.ts +409 -409
  188. package/docs/02-CORE-GUIDES/data-sources/examples/data-sources-readme.md +178 -178
  189. package/docs/02-CORE-GUIDES/data-sources/examples/s3-operations.ts +308 -308
  190. package/docs/02-CORE-GUIDES/data-sources/examples/sftp-operations.ts +371 -371
  191. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-01-foundations.md +735 -735
  192. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-02-s3-operations.md +1302 -1302
  193. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-03-sftp-operations.md +1379 -1379
  194. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-04-file-patterns.md +941 -941
  195. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-05-advanced-topics.md +813 -813
  196. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-06-integration-patterns.md +486 -486
  197. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-07-troubleshooting.md +387 -387
  198. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-08-api-reference.md +417 -417
  199. package/docs/02-CORE-GUIDES/data-sources/readme.md +77 -77
  200. package/docs/02-CORE-GUIDES/error-handling-guide.md +936 -936
  201. package/docs/02-CORE-GUIDES/extraction/examples/02-core-guides-extraction-readme.md +116 -116
  202. package/docs/02-CORE-GUIDES/extraction/examples/common-patterns.ts +428 -428
  203. package/docs/02-CORE-GUIDES/extraction/examples/extract-inventory-basic.ts +187 -187
  204. package/docs/02-CORE-GUIDES/extraction/extraction-quick-reference.md +596 -596
  205. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-01-foundations.md +514 -514
  206. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-02-basic-extraction.md +823 -823
  207. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-03-parquet-processing.md +507 -507
  208. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-04-data-enrichment.md +546 -546
  209. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-05-transformation.md +494 -494
  210. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-export-formats.md +458 -458
  211. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-performance.md +138 -138
  212. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-api-reference.md +148 -148
  213. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-optimization.md +692 -692
  214. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-08-extraction-orchestrator.md +1008 -1008
  215. package/docs/02-CORE-GUIDES/extraction/readme.md +151 -151
  216. package/docs/02-CORE-GUIDES/ingestion/examples/_simple-kv-store.ts +40 -40
  217. package/docs/02-CORE-GUIDES/ingestion/examples/error-recovery.ts +728 -728
  218. package/docs/02-CORE-GUIDES/ingestion/examples/event-driven.ts +501 -501
  219. package/docs/02-CORE-GUIDES/ingestion/examples/local-file-ingestion.ts +88 -88
  220. package/docs/02-CORE-GUIDES/ingestion/examples/parquet-ingestion.ts +117 -117
  221. package/docs/02-CORE-GUIDES/ingestion/examples/performance-optimized.ts +647 -647
  222. package/docs/02-CORE-GUIDES/ingestion/examples/s3-csv-ingestion.ts +169 -169
  223. package/docs/02-CORE-GUIDES/ingestion/examples/sftp-csv-ingestion.ts +134 -134
  224. package/docs/02-CORE-GUIDES/ingestion/ingestion-quick-reference.md +546 -546
  225. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-01-introduction.md +626 -626
  226. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-02-quick-start.md +658 -658
  227. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-03-data-sources.md +1052 -1052
  228. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-04-field-mapping.md +763 -763
  229. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-05-advanced-parsers.md +676 -676
  230. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-06-batch-api.md +1295 -1295
  231. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-api-reference.md +138 -138
  232. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-state-management.md +1037 -1037
  233. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-08-performance-optimization.md +1349 -1349
  234. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-09-best-practices.md +1893 -1893
  235. package/docs/02-CORE-GUIDES/ingestion/readme.md +160 -160
  236. package/docs/02-CORE-GUIDES/logging-guide.md +585 -585
  237. package/docs/02-CORE-GUIDES/mapping/error-handling-patterns.md +401 -401
  238. package/docs/02-CORE-GUIDES/mapping/examples/02-core-guides-mapping-readme.md +128 -128
  239. package/docs/02-CORE-GUIDES/mapping/examples/common-patterns.ts +273 -273
  240. package/docs/02-CORE-GUIDES/mapping/examples/csv-location-ingestion.json +36 -36
  241. package/docs/02-CORE-GUIDES/mapping/examples/csv-mapping.ts +242 -242
  242. package/docs/02-CORE-GUIDES/mapping/examples/graphql-to-parquet-extraction.json +36 -36
  243. package/docs/02-CORE-GUIDES/mapping/examples/json-mapping.ts +213 -213
  244. package/docs/02-CORE-GUIDES/mapping/examples/json-product-to-mutation.json +48 -48
  245. package/docs/02-CORE-GUIDES/mapping/examples/xml-mapping.ts +291 -291
  246. package/docs/02-CORE-GUIDES/mapping/examples/xml-order-to-mutation.json +45 -45
  247. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-quick-reference.md +463 -463
  248. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-readme.md +227 -227
  249. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-01-introduction.md +222 -222
  250. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-02-quick-start.md +351 -351
  251. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-03-schema-validation.md +569 -569
  252. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-04-mapping-patterns.md +471 -471
  253. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-05-configuration-reference.md +611 -611
  254. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-advanced-xpath.md +148 -148
  255. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-path-syntax.md +464 -464
  256. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-api-reference.md +94 -94
  257. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-array-handling.md +307 -307
  258. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-08-custom-resolvers.md +544 -544
  259. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-09-advanced-patterns.md +427 -427
  260. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-10-hooks-and-variables.md +336 -336
  261. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-11-error-handling.md +488 -488
  262. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-12-arguments-vs-nodes.md +383 -383
  263. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-13-best-practices.md +477 -477
  264. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/readme.md +62 -62
  265. package/docs/02-CORE-GUIDES/mapping/mapping-format-decision-tree.md +480 -480
  266. package/docs/02-CORE-GUIDES/mapping/mapping-graphql-alias-batching-guide.md +820 -820
  267. package/docs/02-CORE-GUIDES/mapping/mapping-javascript-objects.md +2369 -2369
  268. package/docs/02-CORE-GUIDES/mapping/mapping-mapper-comparison-guide.md +682 -682
  269. package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-07-api-reference.md +1327 -1327
  270. package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-08-error-handling.md +1142 -1142
  271. package/docs/02-CORE-GUIDES/mapping/modules/mapping-04-use-cases.md +891 -891
  272. package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-helpers-resolvers.md +1126 -1126
  273. package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-sdk-resolvers.md +199 -199
  274. package/docs/02-CORE-GUIDES/mapping/modules/mapping-07-api-reference.md +1319 -1319
  275. package/docs/02-CORE-GUIDES/mapping/readme.md +178 -178
  276. package/docs/02-CORE-GUIDES/mapping/resolver-registration.md +410 -410
  277. package/docs/02-CORE-GUIDES/mapping/resolvers/examples/common-patterns.ts +226 -226
  278. package/docs/02-CORE-GUIDES/mapping/resolvers/examples/custom-resolvers.ts +227 -227
  279. package/docs/02-CORE-GUIDES/mapping/resolvers/examples/sdk-resolvers-usage.ts +203 -203
  280. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-readme.md +274 -274
  281. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-api-reference.md +679 -679
  282. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-cookbook.md +826 -826
  283. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-guide.md +1330 -1330
  284. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-helpers-reference.md +1437 -1437
  285. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-parameters-reference.md +553 -553
  286. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-troubleshooting.md +854 -854
  287. package/docs/02-CORE-GUIDES/mapping/resolvers/readme.md +75 -75
  288. package/docs/02-CORE-GUIDES/parsers/examples/02-core-guides-parsers-readme.md +161 -161
  289. package/docs/02-CORE-GUIDES/parsers/examples/csv-parser-examples.ts +110 -110
  290. package/docs/02-CORE-GUIDES/parsers/examples/json-parser-examples.ts +33 -33
  291. package/docs/02-CORE-GUIDES/parsers/examples/parquet-parser-examples.ts +47 -47
  292. package/docs/02-CORE-GUIDES/parsers/examples/xml-parser-examples.ts +38 -38
  293. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-01-foundations.md +355 -355
  294. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-02-csv-parser.md +772 -772
  295. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-03-json-parser.md +789 -789
  296. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-04-xml-parser.md +857 -857
  297. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-05-parquet-parser.md +603 -603
  298. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-integration-patterns.md +702 -702
  299. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-streaming.md +121 -121
  300. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-api-reference.md +89 -89
  301. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-troubleshooting.md +727 -727
  302. package/docs/02-CORE-GUIDES/parsers/parsers-quick-reference.md +482 -482
  303. package/docs/02-CORE-GUIDES/parsers/parsers-readme.md +258 -258
  304. package/docs/02-CORE-GUIDES/parsers/readme.md +65 -65
  305. package/docs/02-CORE-GUIDES/readme.md +194 -194
  306. package/docs/02-CORE-GUIDES/webhook-validation/examples/basic-validation.ts +108 -108
  307. package/docs/02-CORE-GUIDES/webhook-validation/examples/common-patterns.ts +316 -316
  308. package/docs/02-CORE-GUIDES/webhook-validation/examples/webhook-validation-readme.md +61 -61
  309. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-01-foundations.md +440 -440
  310. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-02-quick-start.md +525 -525
  311. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-03-versori-integration.md +741 -741
  312. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-04-platform-integration.md +629 -629
  313. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-05-configuration.md +535 -535
  314. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-error-handling.md +611 -611
  315. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-troubleshooting.md +124 -124
  316. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-07-api-reference.md +511 -511
  317. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-08-rubix-webhooks.md +590 -590
  318. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-09-rubix-event-vs-http-call.md +432 -432
  319. package/docs/02-CORE-GUIDES/webhook-validation/readme.md +239 -239
  320. package/docs/02-CORE-GUIDES/webhook-validation/webhook-validation-quick-reference.md +392 -392
  321. package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-quick-reference.md +498 -498
  322. package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-readme.md +313 -313
  323. package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/common-patterns.ts +612 -612
  324. package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/connector-scenarios-readme.md +253 -253
  325. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-01-foundations.md +452 -452
  326. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-02-simple-scenarios.md +681 -681
  327. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-03-intermediate-scenarios.md +637 -637
  328. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-04-advanced-scenarios.md +650 -650
  329. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-05-bidirectional-sync.md +233 -233
  330. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-06-production-patterns.md +442 -442
  331. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-07-reference.md +445 -445
  332. package/docs/03-PATTERN-GUIDES/connector-scenarios/readme.md +31 -31
  333. package/docs/03-PATTERN-GUIDES/enterprise-integration-patterns.md +1528 -1528
  334. package/docs/03-PATTERN-GUIDES/error-handling/comprehensive-error-handling-guide.md +1437 -1437
  335. package/docs/03-PATTERN-GUIDES/error-handling/error-handling-quick-reference.md +390 -390
  336. package/docs/03-PATTERN-GUIDES/error-handling/examples/common-patterns.ts +438 -438
  337. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-01-foundations.md +362 -362
  338. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-02-error-types.md +850 -850
  339. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-03-utf8-handling.md +456 -456
  340. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-04-error-scenarios.md +658 -658
  341. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-05-calling-patterns.md +671 -671
  342. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-06-retry-strategies.md +1034 -1034
  343. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-07-monitoring.md +653 -653
  344. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-08-api-reference.md +847 -847
  345. package/docs/03-PATTERN-GUIDES/error-handling/readme.md +36 -36
  346. package/docs/03-PATTERN-GUIDES/examples/__tests__/readme.md +40 -40
  347. package/docs/03-PATTERN-GUIDES/examples/__tests__/resolver-examples.test.js +282 -282
  348. package/docs/03-PATTERN-GUIDES/examples/test-data/03-pattern-guides-readme.md +110 -110
  349. package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-inventory.json +123 -123
  350. package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-order.json +171 -171
  351. package/docs/03-PATTERN-GUIDES/examples/test-data/readme.md +28 -28
  352. package/docs/03-PATTERN-GUIDES/extraction/extraction-readme.md +15 -15
  353. package/docs/03-PATTERN-GUIDES/extraction/readme.md +25 -25
  354. package/docs/03-PATTERN-GUIDES/file-operations/examples/common-patterns.ts +407 -407
  355. package/docs/03-PATTERN-GUIDES/file-operations/examples/file-operations-readme.md +142 -142
  356. package/docs/03-PATTERN-GUIDES/file-operations/file-operations-quick-reference.md +462 -462
  357. package/docs/03-PATTERN-GUIDES/file-operations/file-operations-readme.md +379 -379
  358. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-01-foundations.md +430 -430
  359. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-02-quick-start.md +484 -484
  360. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-03-s3-operations.md +507 -507
  361. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-04-sftp-operations.md +963 -963
  362. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-05-streaming-performance.md +503 -503
  363. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-archive-patterns.md +386 -386
  364. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-error-handling.md +117 -117
  365. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-api-reference.md +78 -78
  366. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-testing-troubleshooting.md +567 -567
  367. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-08-api-reference.md +1055 -1055
  368. package/docs/03-PATTERN-GUIDES/file-operations/readme.md +32 -32
  369. package/docs/03-PATTERN-GUIDES/ingestion/ingestion-readme.md +15 -15
  370. package/docs/03-PATTERN-GUIDES/ingestion/readme.md +25 -25
  371. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/batch-processing.ts +130 -130
  372. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/common-patterns.ts +360 -360
  373. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/delta-sync.ts +130 -130
  374. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/integration-patterns-readme.md +100 -100
  375. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/real-time-webhook.ts +398 -398
  376. package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-quick-reference.md +962 -962
  377. package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-readme.md +134 -134
  378. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-01-real-time-processing.md +991 -991
  379. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-02-batch-processing.md +1547 -1547
  380. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-03-delta-sync.md +1108 -1108
  381. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-04-webhook-patterns.md +1181 -1181
  382. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-05-error-handling.md +1061 -1061
  383. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-advanced-integration-services.md +1547 -1547
  384. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-performance.md +109 -109
  385. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-07-api-reference.md +34 -34
  386. package/docs/03-PATTERN-GUIDES/integration-patterns/readme.md +30 -30
  387. package/docs/03-PATTERN-GUIDES/logging-minimal-mode.md +128 -128
  388. package/docs/03-PATTERN-GUIDES/multiple-connections/examples/common-patterns.ts +380 -380
  389. package/docs/03-PATTERN-GUIDES/multiple-connections/examples/multiple-connections-readme.md +139 -139
  390. package/docs/03-PATTERN-GUIDES/multiple-connections/examples/parallel-root-connections.ts +149 -149
  391. package/docs/03-PATTERN-GUIDES/multiple-connections/examples/real-world-scenarios.ts +405 -405
  392. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-01-foundations.md +378 -378
  393. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-02-quick-start.md +566 -566
  394. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-03-targeting-connections.md +659 -659
  395. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-04-parallel-queries.md +656 -656
  396. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-05-best-practices.md +624 -624
  397. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-api-reference.md +824 -824
  398. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-versori.md +119 -119
  399. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-07-api-reference.md +87 -87
  400. package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-quick-reference.md +353 -353
  401. package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-readme.md +270 -270
  402. package/docs/03-PATTERN-GUIDES/multiple-connections/readme.md +30 -30
  403. package/docs/03-PATTERN-GUIDES/pagination/pagination-readme.md +14 -14
  404. package/docs/03-PATTERN-GUIDES/pagination/readme.md +24 -24
  405. package/docs/03-PATTERN-GUIDES/parquet/examples/common-patterns.ts +180 -180
  406. package/docs/03-PATTERN-GUIDES/parquet/examples/read-parquet.ts +48 -48
  407. package/docs/03-PATTERN-GUIDES/parquet/examples/write-parquet.ts +65 -65
  408. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-01-introduction.md +393 -393
  409. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-02-quick-start.md +572 -572
  410. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-03-reading-parquet.md +525 -525
  411. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-04-writing-parquet.md +554 -554
  412. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-05-graphql-extraction.md +405 -405
  413. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-performance.md +104 -104
  414. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-s3-integration.md +511 -511
  415. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-api-reference.md +90 -90
  416. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-performance-optimization.md +525 -525
  417. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-08-best-practices.md +712 -712
  418. package/docs/03-PATTERN-GUIDES/parquet/parquet-quick-reference.md +683 -683
  419. package/docs/03-PATTERN-GUIDES/parquet/parquet-readme.md +248 -248
  420. package/docs/03-PATTERN-GUIDES/parquet/readme.md +32 -32
  421. package/docs/03-PATTERN-GUIDES/parsers/parsers-readme.md +12 -12
  422. package/docs/03-PATTERN-GUIDES/parsers/readme.md +24 -24
  423. package/docs/03-PATTERN-GUIDES/readme.md +159 -159
  424. package/docs/03-PATTERN-GUIDES/webhooks/readme.md +24 -24
  425. package/docs/03-PATTERN-GUIDES/webhooks/webhooks-readme.md +8 -8
  426. package/docs/04-REFERENCE/architecture/architecture-01-overview.md +427 -427
  427. package/docs/04-REFERENCE/architecture/architecture-02-client-architecture.md +424 -424
  428. package/docs/04-REFERENCE/architecture/architecture-03-data-flow.md +690 -690
  429. package/docs/04-REFERENCE/architecture/architecture-04-service-layer.md +834 -834
  430. package/docs/04-REFERENCE/architecture/architecture-05-integration-architecture.md +655 -655
  431. package/docs/04-REFERENCE/architecture/architecture-06-state-management.md +653 -653
  432. package/docs/04-REFERENCE/architecture/architecture-adding-new-data-sources.md +686 -686
  433. package/docs/04-REFERENCE/architecture/readme.md +279 -279
  434. package/docs/04-REFERENCE/platforms/deno/readme.md +117 -117
  435. package/docs/04-REFERENCE/platforms/nodejs/readme.md +146 -146
  436. package/docs/04-REFERENCE/platforms/readme.md +135 -135
  437. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-01-introduction.md +398 -398
  438. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-02-quick-start.md +560 -560
  439. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-03-authentication.md +757 -757
  440. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-04-workflows.md +2476 -2476
  441. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-05-connections.md +1167 -1167
  442. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-kv-storage.md +990 -990
  443. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-state-management.md +121 -121
  444. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-api-reference.md +68 -68
  445. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-deployment.md +731 -731
  446. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-08-best-practices.md +1111 -1111
  447. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-09-signature-reference.md +766 -766
  448. package/docs/04-REFERENCE/platforms/versori/platforms-versori-readme.md +299 -299
  449. package/docs/04-REFERENCE/platforms/versori/platforms-versori-s3-sftp-configuration-guide.md +1425 -1425
  450. package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-api-key-security.md +816 -816
  451. package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-connection-security.md +681 -681
  452. package/docs/04-REFERENCE/platforms/versori/platforms-versori-workflow-task-types.md +708 -708
  453. package/docs/04-REFERENCE/platforms/versori/readme.md +108 -108
  454. package/docs/04-REFERENCE/readme.md +148 -148
  455. package/docs/04-REFERENCE/resolver-signature/examples/advanced-resolvers.ts +482 -482
  456. package/docs/04-REFERENCE/resolver-signature/examples/async-resolvers.ts +496 -496
  457. package/docs/04-REFERENCE/resolver-signature/examples/basic-resolvers.ts +343 -343
  458. package/docs/04-REFERENCE/resolver-signature/examples/resolver-signature-readme.md +188 -188
  459. package/docs/04-REFERENCE/resolver-signature/examples/testing-resolvers.ts +463 -463
  460. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-01-foundations.md +286 -286
  461. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-02-parameter-reference.md +643 -643
  462. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-03-basic-examples.md +521 -521
  463. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-04-advanced-patterns.md +739 -739
  464. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-05-sdk-resolvers.md +531 -531
  465. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-migration-guide.md +650 -650
  466. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-testing.md +125 -125
  467. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-07-api-reference.md +794 -794
  468. package/docs/04-REFERENCE/resolver-signature/readme.md +64 -64
  469. package/docs/04-REFERENCE/resolver-signature/resolver-signature-quick-reference.md +270 -270
  470. package/docs/04-REFERENCE/resolver-signature/resolver-signature-readme.md +351 -351
  471. package/docs/04-REFERENCE/schema/fluent-commerce-schema.json +764 -764
  472. package/docs/04-REFERENCE/schema/readme.md +141 -141
  473. package/docs/04-REFERENCE/testing/examples/04-reference-testing-readme.md +158 -158
  474. package/docs/04-REFERENCE/testing/examples/fluent-testing.ts +62 -62
  475. package/docs/04-REFERENCE/testing/examples/health-check.ts +155 -155
  476. package/docs/04-REFERENCE/testing/examples/integration-test.ts +119 -119
  477. package/docs/04-REFERENCE/testing/examples/performance-test.ts +183 -183
  478. package/docs/04-REFERENCE/testing/examples/s3-testing.ts +127 -127
  479. package/docs/04-REFERENCE/testing/modules/04-reference-testing-01-foundations.md +267 -267
  480. package/docs/04-REFERENCE/testing/modules/04-reference-testing-02-s3-testing.md +599 -599
  481. package/docs/04-REFERENCE/testing/modules/04-reference-testing-03-fluent-testing.md +589 -589
  482. package/docs/04-REFERENCE/testing/modules/04-reference-testing-04-integration-testing.md +699 -699
  483. package/docs/04-REFERENCE/testing/modules/04-reference-testing-05-debugging.md +478 -478
  484. package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-cicd-integration.md +463 -463
  485. package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-preflight-validation.md +131 -131
  486. package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-best-practices.md +499 -499
  487. package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-coverage-ci.md +165 -165
  488. package/docs/04-REFERENCE/testing/modules/04-reference-testing-08-api-reference.md +634 -634
  489. package/docs/04-REFERENCE/testing/readme.md +86 -86
  490. package/docs/04-REFERENCE/testing/testing-quick-reference.md +667 -667
  491. package/docs/04-REFERENCE/testing/testing-readme.md +286 -286
  492. package/docs/04-REFERENCE/troubleshooting/readme.md +144 -144
  493. package/docs/04-REFERENCE/troubleshooting/troubleshooting-deno-sftp-compatibility.md +392 -392
  494. package/docs/template-loading-matrix.md +242 -242
  495. package/package.json +5 -3
@@ -1,1185 +1,1185 @@
1
- # Standalone: Multi-Channel Inventory Sync (Real-Time ATP to Marketplaces)
2
-
3
- **FC Connect SDK Use Case Guide**
4
-
5
- > **SDK**: [@fluentcommerce/fc-connect-sdk](https://www.npmjs.com/package/@fluentcommerce/fc-connect-sdk)
6
- > **Version**: Use latest - `npm install @fluentcommerce/fc-connect-sdk@latest`
7
-
8
- **Context**: Node.js script that aggregates Available-to-Promise (ATP) inventory from Fluent Commerce and pushes real-time updates to multiple marketplaces (Amazon, eBay, Walmart)
9
-
10
- **Complexity**: High
11
-
12
- **Runtime**: Node.js >=18
13
-
14
- **Estimated Lines**: ~950 lines
15
-
16
- **Volume**: Large (10k-100k SKUs, multiple marketplaces)
17
-
18
- **Latency**: Near real-time (every 5-15 min)
19
-
20
- **Pattern**: GraphQL pagination → external marketplace APIs
21
-
22
- ## What You'll Build
23
-
24
- - OAuth2-authenticated Fluent Commerce client
25
- - GraphQL query with auto-pagination for inventory positions
26
- - ATP (Available-to-Promise) aggregation across multiple locations
27
- - Marketplace-specific buffer stock calculations
28
- - Parallel marketplace updates with rate limiting:
29
- - Amazon MWS/SP-API integration
30
- - eBay Trading API integration
31
- - Walmart Seller API integration
32
- - Per-marketplace error handling and retry logic
33
- - SLA tracking (15-minute sync requirement)
34
- - Comprehensive metrics and logging
35
- - Dry-run mode for testing
36
- - State management to prevent duplicate updates
37
-
38
- ## SDK Methods Used
39
-
40
- - `createClient({ config: { baseUrl, clientId, clientSecret, retailerId } })` - OAuth2 client
41
- - `client.graphql({ query, variables, pagination })` - Query with auto-pagination
42
- - `UniversalMapper(mappingConfig)` - Transform Fluent data to marketplace formats
43
- - `createConsoleLogger()` - Simple console logger
44
- - `toStructuredLogger(logger, context)` - Add context to logs
45
- - `generateCorrelationId()` - Generate unique correlation IDs
46
- - State tracking for incremental updates
47
-
48
- ---
49
-
50
- ## Complete Working Implementation
51
-
52
- ### 1. Project Setup
53
-
54
- ```bash
55
- # Create project directory
56
- mkdir multi-channel-inventory-sync
57
- cd multi-channel-inventory-sync
58
-
59
- # Initialize Node.js project
60
- npm init -y
61
-
62
- # Install dependencies
63
- npm install @fluentcommerce/fc-connect-sdk dotenv axios p-limit p-retry
64
- ```
65
-
66
- ### 2. Environment Configuration
67
-
68
- Create `.env` file:
69
-
70
- ```bash
71
- # Fluent Commerce OAuth2
72
- FLUENT_BASE_URL=https://api.fluentcommerce.com
73
- FLUENT_CLIENT_ID=your-oauth2-client-id
74
- FLUENT_CLIENT_SECRET=your-oauth2-client-secret
75
- FLUENT_RETAILER_ID=your-retailer-id
76
-
77
- # Sync Configuration
78
- SYNC_INTERVAL_MINUTES=15
79
- SLA_THRESHOLD_MINUTES=15
80
- MAX_RECORDS_PER_SYNC=100000
81
- DRY_RUN=false
82
-
83
- # Amazon SP-API Credentials
84
- AMAZON_ENABLED=true
85
- AMAZON_MARKETPLACE_ID=ATVPDKIKX0DER
86
- AMAZON_SELLER_ID=your-amazon-seller-id
87
- AMAZON_REFRESH_TOKEN=your-amazon-refresh-token
88
- AMAZON_CLIENT_ID=amzn1.application-oa2-client.xxxxx
89
- AMAZON_CLIENT_SECRET=your-amazon-client-secret
90
- AMAZON_AWS_ACCESS_KEY_ID=your-aws-access-key
91
- AMAZON_AWS_SECRET_ACCESS_KEY=your-aws-secret-key
92
- AMAZON_REGION=us-east-1
93
- AMAZON_ROLE_ARN=arn:aws:iam::123456789:role/SellingPartnerAPI
94
- AMAZON_BUFFER_STOCK=5
95
- AMAZON_RATE_LIMIT=10
96
-
97
- # eBay Trading API Credentials
98
- EBAY_ENABLED=true
99
- EBAY_APP_ID=your-ebay-app-id
100
- EBAY_DEV_ID=your-ebay-dev-id
101
- EBAY_CERT_ID=your-ebay-cert-id
102
- EBAY_AUTH_TOKEN=your-ebay-auth-token
103
- EBAY_SITE_ID=0
104
- EBAY_SANDBOX=false
105
- EBAY_BUFFER_STOCK=3
106
- EBAY_RATE_LIMIT=5
107
-
108
- # Walmart Seller API Credentials
109
- WALMART_ENABLED=true
110
- WALMART_CLIENT_ID=your-walmart-client-id
111
- WALMART_CLIENT_SECRET=your-walmart-client-secret
112
- WALMART_CHANNEL_TYPE=0a7d6c3e-e9a0-4a0c-8d6a-f6c6f1e7a5c7
113
- WALMART_BUFFER_STOCK=10
114
- WALMART_RATE_LIMIT=20
115
-
116
- # Logging
117
- LOG_LEVEL=info
118
- METRICS_ENABLED=true
119
- ```
120
-
121
- ### 3. Package Configuration
122
-
123
- Create `package.json`:
124
-
125
- ```json
126
- {
127
- "name": "multi-channel-inventory-sync",
128
- "version": "1.0.0",
129
- "type": "module",
130
- "description": "Real-time ATP inventory sync from Fluent Commerce to multiple marketplaces",
131
- "main": "src/index.js",
132
- "scripts": {
133
- "start": "node src/index.js",
134
- "sync:once": "node src/index.js --once",
135
- "sync:continuous": "node src/index.js",
136
- "sync:dry-run": "DRY_RUN=true node src/index.js --once",
137
- "test": "node --test tests/**/*.test.js"
138
- },
139
- "dependencies": {
140
- "@fluentcommerce/fc-connect-sdk": "^0.1.39",
141
- "axios": "^1.6.0",
142
- "dotenv": "^16.0.0",
143
- "p-limit": "^5.0.0",
144
- "p-retry": "^6.0.0"
145
- },
146
- "devDependencies": {
147
- "@types/node": "^20.0.0"
148
- },
149
- "engines": {
150
- "node": ">=18.0.0"
151
- }
152
- }
153
- ```
154
-
155
- ### 4. TypeScript Configuration (tsconfig.json)
156
-
157
- ```json
158
- {
159
- "compilerOptions": {
160
- "module": "ES2022",
161
- "target": "ES2024",
162
- "moduleResolution": "node"
163
- }
164
- }
165
- ```
166
-
167
- ### 5. Main Script Implementation (src/multi-channel-sync.ts)
168
-
169
- > **⚠️ RUNTIME COMPATIBILITY NOTE:**
170
- > This template includes `import { Buffer } from 'node:buffer';` for Deno/Versori compatibility.
171
- > While Buffer is globally available in Node.js and this import is optional for Node.js-only deployments,
172
- > including it ensures the code works across all runtimes (Node.js, Deno, Versori) without modification.
173
-
174
- ```typescript
175
- import 'dotenv/config';
176
- import { Buffer } from 'node:buffer'; // Required for Deno/Versori runtime compatibility
177
-
178
- // FC Connect SDK+
179
- // Install: npm install @fluentcommerce/fc-connect-sdk@latest
180
- // Docs: https://www.npmjs.com/package/@fluentcommerce/fc-connect-sdk
181
- // GitHub: https://github.com/fluentcommerce/fc-connect-sdk
182
-
183
- import {
184
- createClient,
185
- type FluentClient,
186
- type StructuredLogger,
187
- createConsoleLogger,
188
- toStructuredLogger
189
- } from '@fluentcommerce/fc-connect-sdk';
190
-
191
- import axios, { AxiosInstance } from 'axios';
192
- import pLimit from 'p-limit';
193
-
194
- // ============================================================================
195
- // TYPES & INTERFACES
196
- // ============================================================================
197
-
198
- interface InventoryPosition {
199
- productRef: string;
200
- locationRef: string;
201
- quantity: number;
202
- onHand: number;
203
- available: number;
204
- reserved: number;
205
- }
206
-
207
- interface ChannelConfig {
208
- enabled: boolean;
209
- apiClient: AxiosInstance;
210
- bufferStock: number;
211
- rateLimit: number;
212
- }
213
-
214
- interface SyncMetrics {
215
- startTime: Date;
216
- endTime?: Date;
217
- totalSKUs: number;
218
- successfulUpdates: number;
219
- failedUpdates: number;
220
- skippedUpdates: number;
221
- errors: Array<{ sku: string; channel: string; error: string }>;
222
- rateLimitHits: number;
223
- avgResponseTime: number;
224
- }
225
-
226
- // ============================================================================
227
- // CONFIGURATION
228
- // ============================================================================
229
-
230
- const config = {
231
- fluent: {
232
- baseUrl: process.env.FLUENT_BASE_URL!,
233
- clientId: process.env.FLUENT_CLIENT_ID!,
234
- clientSecret: process.env.FLUENT_CLIENT_SECRET!,
235
- retailerId: process.env.FLUENT_RETAILER_ID!,
236
- },
237
- amazon: {
238
- enabled: process.env.AMAZON_ENABLED === 'true',
239
- clientId: process.env.AMAZON_CLIENT_ID!,
240
- clientSecret: process.env.AMAZON_CLIENT_SECRET!,
241
- refreshToken: process.env.AMAZON_REFRESH_TOKEN!,
242
- marketplaceId: process.env.AMAZON_MARKETPLACE_ID!,
243
- sellerId: process.env.AMAZON_SELLER_ID!,
244
- bufferStock: parseInt(process.env.AMAZON_BUFFER_STOCK || '5'),
245
- rateLimit: parseInt(process.env.AMAZON_RATE_LIMIT || '10'),
246
- },
247
- ebay: {
248
- enabled: process.env.EBAY_ENABLED === 'true',
249
- appId: process.env.EBAY_APP_ID!,
250
- certId: process.env.EBAY_CERT_ID!,
251
- authToken: process.env.EBAY_AUTH_TOKEN!,
252
- siteId: process.env.EBAY_SITE_ID || '0',
253
- bufferStock: parseInt(process.env.EBAY_BUFFER_STOCK || '3'),
254
- rateLimit: parseInt(process.env.EBAY_RATE_LIMIT || '5'),
255
- },
256
- walmart: {
257
- enabled: process.env.WALMART_ENABLED === 'true',
258
- clientId: process.env.WALMART_CLIENT_ID!,
259
- clientSecret: process.env.WALMART_CLIENT_SECRET!,
260
- channelType: process.env.WALMART_CHANNEL_TYPE!,
261
- bufferStock: parseInt(process.env.WALMART_BUFFER_STOCK || '10'),
262
- rateLimit: parseInt(process.env.WALMART_RATE_LIMIT || '20'),
263
- },
264
- processing: {
265
- concurrency: parseInt(process.env.CONCURRENCY || '10'),
266
- metricsEnabled: process.env.METRICS_ENABLED === 'true',
267
- },
268
- };
269
-
270
- // ============================================================================
271
- // MARKETPLACE API CLIENTS
272
- // ============================================================================
273
-
274
- class AmazonAPIClient {
275
- private client: AxiosInstance;
276
- private accessToken?: string;
277
- private tokenExpiry?: Date;
278
-
279
- constructor(
280
- private config: typeof config.amazon,
281
- private logger: StructuredLogger
282
- ) {
283
- this.client = axios.create({
284
- baseURL: 'https://sellingpartnerapi-na.amazon.com',
285
- timeout: 30000,
286
- });
287
- }
288
-
289
- async ensureAuthenticated(): Promise<void> {
290
- if (this.accessToken && this.tokenExpiry && new Date() < this.tokenExpiry) {
291
- return; // Token still valid
292
- }
293
-
294
- this.logger.info('Refreshing Amazon SP-API access token');
295
-
296
- const response = await axios.post('https://api.amazon.com/auth/o2/token', {
297
- grant_type: 'refresh_token',
298
- refresh_token: this.config.refreshToken,
299
- client_id: this.config.clientId,
300
- client_secret: this.config.clientSecret,
301
- });
302
-
303
- this.accessToken = response.data.access_token;
304
- this.tokenExpiry = new Date(Date.now() + response.data.expires_in * 1000);
305
-
306
- this.logger.info('Amazon SP-API token refreshed successfully');
307
- }
308
-
309
- async updateInventory(sku: string, quantity: number): Promise<void> {
310
- await this.ensureAuthenticated();
311
-
312
- const payload = {
313
- marketplaceId: this.config.marketplaceId,
314
- sellerId: this.config.sellerId,
315
- feeds: [
316
- {
317
- feedType: 'POST_INVENTORY_AVAILABILITY_DATA',
318
- feedOptions: {
319
- encoding: 'UTF-8',
320
- },
321
- feedContent: this.buildInventoryFeedXml(sku, quantity),
322
- },
323
- ],
324
- };
325
-
326
- await this.client.post('/feeds/2021-06-30/feeds', payload, {
327
- headers: {
328
- 'x-amz-access-token': this.accessToken,
329
- 'Content-Type': 'application/json',
330
- },
331
- });
332
- }
333
-
334
- private buildInventoryFeedXml(sku: string, quantity: number): string {
335
- return `<?xml version="1.0" encoding="UTF-8"?>
336
- <AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
337
- <Header>
338
- <DocumentVersion>1.01</DocumentVersion>
339
- <MerchantIdentifier>${this.config.sellerId}</MerchantIdentifier>
340
- </Header>
341
- <MessageType>Inventory</MessageType>
342
- <Message>
343
- <MessageID>1</MessageID>
344
- <OperationType>Update</OperationType>
345
- <Inventory>
346
- <SKU>${sku}</SKU>
347
- <Quantity>${quantity}</Quantity>
348
- <FulfillmentLatency>2</FulfillmentLatency>
349
- </Inventory>
350
- </Message>
351
- </AmazonEnvelope>`;
352
- }
353
- }
354
-
355
- class eBayAPIClient {
356
- private client: AxiosInstance;
357
-
358
- constructor(
359
- private config: typeof config.ebay,
360
- private logger: StructuredLogger
361
- ) {
362
- this.client = axios.create({
363
- baseURL: 'https://api.ebay.com/ws/api.dll',
364
- timeout: 30000,
365
- });
366
- }
367
-
368
- async updateInventory(sku: string, quantity: number): Promise<void> {
369
- const xmlRequest = `<?xml version="1.0" encoding="utf-8"?>
370
- <ReviseInventoryStatusRequest xmlns="urn:ebay:apis:eBLBaseComponents">
371
- <RequesterCredentials>
372
- <eBayAuthToken>${this.config.authToken}</eBayAuthToken>
373
- </RequesterCredentials>
374
- <InventoryStatus>
375
- <SKU>${sku}</SKU>
376
- <Quantity>${quantity}</Quantity>
377
- </InventoryStatus>
378
- </ReviseInventoryStatusRequest>`;
379
-
380
- await this.client.post('', xmlRequest, {
381
- headers: {
382
- 'X-EBAY-API-SITEID': this.config.siteId,
383
- 'X-EBAY-API-COMPATIBILITY-LEVEL': '967',
384
- 'X-EBAY-API-CALL-NAME': 'ReviseInventoryStatus',
385
- 'Content-Type': 'text/xml',
386
- },
387
- });
388
- }
389
- }
390
-
391
- class WalmartAPIClient {
392
- private client: AxiosInstance;
393
- private accessToken?: string;
394
- private tokenExpiry?: Date;
395
-
396
- constructor(
397
- private config: typeof config.walmart,
398
- private logger: StructuredLogger
399
- ) {
400
- this.client = axios.create({
401
- baseURL: 'https://marketplace.walmartapis.com/v3',
402
- timeout: 30000,
403
- });
404
- }
405
-
406
- async ensureAuthenticated(): Promise<void> {
407
- if (this.accessToken && this.tokenExpiry && new Date() < this.tokenExpiry) {
408
- return;
409
- }
410
-
411
- this.logger.info('Refreshing Walmart Marketplace access token');
412
-
413
- const credentials = Buffer.from(`${this.config.clientId}:${this.config.clientSecret}`).toString(
414
- 'base64'
415
- );
416
-
417
- const response = await axios.post(
418
- 'https://marketplace.walmartapis.com/v3/token',
419
- 'grant_type=client_credentials',
420
- {
421
- headers: {
422
- Authorization: `Basic ${credentials}`,
423
- 'Content-Type': 'application/x-www-form-urlencoded',
424
- 'WM_SVC.NAME': 'Walmart Marketplace',
425
- 'WM_QOS.CORRELATION_ID': Date.now().toString(),
426
- },
427
- }
428
- );
429
-
430
- this.accessToken = response.data.access_token;
431
- this.tokenExpiry = new Date(Date.now() + response.data.expires_in * 1000);
432
-
433
- this.logger.info('Walmart access token refreshed successfully');
434
- }
435
-
436
- async updateInventory(sku: string, quantity: number): Promise<void> {
437
- await this.ensureAuthenticated();
438
-
439
- const payload = {
440
- sku,
441
- quantity: {
442
- unit: 'EACH',
443
- amount: quantity,
444
- },
445
- };
446
-
447
- await this.client.put(`/inventory?sku=${sku}`, payload, {
448
- headers: {
449
- 'WM_SEC.ACCESS_TOKEN': this.accessToken,
450
- 'WM_SVC.NAME': 'Walmart Marketplace',
451
- 'WM_QOS.CORRELATION_ID': Date.now().toString(),
452
- 'Content-Type': 'application/json',
453
- },
454
- });
455
- }
456
- }
457
-
458
- // ============================================================================
459
- // MULTI-CHANNEL INVENTORY SYNCHRONIZER
460
- // ============================================================================
461
-
462
- class MultiChannelInventorySync {
463
- private fluentClient: FluentClient;
464
- private logger: StructuredLogger;
465
- private channels: Map<string, ChannelConfig> = new Map();
466
- private metrics: SyncMetrics;
467
-
468
- constructor() {
469
- this.logger = toStructuredLogger(createConsoleLogger(), { logLevel: 'info' });
470
-
471
- this.metrics = {
472
- startTime: new Date(),
473
- totalSKUs: 0,
474
- successfulUpdates: 0,
475
- failedUpdates: 0,
476
- skippedUpdates: 0,
477
- errors: [],
478
- rateLimitHits: 0,
479
- avgResponseTime: 0,
480
- };
481
- }
482
-
483
- async initialize(): Promise<void> {
484
- this.logger.info('Initializing Multi-Channel Inventory Sync');
485
-
486
- // Initialize Fluent Commerce client
487
- this.fluentClient = await createClient({ config: config.fluent });
488
-
489
- // Initialize marketplace API clients
490
- if (config.amazon.enabled) {
491
- const amazonClient = new AmazonAPIClient(config.amazon, this.logger);
492
- this.channels.set('amazon', {
493
- enabled: true,
494
- apiClient: amazonClient as any,
495
- bufferStock: config.amazon.bufferStock,
496
- rateLimit: config.amazon.rateLimit,
497
- });
498
- this.logger.info('Amazon SP-API client initialized');
499
- }
500
-
501
- if (config.ebay.enabled) {
502
- const ebayClient = new eBayAPIClient(config.ebay, this.logger);
503
- this.channels.set('ebay', {
504
- enabled: true,
505
- apiClient: ebayClient as any,
506
- bufferStock: config.ebay.bufferStock,
507
- rateLimit: config.ebay.rateLimit,
508
- });
509
- this.logger.info('eBay Trading API client initialized');
510
- }
511
-
512
- if (config.walmart.enabled) {
513
- const walmartClient = new WalmartAPIClient(config.walmart, this.logger);
514
- this.channels.set('walmart', {
515
- enabled: true,
516
- apiClient: walmartClient as any,
517
- bufferStock: config.walmart.bufferStock,
518
- rateLimit: config.walmart.rateLimit,
519
- });
520
- this.logger.info('Walmart Marketplace API client initialized');
521
- }
522
-
523
- this.logger.info(`Initialized ${this.channels.size} marketplace channels`);
524
- }
525
-
526
- async syncInventory(): Promise<void> {
527
- this.logger.info('Starting multi-channel inventory sync');
528
- this.metrics.startTime = new Date();
529
-
530
- try {
531
- // Step 1: Fetch all ATP inventory from Fluent Commerce
532
- const inventory = await this.fetchFluentInventory();
533
- this.metrics.totalSKUs = inventory.length;
534
-
535
- this.logger.info(`Fetched ${inventory.length} inventory positions from Fluent`);
536
-
537
- // Step 2: Calculate ATP for each channel with buffer stock
538
- const channelInventory = this.calculateChannelInventory(inventory);
539
-
540
- // Step 3: Update each marketplace in parallel with rate limiting
541
- await this.updateMarketplaces(channelInventory);
542
-
543
- this.metrics.endTime = new Date();
544
- this.logMetrics();
545
-
546
- this.logger.info('Multi-channel inventory sync completed successfully');
547
- } catch (error: any) {
548
- this.logger.error('Multi-channel inventory sync failed', error);
549
- throw error;
550
- }
551
- }
552
-
553
- private async fetchFluentInventory(): Promise<InventoryPosition[]> {
554
- const query = `
555
- query GetInventory($retailerId: ID!, $first: Int!, $after: String) {
556
- inventoryQuantities(
557
- first: $first
558
- after: $after
559
- retailerId: $retailerId
560
- type: "AVAILABLE"
561
- ) {
562
- edges {
563
- node {
564
- productRef
565
- locationRef
566
- quantity
567
- onHand
568
- available
569
- reserved
570
- }
571
- cursor
572
- }
573
- pageInfo {
574
- hasNextPage
575
- }
576
- }
577
- }
578
- `;
579
-
580
- const result = await this.fluentClient.graphql({
581
- query,
582
- variables: {
583
- retailerId: config.fluent.retailerId,
584
- first: 250,
585
- },
586
- pagination: {
587
- maxPages: 500,
588
- },
589
- });
590
-
591
- if (result.errors) {
592
- throw new Error(`GraphQL errors: ${JSON.stringify(result.errors)}`);
593
- }
594
-
595
- const edges = (result.data as any).inventoryQuantities?.edges || [];
596
- return edges.map((edge: any) => edge.node);
597
- }
598
-
599
- private calculateChannelInventory(
600
- inventory: InventoryPosition[]
601
- ): Map<string, Map<string, number>> {
602
- const channelInventory = new Map<string, Map<string, number>>();
603
-
604
- for (const [channelName, channelConfig] of this.channels) {
605
- const skuQuantities = new Map<string, number>();
606
-
607
- for (const position of inventory) {
608
- const atpQuantity = position.available || 0;
609
- const channelQuantity = Math.max(0, atpQuantity - channelConfig.bufferStock);
610
- skuQuantities.set(position.productRef, channelQuantity);
611
- }
612
-
613
- channelInventory.set(channelName, skuQuantities);
614
- }
615
-
616
- return channelInventory;
617
- }
618
-
619
- private async updateMarketplaces(
620
- channelInventory: Map<string, Map<string, number>>
621
- ): Promise<void> {
622
- const updatePromises: Promise<void>[] = [];
623
-
624
- for (const [channelName, skuQuantities] of channelInventory) {
625
- const channelConfig = this.channels.get(channelName)!;
626
- const limit = pLimit(channelConfig.rateLimit);
627
-
628
- const channelPromises = Array.from(skuQuantities.entries()).map(([sku, quantity]) =>
629
- limit(async () => {
630
- try {
631
- const startTime = Date.now();
632
-
633
- if (channelName === 'amazon') {
634
- await (channelConfig.apiClient as any).updateInventory(sku, quantity);
635
- } else if (channelName === 'ebay') {
636
- await (channelConfig.apiClient as any).updateInventory(sku, quantity);
637
- } else if (channelName === 'walmart') {
638
- await (channelConfig.apiClient as any).updateInventory(sku, quantity);
639
- }
640
-
641
- const duration = Date.now() - startTime;
642
- this.metrics.successfulUpdates++;
643
-
644
- this.logger.debug(`Updated ${channelName} inventory for ${sku}: ${quantity}`, {
645
- duration,
646
- });
647
- } catch (error: any) {
648
- this.metrics.failedUpdates++;
649
- this.metrics.errors.push({
650
- sku,
651
- channel: channelName,
652
- error: error.message,
653
- });
654
-
655
- if (error.response?.status === 429) {
656
- this.metrics.rateLimitHits++;
657
- }
658
-
659
- this.logger.warn(`Failed to update ${channelName} inventory for ${sku}`, {
660
- error: error.message,
661
- status: error.response?.status,
662
- });
663
- }
664
- })
665
- );
666
-
667
- updatePromises.push(...channelPromises);
668
- }
669
-
670
- await Promise.all(updatePromises);
671
- }
672
-
673
- private logMetrics(): void {
674
- if (!config.processing.metricsEnabled) return;
675
-
676
- const duration = this.metrics.endTime
677
- ? (this.metrics.endTime.getTime() - this.metrics.startTime.getTime()) / 1000
678
- : 0;
679
-
680
- this.logger.info('='.repeat(80));
681
- this.logger.info('SYNC METRICS', {
682
- duration: `${duration.toFixed(2)}s`,
683
- totalSKUs: this.metrics.totalSKUs,
684
- successfulUpdates: this.metrics.successfulUpdates,
685
- failedUpdates: this.metrics.failedUpdates,
686
- skippedUpdates: this.metrics.skippedUpdates,
687
- successRate: `${((this.metrics.successfulUpdates / (this.metrics.successfulUpdates + this.metrics.failedUpdates)) * 100).toFixed(2)}%`,
688
- rateLimitHits: this.metrics.rateLimitHits,
689
- errorCount: this.metrics.errors.length,
690
- });
691
-
692
- if (this.metrics.errors.length > 0) {
693
- this.logger.warn('Error summary (first 10):', {
694
- errors: this.metrics.errors.slice(0, 10),
695
- });
696
- }
697
-
698
- this.logger.info('='.repeat(80));
699
- }
700
- }
701
-
702
- // ============================================================================
703
- // MAIN ENTRY POINT
704
- // ============================================================================
705
-
706
- async function main() {
707
- const sync = new MultiChannelInventorySync();
708
-
709
- try {
710
- await sync.initialize();
711
- await sync.syncInventory();
712
-
713
- console.log('Multi-channel inventory sync completed successfully');
714
- process.exit(0);
715
- } catch (error: any) {
716
- console.error('Fatal error:', error);
717
- process.exit(1);
718
- }
719
- }
720
-
721
- // Run if executed directly
722
- if (require.main === module) {
723
- main();
724
- }
725
-
726
- export { MultiChannelInventorySync };
727
- ```
728
-
729
- ---
730
-
731
- ## Key Patterns Explained
732
-
733
- ### Pattern 1: GraphQL Auto-Pagination for Large Datasets
734
-
735
- **Challenge**: Efficiently fetch 10k-100k inventory positions without manual pagination logic
736
-
737
- **Solution**: Use SDK's built-in auto-pagination with progress callbacks
738
-
739
- ```javascript
740
- const result = await fluentClient.graphql({
741
- query,
742
- variables: { retailerId, first: 200 },
743
- pagination: {
744
- maxRecords: 100000,
745
- maxPages: 500,
746
- },
747
- });
748
- ```
749
-
750
- **Why This Works**:
751
-
752
- - **Automatic**: No manual cursor tracking needed
753
- - **Safe**: Built-in protections against infinite loops
754
- - **Efficient**: Streams data as it's received
755
- - **Observable**: Progress callbacks for monitoring
756
-
757
- ### Pattern 2: ATP Aggregation with Location Rollup
758
-
759
- **Challenge**: Calculate total Available-to-Promise across multiple warehouses/stores per SKU
760
-
761
- **Solution**: Map-based aggregation with location tracking
762
-
763
- ```javascript
764
- function aggregateATP(inventoryPositions) {
765
- const atpMap = new Map();
766
- for (const position of inventoryPositions) {
767
- const sku = position.productRef;
768
- const availableQty = Math.max(0, position.availableQty || 0);
769
-
770
- if (!atpMap.has(sku)) {
771
- atpMap.set(sku, {
772
- sku,
773
- totalATP: 0,
774
- locations: [],
775
- lastUpdated: position.updatedOn,
776
- });
777
- }
778
-
779
- const aggregated = atpMap.get(sku);
780
- aggregated.totalATP += availableQty;
781
- aggregated.locations.push({
782
- locationRef: position.locationRef,
783
- availableQty: availableQty,
784
- });
785
- }
786
- return atpMap;
787
- }
788
- ```
789
-
790
- **Why This Works**:
791
-
792
- - **O(n) complexity**: Single pass through inventory
793
- - **Location visibility**: Track which locations contribute to total
794
- - **Negative protection**: `Math.max(0, ...)` prevents negative ATP
795
- - **Timestamp tracking**: Know when inventory was last updated
796
-
797
- ### Pattern 3: Marketplace-Specific Buffer Stock
798
-
799
- **Challenge**: Different marketplaces need different safety buffers to prevent overselling
800
-
801
- **Solution**: Configurable buffer per marketplace
802
-
803
- ```javascript
804
- // Configuration
805
- const buffers = {
806
- amazon: 5, // Lower buffer (fast fulfillment)
807
- ebay: 3, // Moderate buffer
808
- walmart: 10, // Higher buffer (longer fulfillment)
809
- };
810
-
811
- // Application
812
- function applyBufferStock(totalATP, bufferStock) {
813
- return Math.max(0, totalATP - bufferStock);
814
- }
815
-
816
- // Example: SKU with 50 ATP across all locations
817
- const amazonQty = applyBufferStock(50, 5); // 45 available on Amazon
818
- const ebayQty = applyBufferStock(50, 3); // 47 available on eBay
819
- const walmartQty = applyBufferStock(50, 10); // 40 available on Walmart
820
- ```
821
-
822
- **Why This Works**:
823
-
824
- - **Oversell prevention**: Accounts for sync delays and processing time
825
- - **Marketplace flexibility**: Different risk profiles per marketplace
826
- - **Safety floor**: `Math.max(0, ...)` ensures quantity never goes negative
827
- - **Configurable**: Easy to adjust per marketplace requirements
828
-
829
- ### Pattern 4: Parallel Marketplace Updates with Rate Limiting
830
-
831
- **Challenge**: Update multiple marketplaces efficiently without exceeding API rate limits
832
-
833
- **Solution**: Parallel execution with per-marketplace rate limiters
834
-
835
- ```javascript
836
- import pLimit from 'p-limit';
837
-
838
- // Each marketplace has its own rate limiter
839
- class AmazonMarketplace {
840
- constructor(config) {
841
- this.limiter = pLimit(config.rateLimit); // 10 req/sec
842
- }
843
-
844
- async updateInventory(sku, quantity) {
845
- // Rate-limited execution
846
- return this.limiter(() => this.makeApiCall(sku, quantity));
847
- }
848
- }
849
-
850
- // Parallel sync across all marketplaces
851
- const syncResults = await Promise.all(
852
- marketplaces.map(marketplace => marketplace.syncInventory(atpMap))
853
- );
854
- ```
855
-
856
- **Why This Works**:
857
-
858
- - **Parallel execution**: All marketplaces sync simultaneously
859
- - **Independent rate limits**: Each marketplace respects its own limits
860
- - **Error isolation**: Failure in one marketplace doesn't affect others
861
- - **Concurrency control**: p-limit prevents overwhelming APIs
862
-
863
- ### Pattern 5: Exponential Backoff Retry Strategy
864
-
865
- **Challenge**: Handle transient API failures (429 rate limits, 500 server errors)
866
-
867
- **Solution**: p-retry with exponential backoff
868
-
869
- ```javascript
870
- import pRetry from 'p-retry';
871
-
872
- async updateInventory(sku, quantity) {
873
- return pRetry(
874
- async () => {
875
- // Attempt API call
876
- const response = await axios.put(endpoint, payload);
877
-
878
- // Check for retryable errors
879
- if (response.status === 429) {
880
- throw new Error('Rate limit exceeded'); // Will retry
881
- }
882
-
883
- return response.data;
884
- },
885
- {
886
- retries: 3,
887
- factor: 2, // Exponential backoff factor
888
- minTimeout: 1000, // 1s, 2s, 4s delays
889
- onFailedAttempt: error => {
890
- logger.warn(`Retry attempt ${error.attemptNumber}`, {
891
- retriesLeft: error.retriesLeft,
892
- });
893
- },
894
- }
895
- );
896
- }
897
- ```
898
-
899
- **Why This Works**:
900
-
901
- - **Transient failure recovery**: Handles temporary API issues
902
- - **Exponential backoff**: Reduces load on overloaded APIs
903
- - **Configurable retries**: 3 attempts is reasonable for most cases
904
- - **Observable**: Logs each retry attempt for debugging
905
-
906
- ### Pattern 6: SLA Tracking and Compliance
907
-
908
- **Challenge**: Ensure sync completes within 15-minute SLA requirement
909
-
910
- **Solution**: Duration tracking with SLA compliance check
911
-
912
- ```javascript
913
- function checkSLA(durationMs) {
914
- const durationMinutes = durationMs / 60000;
915
- const slaThreshold = 15; // 15-minute requirement
916
- const slaMet = durationMinutes <= slaThreshold;
917
-
918
- if (!slaMet) {
919
- logger.warn('SLA BREACH: Sync exceeded threshold', {
920
- durationMinutes: durationMinutes.toFixed(2),
921
- threshold: slaThreshold,
922
- });
923
- metrics.increment('sla_breaches');
924
- // Alert via PagerDuty, Slack, etc.
925
- }
926
-
927
- return slaMet;
928
- }
929
- ```
930
-
931
- **Why This Works**:
932
-
933
- - **Clear threshold**: 15 minutes is measurable and actionable
934
- - **Automated detection**: No manual checking needed
935
- - **Alerting hook**: Can trigger notifications on breach
936
- - **Metrics tracking**: Historical SLA compliance data
937
-
938
- ### Pattern 7: Dry-Run Mode for Safe Testing
939
-
940
- **Challenge**: Test sync logic without actually updating marketplaces
941
-
942
- **Solution**: Dry-run flag that short-circuits API calls
943
-
944
- ```javascript
945
- async updateInventory(sku, quantity, dryRun = false) {
946
- if (dryRun) {
947
- this.logger.info(`[DRY RUN] Would update inventory`, { sku, quantity });
948
- return { success: true, sku, quantity, dryRun: true };
949
- }
950
-
951
- // Real API call
952
- return this.makeApiCall(sku, quantity);
953
- }
954
-
955
- // Usage
956
- npm run sync:dry-run
957
- ```
958
-
959
- **Why This Works**:
960
-
961
- - **Safe testing**: Validate logic without side effects
962
- - **End-to-end flow**: Tests everything except final API call
963
- - **Easy toggle**: Environment variable or CLI flag
964
- - **Visible logging**: Clear indication of dry-run mode
965
-
966
- ---
967
-
968
- ## Testing
969
-
970
- ### Dry-Run Test
971
-
972
- ```bash
973
- # Test sync without updating marketplaces
974
- DRY_RUN=true npm run sync:once
975
-
976
- # Expected output:
977
- # [DRY RUN] Would update Amazon inventory { sku: 'PROD-001', quantity: 45 }
978
- # [DRY RUN] Would update eBay inventory { sku: 'PROD-001', quantity: 47 }
979
- # [DRY RUN] Would update Walmart inventory { sku: 'PROD-001', quantity: 40 }
980
- ```
981
-
982
- ### Single Sync Execution
983
-
984
- ```bash
985
- # Run once and exit
986
- npm run sync:once
987
-
988
- # Check logs
989
- cat logs/inventory-sync.log | grep "COMPLETE"
990
- ```
991
-
992
- ### Continuous Sync Mode
993
-
994
- ```bash
995
- # Run continuously (every 15 minutes)
996
- npm run sync:continuous
997
-
998
- # Check next sync time in logs
999
- ```
1000
-
1001
- ---
1002
-
1003
- ## Deployment Options
1004
-
1005
- ### Option 1: Docker Container
1006
-
1007
- Create `Dockerfile`:
1008
-
1009
- ```dockerfile
1010
- FROM node:18-alpine
1011
-
1012
- WORKDIR /app
1013
-
1014
- # Copy package files
1015
- COPY package*.json ./
1016
-
1017
- # Install dependencies
1018
- RUN npm ci --only=production
1019
-
1020
- # Copy application code
1021
- COPY src ./src
1022
-
1023
- # Create state directory
1024
- RUN mkdir -p /app/state
1025
-
1026
- # Run continuous sync
1027
- CMD ["node", "src/index.js"]
1028
- ```
1029
-
1030
- Build and run:
1031
-
1032
- ```bash
1033
- # Build image
1034
- docker build -t multi-channel-sync .
1035
-
1036
- # Run container
1037
- docker run -d \
1038
- --name inventory-sync \
1039
- --env-file .env \
1040
- --restart unless-stopped \
1041
- --volume ./state:/app/state \
1042
- multi-channel-sync
1043
- ```
1044
-
1045
- ### Option 2: AWS ECS Task
1046
-
1047
- Create `ecs-task-definition.json`:
1048
-
1049
- ```json
1050
- {
1051
- "family": "multi-channel-inventory-sync",
1052
- "networkMode": "awsvpc",
1053
- "requiresCompatibilities": ["FARGATE"],
1054
- "cpu": "1024",
1055
- "memory": "2048",
1056
- "containerDefinitions": [
1057
- {
1058
- "name": "inventory-sync",
1059
- "image": "your-registry/multi-channel-sync:latest",
1060
- "essential": true,
1061
- "environment": [
1062
- { "name": "LOG_LEVEL", "value": "info" },
1063
- { "name": "SYNC_INTERVAL_MINUTES", "value": "15" }
1064
- ],
1065
- "secrets": [
1066
- {
1067
- "name": "FLUENT_CLIENT_ID",
1068
- "valueFrom": "arn:aws:secretsmanager:us-east-1:123:secret:fluent-client-id"
1069
- }
1070
- ],
1071
- "logConfiguration": {
1072
- "logDriver": "awslogs",
1073
- "options": {
1074
- "awslogs-group": "/ecs/inventory-sync",
1075
- "awslogs-region": "us-east-1",
1076
- "awslogs-stream-prefix": "ecs"
1077
- }
1078
- }
1079
- }
1080
- ]
1081
- }
1082
- ```
1083
-
1084
- Deploy:
1085
-
1086
- ```bash
1087
- aws ecs register-task-definition --cli-input-json file://ecs-task-definition.json
1088
- aws ecs create-service \
1089
- --cluster production \
1090
- --service-name inventory-sync \
1091
- --task-definition multi-channel-inventory-sync \
1092
- --desired-count 1 \
1093
- --launch-type FARGATE
1094
- ```
1095
-
1096
- ---
1097
-
1098
- ## Common Issues & Solutions
1099
-
1100
- ### Issue 1: SLA Breach (Sync Takes >15 Minutes)
1101
-
1102
- **Symptoms**:
1103
-
1104
- - Log shows "SLA BREACH" warning
1105
- - Sync duration exceeds 15 minutes
1106
-
1107
- **Solutions**:
1108
-
1109
- 1. **Reduce page size** (faster initial response):
1110
-
1111
- ```javascript
1112
- variables: {
1113
- first: 100;
1114
- } // Instead of 200
1115
- ```
1116
-
1117
- 2. **Increase parallelism**:
1118
-
1119
- ```javascript
1120
- const limiter = pLimit(20); // Increase from 10
1121
- ```
1122
-
1123
- 3. **Optimize marketplace rate limits** (if APIs allow):
1124
-
1125
- ```bash
1126
- AMAZON_RATE_LIMIT=20 # Increase from 10
1127
- ```
1128
-
1129
- 4. **Split sync by marketplace** (run separately):
1130
-
1131
- ```bash
1132
- AMAZON_ENABLED=true EBAY_ENABLED=false WALMART_ENABLED=false npm run sync:once
1133
- ```
1134
-
1135
- ---
1136
-
1137
- ## Related Guides
1138
-
1139
- - **GraphQL Query Export**: [`./graphql-query-export.md`](./graphql-query-export.md) - GraphQL pagination patterns
1140
- - **Multi-Source Aggregation**: `./04-multi-source-aggregation.md` - Data aggregation strategies
1141
- - **Error Handling Patterns**: `../../03-PATTERN-GUIDES/error-handling/readme.md` - Retry and error handling
1142
- - **Universal Mapping Guide**: `../../02-CORE-GUIDES/mapping/readme.md` - Field transformations
1143
- - **SDK API Reference**: `../../readme.md` - Core SDK documentation
1144
-
1145
- ---
1146
-
1147
- ## Production Checklist
1148
-
1149
- Before deploying to production:
1150
-
1151
- - [ ] All marketplace credentials secured (AWS Secrets Manager, Vault)
1152
- - [ ] Rate limits configured per marketplace API documentation
1153
- - [ ] Buffer stock values tested and approved by business
1154
- - [ ] SLA threshold aligned with business requirements
1155
- - [ ] Monitoring dashboards created (sync duration, SLA compliance, error rates)
1156
- - [ ] Alerting configured (PagerDuty, Slack, email)
1157
- - [ ] Dry-run testing completed with production data
1158
- - [ ] Load testing with 100k+ SKUs
1159
- - [ ] State management enabled to prevent duplicate processing
1160
- - [ ] Logging configured (CloudWatch, Datadog, Splunk)
1161
- - [ ] Error tracking integrated (Sentry, Rollbar)
1162
- - [ ] Documentation updated with runbooks
1163
- - [ ] On-call team trained on troubleshooting
1164
- - [ ] Disaster recovery plan documented
1165
- - [ ] Metrics baseline established (average sync duration, success rate)
1166
-
1167
- ---
1168
-
1169
- **Next Steps**:
1170
-
1171
- 1. Customize buffer stock values per marketplace and product category
1172
- 2. Implement incremental sync (only process changed inventory)
1173
- 3. Add webhook integration for real-time inventory updates
1174
- 4. Set up monitoring dashboards (Grafana, Datadog)
1175
- 5. Integrate with incident management (PagerDuty)
1176
- 6. Add marketplace-specific SKU mapping (Fluent SKU → Marketplace SKU)
1177
- 7. Implement A/B testing for buffer stock optimization
1178
-
1179
- **Support**:
1180
-
1181
- - SDK Issues: https://github.com/fluentcommerce/fc-connect-sdk/issues
1182
- - Fluent Commerce API: https://docs.fluentcommerce.com
1183
- - Amazon SP-API: https://developer-docs.amazon.com/sp-api/
1184
- - eBay Trading API: https://developer.ebay.com/devzone/xml/docs/reference/ebay/
1185
- - Walmart Seller API: https://developer.walmart.com/
1
+ # Standalone: Multi-Channel Inventory Sync (Real-Time ATP to Marketplaces)
2
+
3
+ **FC Connect SDK Use Case Guide**
4
+
5
+ > **SDK**: [@fluentcommerce/fc-connect-sdk](https://www.npmjs.com/package/@fluentcommerce/fc-connect-sdk)
6
+ > **Version**: Use latest - `npm install @fluentcommerce/fc-connect-sdk@latest`
7
+
8
+ **Context**: Node.js script that aggregates Available-to-Promise (ATP) inventory from Fluent Commerce and pushes real-time updates to multiple marketplaces (Amazon, eBay, Walmart)
9
+
10
+ **Complexity**: High
11
+
12
+ **Runtime**: Node.js >=18
13
+
14
+ **Estimated Lines**: ~950 lines
15
+
16
+ **Volume**: Large (10k-100k SKUs, multiple marketplaces)
17
+
18
+ **Latency**: Near real-time (every 5-15 min)
19
+
20
+ **Pattern**: GraphQL pagination → external marketplace APIs
21
+
22
+ ## What You'll Build
23
+
24
+ - OAuth2-authenticated Fluent Commerce client
25
+ - GraphQL query with auto-pagination for inventory positions
26
+ - ATP (Available-to-Promise) aggregation across multiple locations
27
+ - Marketplace-specific buffer stock calculations
28
+ - Parallel marketplace updates with rate limiting:
29
+ - Amazon MWS/SP-API integration
30
+ - eBay Trading API integration
31
+ - Walmart Seller API integration
32
+ - Per-marketplace error handling and retry logic
33
+ - SLA tracking (15-minute sync requirement)
34
+ - Comprehensive metrics and logging
35
+ - Dry-run mode for testing
36
+ - State management to prevent duplicate updates
37
+
38
+ ## SDK Methods Used
39
+
40
+ - `createClient({ config: { baseUrl, clientId, clientSecret, retailerId } })` - OAuth2 client
41
+ - `client.graphql({ query, variables, pagination })` - Query with auto-pagination
42
+ - `UniversalMapper(mappingConfig)` - Transform Fluent data to marketplace formats
43
+ - `createConsoleLogger()` - Simple console logger
44
+ - `toStructuredLogger(logger, context)` - Add context to logs
45
+ - `generateCorrelationId()` - Generate unique correlation IDs
46
+ - State tracking for incremental updates
47
+
48
+ ---
49
+
50
+ ## Complete Working Implementation
51
+
52
+ ### 1. Project Setup
53
+
54
+ ```bash
55
+ # Create project directory
56
+ mkdir multi-channel-inventory-sync
57
+ cd multi-channel-inventory-sync
58
+
59
+ # Initialize Node.js project
60
+ npm init -y
61
+
62
+ # Install dependencies
63
+ npm install @fluentcommerce/fc-connect-sdk dotenv axios p-limit p-retry
64
+ ```
65
+
66
+ ### 2. Environment Configuration
67
+
68
+ Create `.env` file:
69
+
70
+ ```bash
71
+ # Fluent Commerce OAuth2
72
+ FLUENT_BASE_URL=https://api.fluentcommerce.com
73
+ FLUENT_CLIENT_ID=your-oauth2-client-id
74
+ FLUENT_CLIENT_SECRET=your-oauth2-client-secret
75
+ FLUENT_RETAILER_ID=your-retailer-id
76
+
77
+ # Sync Configuration
78
+ SYNC_INTERVAL_MINUTES=15
79
+ SLA_THRESHOLD_MINUTES=15
80
+ MAX_RECORDS_PER_SYNC=100000
81
+ DRY_RUN=false
82
+
83
+ # Amazon SP-API Credentials
84
+ AMAZON_ENABLED=true
85
+ AMAZON_MARKETPLACE_ID=ATVPDKIKX0DER
86
+ AMAZON_SELLER_ID=your-amazon-seller-id
87
+ AMAZON_REFRESH_TOKEN=your-amazon-refresh-token
88
+ AMAZON_CLIENT_ID=amzn1.application-oa2-client.xxxxx
89
+ AMAZON_CLIENT_SECRET=your-amazon-client-secret
90
+ AMAZON_AWS_ACCESS_KEY_ID=your-aws-access-key
91
+ AMAZON_AWS_SECRET_ACCESS_KEY=your-aws-secret-key
92
+ AMAZON_REGION=us-east-1
93
+ AMAZON_ROLE_ARN=arn:aws:iam::123456789:role/SellingPartnerAPI
94
+ AMAZON_BUFFER_STOCK=5
95
+ AMAZON_RATE_LIMIT=10
96
+
97
+ # eBay Trading API Credentials
98
+ EBAY_ENABLED=true
99
+ EBAY_APP_ID=your-ebay-app-id
100
+ EBAY_DEV_ID=your-ebay-dev-id
101
+ EBAY_CERT_ID=your-ebay-cert-id
102
+ EBAY_AUTH_TOKEN=your-ebay-auth-token
103
+ EBAY_SITE_ID=0
104
+ EBAY_SANDBOX=false
105
+ EBAY_BUFFER_STOCK=3
106
+ EBAY_RATE_LIMIT=5
107
+
108
+ # Walmart Seller API Credentials
109
+ WALMART_ENABLED=true
110
+ WALMART_CLIENT_ID=your-walmart-client-id
111
+ WALMART_CLIENT_SECRET=your-walmart-client-secret
112
+ WALMART_CHANNEL_TYPE=0a7d6c3e-e9a0-4a0c-8d6a-f6c6f1e7a5c7
113
+ WALMART_BUFFER_STOCK=10
114
+ WALMART_RATE_LIMIT=20
115
+
116
+ # Logging
117
+ LOG_LEVEL=info
118
+ METRICS_ENABLED=true
119
+ ```
120
+
121
+ ### 3. Package Configuration
122
+
123
+ Create `package.json`:
124
+
125
+ ```json
126
+ {
127
+ "name": "multi-channel-inventory-sync",
128
+ "version": "1.0.0",
129
+ "type": "module",
130
+ "description": "Real-time ATP inventory sync from Fluent Commerce to multiple marketplaces",
131
+ "main": "src/index.js",
132
+ "scripts": {
133
+ "start": "node src/index.js",
134
+ "sync:once": "node src/index.js --once",
135
+ "sync:continuous": "node src/index.js",
136
+ "sync:dry-run": "DRY_RUN=true node src/index.js --once",
137
+ "test": "node --test tests/**/*.test.js"
138
+ },
139
+ "dependencies": {
140
+ "@fluentcommerce/fc-connect-sdk": "^0.1.39",
141
+ "axios": "^1.6.0",
142
+ "dotenv": "^16.0.0",
143
+ "p-limit": "^5.0.0",
144
+ "p-retry": "^6.0.0"
145
+ },
146
+ "devDependencies": {
147
+ "@types/node": "^20.0.0"
148
+ },
149
+ "engines": {
150
+ "node": ">=18.0.0"
151
+ }
152
+ }
153
+ ```
154
+
155
+ ### 4. TypeScript Configuration (tsconfig.json)
156
+
157
+ ```json
158
+ {
159
+ "compilerOptions": {
160
+ "module": "ES2022",
161
+ "target": "ES2024",
162
+ "moduleResolution": "node"
163
+ }
164
+ }
165
+ ```
166
+
167
+ ### 5. Main Script Implementation (src/multi-channel-sync.ts)
168
+
169
+ > **⚠️ RUNTIME COMPATIBILITY NOTE:**
170
+ > This template includes `import { Buffer } from 'node:buffer';` for Deno/Versori compatibility.
171
+ > While Buffer is globally available in Node.js and this import is optional for Node.js-only deployments,
172
+ > including it ensures the code works across all runtimes (Node.js, Deno, Versori) without modification.
173
+
174
+ ```typescript
175
+ import 'dotenv/config';
176
+ import { Buffer } from 'node:buffer'; // Required for Deno/Versori runtime compatibility
177
+
178
+ // FC Connect SDK+
179
+ // Install: npm install @fluentcommerce/fc-connect-sdk@latest
180
+ // Docs: https://www.npmjs.com/package/@fluentcommerce/fc-connect-sdk
181
+ // GitHub: https://github.com/fluentcommerce/fc-connect-sdk
182
+
183
+ import {
184
+ createClient,
185
+ type FluentClient,
186
+ type StructuredLogger,
187
+ createConsoleLogger,
188
+ toStructuredLogger
189
+ } from '@fluentcommerce/fc-connect-sdk';
190
+
191
+ import axios, { AxiosInstance } from 'axios';
192
+ import pLimit from 'p-limit';
193
+
194
+ // ============================================================================
195
+ // TYPES & INTERFACES
196
+ // ============================================================================
197
+
198
+ interface InventoryPosition {
199
+ productRef: string;
200
+ locationRef: string;
201
+ quantity: number;
202
+ onHand: number;
203
+ available: number;
204
+ reserved: number;
205
+ }
206
+
207
+ interface ChannelConfig {
208
+ enabled: boolean;
209
+ apiClient: AxiosInstance;
210
+ bufferStock: number;
211
+ rateLimit: number;
212
+ }
213
+
214
+ interface SyncMetrics {
215
+ startTime: Date;
216
+ endTime?: Date;
217
+ totalSKUs: number;
218
+ successfulUpdates: number;
219
+ failedUpdates: number;
220
+ skippedUpdates: number;
221
+ errors: Array<{ sku: string; channel: string; error: string }>;
222
+ rateLimitHits: number;
223
+ avgResponseTime: number;
224
+ }
225
+
226
+ // ============================================================================
227
+ // CONFIGURATION
228
+ // ============================================================================
229
+
230
+ const config = {
231
+ fluent: {
232
+ baseUrl: process.env.FLUENT_BASE_URL!,
233
+ clientId: process.env.FLUENT_CLIENT_ID!,
234
+ clientSecret: process.env.FLUENT_CLIENT_SECRET!,
235
+ retailerId: process.env.FLUENT_RETAILER_ID!,
236
+ },
237
+ amazon: {
238
+ enabled: process.env.AMAZON_ENABLED === 'true',
239
+ clientId: process.env.AMAZON_CLIENT_ID!,
240
+ clientSecret: process.env.AMAZON_CLIENT_SECRET!,
241
+ refreshToken: process.env.AMAZON_REFRESH_TOKEN!,
242
+ marketplaceId: process.env.AMAZON_MARKETPLACE_ID!,
243
+ sellerId: process.env.AMAZON_SELLER_ID!,
244
+ bufferStock: parseInt(process.env.AMAZON_BUFFER_STOCK || '5'),
245
+ rateLimit: parseInt(process.env.AMAZON_RATE_LIMIT || '10'),
246
+ },
247
+ ebay: {
248
+ enabled: process.env.EBAY_ENABLED === 'true',
249
+ appId: process.env.EBAY_APP_ID!,
250
+ certId: process.env.EBAY_CERT_ID!,
251
+ authToken: process.env.EBAY_AUTH_TOKEN!,
252
+ siteId: process.env.EBAY_SITE_ID || '0',
253
+ bufferStock: parseInt(process.env.EBAY_BUFFER_STOCK || '3'),
254
+ rateLimit: parseInt(process.env.EBAY_RATE_LIMIT || '5'),
255
+ },
256
+ walmart: {
257
+ enabled: process.env.WALMART_ENABLED === 'true',
258
+ clientId: process.env.WALMART_CLIENT_ID!,
259
+ clientSecret: process.env.WALMART_CLIENT_SECRET!,
260
+ channelType: process.env.WALMART_CHANNEL_TYPE!,
261
+ bufferStock: parseInt(process.env.WALMART_BUFFER_STOCK || '10'),
262
+ rateLimit: parseInt(process.env.WALMART_RATE_LIMIT || '20'),
263
+ },
264
+ processing: {
265
+ concurrency: parseInt(process.env.CONCURRENCY || '10'),
266
+ metricsEnabled: process.env.METRICS_ENABLED === 'true',
267
+ },
268
+ };
269
+
270
+ // ============================================================================
271
+ // MARKETPLACE API CLIENTS
272
+ // ============================================================================
273
+
274
+ class AmazonAPIClient {
275
+ private client: AxiosInstance;
276
+ private accessToken?: string;
277
+ private tokenExpiry?: Date;
278
+
279
+ constructor(
280
+ private config: typeof config.amazon,
281
+ private logger: StructuredLogger
282
+ ) {
283
+ this.client = axios.create({
284
+ baseURL: 'https://sellingpartnerapi-na.amazon.com',
285
+ timeout: 30000,
286
+ });
287
+ }
288
+
289
+ async ensureAuthenticated(): Promise<void> {
290
+ if (this.accessToken && this.tokenExpiry && new Date() < this.tokenExpiry) {
291
+ return; // Token still valid
292
+ }
293
+
294
+ this.logger.info('Refreshing Amazon SP-API access token');
295
+
296
+ const response = await axios.post('https://api.amazon.com/auth/o2/token', {
297
+ grant_type: 'refresh_token',
298
+ refresh_token: this.config.refreshToken,
299
+ client_id: this.config.clientId,
300
+ client_secret: this.config.clientSecret,
301
+ });
302
+
303
+ this.accessToken = response.data.access_token;
304
+ this.tokenExpiry = new Date(Date.now() + response.data.expires_in * 1000);
305
+
306
+ this.logger.info('Amazon SP-API token refreshed successfully');
307
+ }
308
+
309
+ async updateInventory(sku: string, quantity: number): Promise<void> {
310
+ await this.ensureAuthenticated();
311
+
312
+ const payload = {
313
+ marketplaceId: this.config.marketplaceId,
314
+ sellerId: this.config.sellerId,
315
+ feeds: [
316
+ {
317
+ feedType: 'POST_INVENTORY_AVAILABILITY_DATA',
318
+ feedOptions: {
319
+ encoding: 'UTF-8',
320
+ },
321
+ feedContent: this.buildInventoryFeedXml(sku, quantity),
322
+ },
323
+ ],
324
+ };
325
+
326
+ await this.client.post('/feeds/2021-06-30/feeds', payload, {
327
+ headers: {
328
+ 'x-amz-access-token': this.accessToken,
329
+ 'Content-Type': 'application/json',
330
+ },
331
+ });
332
+ }
333
+
334
+ private buildInventoryFeedXml(sku: string, quantity: number): string {
335
+ return `<?xml version="1.0" encoding="UTF-8"?>
336
+ <AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
337
+ <Header>
338
+ <DocumentVersion>1.01</DocumentVersion>
339
+ <MerchantIdentifier>${this.config.sellerId}</MerchantIdentifier>
340
+ </Header>
341
+ <MessageType>Inventory</MessageType>
342
+ <Message>
343
+ <MessageID>1</MessageID>
344
+ <OperationType>Update</OperationType>
345
+ <Inventory>
346
+ <SKU>${sku}</SKU>
347
+ <Quantity>${quantity}</Quantity>
348
+ <FulfillmentLatency>2</FulfillmentLatency>
349
+ </Inventory>
350
+ </Message>
351
+ </AmazonEnvelope>`;
352
+ }
353
+ }
354
+
355
+ class eBayAPIClient {
356
+ private client: AxiosInstance;
357
+
358
+ constructor(
359
+ private config: typeof config.ebay,
360
+ private logger: StructuredLogger
361
+ ) {
362
+ this.client = axios.create({
363
+ baseURL: 'https://api.ebay.com/ws/api.dll',
364
+ timeout: 30000,
365
+ });
366
+ }
367
+
368
+ async updateInventory(sku: string, quantity: number): Promise<void> {
369
+ const xmlRequest = `<?xml version="1.0" encoding="utf-8"?>
370
+ <ReviseInventoryStatusRequest xmlns="urn:ebay:apis:eBLBaseComponents">
371
+ <RequesterCredentials>
372
+ <eBayAuthToken>${this.config.authToken}</eBayAuthToken>
373
+ </RequesterCredentials>
374
+ <InventoryStatus>
375
+ <SKU>${sku}</SKU>
376
+ <Quantity>${quantity}</Quantity>
377
+ </InventoryStatus>
378
+ </ReviseInventoryStatusRequest>`;
379
+
380
+ await this.client.post('', xmlRequest, {
381
+ headers: {
382
+ 'X-EBAY-API-SITEID': this.config.siteId,
383
+ 'X-EBAY-API-COMPATIBILITY-LEVEL': '967',
384
+ 'X-EBAY-API-CALL-NAME': 'ReviseInventoryStatus',
385
+ 'Content-Type': 'text/xml',
386
+ },
387
+ });
388
+ }
389
+ }
390
+
391
+ class WalmartAPIClient {
392
+ private client: AxiosInstance;
393
+ private accessToken?: string;
394
+ private tokenExpiry?: Date;
395
+
396
+ constructor(
397
+ private config: typeof config.walmart,
398
+ private logger: StructuredLogger
399
+ ) {
400
+ this.client = axios.create({
401
+ baseURL: 'https://marketplace.walmartapis.com/v3',
402
+ timeout: 30000,
403
+ });
404
+ }
405
+
406
+ async ensureAuthenticated(): Promise<void> {
407
+ if (this.accessToken && this.tokenExpiry && new Date() < this.tokenExpiry) {
408
+ return;
409
+ }
410
+
411
+ this.logger.info('Refreshing Walmart Marketplace access token');
412
+
413
+ const credentials = Buffer.from(`${this.config.clientId}:${this.config.clientSecret}`).toString(
414
+ 'base64'
415
+ );
416
+
417
+ const response = await axios.post(
418
+ 'https://marketplace.walmartapis.com/v3/token',
419
+ 'grant_type=client_credentials',
420
+ {
421
+ headers: {
422
+ Authorization: `Basic ${credentials}`,
423
+ 'Content-Type': 'application/x-www-form-urlencoded',
424
+ 'WM_SVC.NAME': 'Walmart Marketplace',
425
+ 'WM_QOS.CORRELATION_ID': Date.now().toString(),
426
+ },
427
+ }
428
+ );
429
+
430
+ this.accessToken = response.data.access_token;
431
+ this.tokenExpiry = new Date(Date.now() + response.data.expires_in * 1000);
432
+
433
+ this.logger.info('Walmart access token refreshed successfully');
434
+ }
435
+
436
+ async updateInventory(sku: string, quantity: number): Promise<void> {
437
+ await this.ensureAuthenticated();
438
+
439
+ const payload = {
440
+ sku,
441
+ quantity: {
442
+ unit: 'EACH',
443
+ amount: quantity,
444
+ },
445
+ };
446
+
447
+ await this.client.put(`/inventory?sku=${sku}`, payload, {
448
+ headers: {
449
+ 'WM_SEC.ACCESS_TOKEN': this.accessToken,
450
+ 'WM_SVC.NAME': 'Walmart Marketplace',
451
+ 'WM_QOS.CORRELATION_ID': Date.now().toString(),
452
+ 'Content-Type': 'application/json',
453
+ },
454
+ });
455
+ }
456
+ }
457
+
458
+ // ============================================================================
459
+ // MULTI-CHANNEL INVENTORY SYNCHRONIZER
460
+ // ============================================================================
461
+
462
+ class MultiChannelInventorySync {
463
+ private fluentClient: FluentClient;
464
+ private logger: StructuredLogger;
465
+ private channels: Map<string, ChannelConfig> = new Map();
466
+ private metrics: SyncMetrics;
467
+
468
+ constructor() {
469
+ this.logger = toStructuredLogger(createConsoleLogger(), { logLevel: 'info' });
470
+
471
+ this.metrics = {
472
+ startTime: new Date(),
473
+ totalSKUs: 0,
474
+ successfulUpdates: 0,
475
+ failedUpdates: 0,
476
+ skippedUpdates: 0,
477
+ errors: [],
478
+ rateLimitHits: 0,
479
+ avgResponseTime: 0,
480
+ };
481
+ }
482
+
483
+ async initialize(): Promise<void> {
484
+ this.logger.info('Initializing Multi-Channel Inventory Sync');
485
+
486
+ // Initialize Fluent Commerce client
487
+ this.fluentClient = await createClient({ config: config.fluent });
488
+
489
+ // Initialize marketplace API clients
490
+ if (config.amazon.enabled) {
491
+ const amazonClient = new AmazonAPIClient(config.amazon, this.logger);
492
+ this.channels.set('amazon', {
493
+ enabled: true,
494
+ apiClient: amazonClient as any,
495
+ bufferStock: config.amazon.bufferStock,
496
+ rateLimit: config.amazon.rateLimit,
497
+ });
498
+ this.logger.info('Amazon SP-API client initialized');
499
+ }
500
+
501
+ if (config.ebay.enabled) {
502
+ const ebayClient = new eBayAPIClient(config.ebay, this.logger);
503
+ this.channels.set('ebay', {
504
+ enabled: true,
505
+ apiClient: ebayClient as any,
506
+ bufferStock: config.ebay.bufferStock,
507
+ rateLimit: config.ebay.rateLimit,
508
+ });
509
+ this.logger.info('eBay Trading API client initialized');
510
+ }
511
+
512
+ if (config.walmart.enabled) {
513
+ const walmartClient = new WalmartAPIClient(config.walmart, this.logger);
514
+ this.channels.set('walmart', {
515
+ enabled: true,
516
+ apiClient: walmartClient as any,
517
+ bufferStock: config.walmart.bufferStock,
518
+ rateLimit: config.walmart.rateLimit,
519
+ });
520
+ this.logger.info('Walmart Marketplace API client initialized');
521
+ }
522
+
523
+ this.logger.info(`Initialized ${this.channels.size} marketplace channels`);
524
+ }
525
+
526
+ async syncInventory(): Promise<void> {
527
+ this.logger.info('Starting multi-channel inventory sync');
528
+ this.metrics.startTime = new Date();
529
+
530
+ try {
531
+ // Step 1: Fetch all ATP inventory from Fluent Commerce
532
+ const inventory = await this.fetchFluentInventory();
533
+ this.metrics.totalSKUs = inventory.length;
534
+
535
+ this.logger.info(`Fetched ${inventory.length} inventory positions from Fluent`);
536
+
537
+ // Step 2: Calculate ATP for each channel with buffer stock
538
+ const channelInventory = this.calculateChannelInventory(inventory);
539
+
540
+ // Step 3: Update each marketplace in parallel with rate limiting
541
+ await this.updateMarketplaces(channelInventory);
542
+
543
+ this.metrics.endTime = new Date();
544
+ this.logMetrics();
545
+
546
+ this.logger.info('Multi-channel inventory sync completed successfully');
547
+ } catch (error: any) {
548
+ this.logger.error('Multi-channel inventory sync failed', error);
549
+ throw error;
550
+ }
551
+ }
552
+
553
+ private async fetchFluentInventory(): Promise<InventoryPosition[]> {
554
+ const query = `
555
+ query GetInventory($retailerId: ID!, $first: Int!, $after: String) {
556
+ inventoryQuantities(
557
+ first: $first
558
+ after: $after
559
+ retailerId: $retailerId
560
+ type: "AVAILABLE"
561
+ ) {
562
+ edges {
563
+ node {
564
+ productRef
565
+ locationRef
566
+ quantity
567
+ onHand
568
+ available
569
+ reserved
570
+ }
571
+ cursor
572
+ }
573
+ pageInfo {
574
+ hasNextPage
575
+ }
576
+ }
577
+ }
578
+ `;
579
+
580
+ const result = await this.fluentClient.graphql({
581
+ query,
582
+ variables: {
583
+ retailerId: config.fluent.retailerId,
584
+ first: 250,
585
+ },
586
+ pagination: {
587
+ maxPages: 500,
588
+ },
589
+ });
590
+
591
+ if (result.errors) {
592
+ throw new Error(`GraphQL errors: ${JSON.stringify(result.errors)}`);
593
+ }
594
+
595
+ const edges = (result.data as any).inventoryQuantities?.edges || [];
596
+ return edges.map((edge: any) => edge.node);
597
+ }
598
+
599
+ private calculateChannelInventory(
600
+ inventory: InventoryPosition[]
601
+ ): Map<string, Map<string, number>> {
602
+ const channelInventory = new Map<string, Map<string, number>>();
603
+
604
+ for (const [channelName, channelConfig] of this.channels) {
605
+ const skuQuantities = new Map<string, number>();
606
+
607
+ for (const position of inventory) {
608
+ const atpQuantity = position.available || 0;
609
+ const channelQuantity = Math.max(0, atpQuantity - channelConfig.bufferStock);
610
+ skuQuantities.set(position.productRef, channelQuantity);
611
+ }
612
+
613
+ channelInventory.set(channelName, skuQuantities);
614
+ }
615
+
616
+ return channelInventory;
617
+ }
618
+
619
+ private async updateMarketplaces(
620
+ channelInventory: Map<string, Map<string, number>>
621
+ ): Promise<void> {
622
+ const updatePromises: Promise<void>[] = [];
623
+
624
+ for (const [channelName, skuQuantities] of channelInventory) {
625
+ const channelConfig = this.channels.get(channelName)!;
626
+ const limit = pLimit(channelConfig.rateLimit);
627
+
628
+ const channelPromises = Array.from(skuQuantities.entries()).map(([sku, quantity]) =>
629
+ limit(async () => {
630
+ try {
631
+ const startTime = Date.now();
632
+
633
+ if (channelName === 'amazon') {
634
+ await (channelConfig.apiClient as any).updateInventory(sku, quantity);
635
+ } else if (channelName === 'ebay') {
636
+ await (channelConfig.apiClient as any).updateInventory(sku, quantity);
637
+ } else if (channelName === 'walmart') {
638
+ await (channelConfig.apiClient as any).updateInventory(sku, quantity);
639
+ }
640
+
641
+ const duration = Date.now() - startTime;
642
+ this.metrics.successfulUpdates++;
643
+
644
+ this.logger.debug(`Updated ${channelName} inventory for ${sku}: ${quantity}`, {
645
+ duration,
646
+ });
647
+ } catch (error: any) {
648
+ this.metrics.failedUpdates++;
649
+ this.metrics.errors.push({
650
+ sku,
651
+ channel: channelName,
652
+ error: error.message,
653
+ });
654
+
655
+ if (error.response?.status === 429) {
656
+ this.metrics.rateLimitHits++;
657
+ }
658
+
659
+ this.logger.warn(`Failed to update ${channelName} inventory for ${sku}`, {
660
+ error: error.message,
661
+ status: error.response?.status,
662
+ });
663
+ }
664
+ })
665
+ );
666
+
667
+ updatePromises.push(...channelPromises);
668
+ }
669
+
670
+ await Promise.all(updatePromises);
671
+ }
672
+
673
+ private logMetrics(): void {
674
+ if (!config.processing.metricsEnabled) return;
675
+
676
+ const duration = this.metrics.endTime
677
+ ? (this.metrics.endTime.getTime() - this.metrics.startTime.getTime()) / 1000
678
+ : 0;
679
+
680
+ this.logger.info('='.repeat(80));
681
+ this.logger.info('SYNC METRICS', {
682
+ duration: `${duration.toFixed(2)}s`,
683
+ totalSKUs: this.metrics.totalSKUs,
684
+ successfulUpdates: this.metrics.successfulUpdates,
685
+ failedUpdates: this.metrics.failedUpdates,
686
+ skippedUpdates: this.metrics.skippedUpdates,
687
+ successRate: `${((this.metrics.successfulUpdates / (this.metrics.successfulUpdates + this.metrics.failedUpdates)) * 100).toFixed(2)}%`,
688
+ rateLimitHits: this.metrics.rateLimitHits,
689
+ errorCount: this.metrics.errors.length,
690
+ });
691
+
692
+ if (this.metrics.errors.length > 0) {
693
+ this.logger.warn('Error summary (first 10):', {
694
+ errors: this.metrics.errors.slice(0, 10),
695
+ });
696
+ }
697
+
698
+ this.logger.info('='.repeat(80));
699
+ }
700
+ }
701
+
702
+ // ============================================================================
703
+ // MAIN ENTRY POINT
704
+ // ============================================================================
705
+
706
+ async function main() {
707
+ const sync = new MultiChannelInventorySync();
708
+
709
+ try {
710
+ await sync.initialize();
711
+ await sync.syncInventory();
712
+
713
+ console.log('Multi-channel inventory sync completed successfully');
714
+ process.exit(0);
715
+ } catch (error: any) {
716
+ console.error('Fatal error:', error);
717
+ process.exit(1);
718
+ }
719
+ }
720
+
721
+ // Run if executed directly
722
+ if (require.main === module) {
723
+ main();
724
+ }
725
+
726
+ export { MultiChannelInventorySync };
727
+ ```
728
+
729
+ ---
730
+
731
+ ## Key Patterns Explained
732
+
733
+ ### Pattern 1: GraphQL Auto-Pagination for Large Datasets
734
+
735
+ **Challenge**: Efficiently fetch 10k-100k inventory positions without manual pagination logic
736
+
737
+ **Solution**: Use SDK's built-in auto-pagination with progress callbacks
738
+
739
+ ```javascript
740
+ const result = await fluentClient.graphql({
741
+ query,
742
+ variables: { retailerId, first: 200 },
743
+ pagination: {
744
+ maxRecords: 100000,
745
+ maxPages: 500,
746
+ },
747
+ });
748
+ ```
749
+
750
+ **Why This Works**:
751
+
752
+ - **Automatic**: No manual cursor tracking needed
753
+ - **Safe**: Built-in protections against infinite loops
754
+ - **Efficient**: Streams data as it's received
755
+ - **Observable**: Progress callbacks for monitoring
756
+
757
+ ### Pattern 2: ATP Aggregation with Location Rollup
758
+
759
+ **Challenge**: Calculate total Available-to-Promise across multiple warehouses/stores per SKU
760
+
761
+ **Solution**: Map-based aggregation with location tracking
762
+
763
+ ```javascript
764
+ function aggregateATP(inventoryPositions) {
765
+ const atpMap = new Map();
766
+ for (const position of inventoryPositions) {
767
+ const sku = position.productRef;
768
+ const availableQty = Math.max(0, position.availableQty || 0);
769
+
770
+ if (!atpMap.has(sku)) {
771
+ atpMap.set(sku, {
772
+ sku,
773
+ totalATP: 0,
774
+ locations: [],
775
+ lastUpdated: position.updatedOn,
776
+ });
777
+ }
778
+
779
+ const aggregated = atpMap.get(sku);
780
+ aggregated.totalATP += availableQty;
781
+ aggregated.locations.push({
782
+ locationRef: position.locationRef,
783
+ availableQty: availableQty,
784
+ });
785
+ }
786
+ return atpMap;
787
+ }
788
+ ```
789
+
790
+ **Why This Works**:
791
+
792
+ - **O(n) complexity**: Single pass through inventory
793
+ - **Location visibility**: Track which locations contribute to total
794
+ - **Negative protection**: `Math.max(0, ...)` prevents negative ATP
795
+ - **Timestamp tracking**: Know when inventory was last updated
796
+
797
+ ### Pattern 3: Marketplace-Specific Buffer Stock
798
+
799
+ **Challenge**: Different marketplaces need different safety buffers to prevent overselling
800
+
801
+ **Solution**: Configurable buffer per marketplace
802
+
803
+ ```javascript
804
+ // Configuration
805
+ const buffers = {
806
+ amazon: 5, // Lower buffer (fast fulfillment)
807
+ ebay: 3, // Moderate buffer
808
+ walmart: 10, // Higher buffer (longer fulfillment)
809
+ };
810
+
811
+ // Application
812
+ function applyBufferStock(totalATP, bufferStock) {
813
+ return Math.max(0, totalATP - bufferStock);
814
+ }
815
+
816
+ // Example: SKU with 50 ATP across all locations
817
+ const amazonQty = applyBufferStock(50, 5); // 45 available on Amazon
818
+ const ebayQty = applyBufferStock(50, 3); // 47 available on eBay
819
+ const walmartQty = applyBufferStock(50, 10); // 40 available on Walmart
820
+ ```
821
+
822
+ **Why This Works**:
823
+
824
+ - **Oversell prevention**: Accounts for sync delays and processing time
825
+ - **Marketplace flexibility**: Different risk profiles per marketplace
826
+ - **Safety floor**: `Math.max(0, ...)` ensures quantity never goes negative
827
+ - **Configurable**: Easy to adjust per marketplace requirements
828
+
829
+ ### Pattern 4: Parallel Marketplace Updates with Rate Limiting
830
+
831
+ **Challenge**: Update multiple marketplaces efficiently without exceeding API rate limits
832
+
833
+ **Solution**: Parallel execution with per-marketplace rate limiters
834
+
835
+ ```javascript
836
+ import pLimit from 'p-limit';
837
+
838
+ // Each marketplace has its own rate limiter
839
+ class AmazonMarketplace {
840
+ constructor(config) {
841
+ this.limiter = pLimit(config.rateLimit); // 10 req/sec
842
+ }
843
+
844
+ async updateInventory(sku, quantity) {
845
+ // Rate-limited execution
846
+ return this.limiter(() => this.makeApiCall(sku, quantity));
847
+ }
848
+ }
849
+
850
+ // Parallel sync across all marketplaces
851
+ const syncResults = await Promise.all(
852
+ marketplaces.map(marketplace => marketplace.syncInventory(atpMap))
853
+ );
854
+ ```
855
+
856
+ **Why This Works**:
857
+
858
+ - **Parallel execution**: All marketplaces sync simultaneously
859
+ - **Independent rate limits**: Each marketplace respects its own limits
860
+ - **Error isolation**: Failure in one marketplace doesn't affect others
861
+ - **Concurrency control**: p-limit prevents overwhelming APIs
862
+
863
+ ### Pattern 5: Exponential Backoff Retry Strategy
864
+
865
+ **Challenge**: Handle transient API failures (429 rate limits, 500 server errors)
866
+
867
+ **Solution**: p-retry with exponential backoff
868
+
869
+ ```javascript
870
+ import pRetry from 'p-retry';
871
+
872
+ async updateInventory(sku, quantity) {
873
+ return pRetry(
874
+ async () => {
875
+ // Attempt API call
876
+ const response = await axios.put(endpoint, payload);
877
+
878
+ // Check for retryable errors
879
+ if (response.status === 429) {
880
+ throw new Error('Rate limit exceeded'); // Will retry
881
+ }
882
+
883
+ return response.data;
884
+ },
885
+ {
886
+ retries: 3,
887
+ factor: 2, // Exponential backoff factor
888
+ minTimeout: 1000, // 1s, 2s, 4s delays
889
+ onFailedAttempt: error => {
890
+ logger.warn(`Retry attempt ${error.attemptNumber}`, {
891
+ retriesLeft: error.retriesLeft,
892
+ });
893
+ },
894
+ }
895
+ );
896
+ }
897
+ ```
898
+
899
+ **Why This Works**:
900
+
901
+ - **Transient failure recovery**: Handles temporary API issues
902
+ - **Exponential backoff**: Reduces load on overloaded APIs
903
+ - **Configurable retries**: 3 attempts is reasonable for most cases
904
+ - **Observable**: Logs each retry attempt for debugging
905
+
906
+ ### Pattern 6: SLA Tracking and Compliance
907
+
908
+ **Challenge**: Ensure sync completes within 15-minute SLA requirement
909
+
910
+ **Solution**: Duration tracking with SLA compliance check
911
+
912
+ ```javascript
913
+ function checkSLA(durationMs) {
914
+ const durationMinutes = durationMs / 60000;
915
+ const slaThreshold = 15; // 15-minute requirement
916
+ const slaMet = durationMinutes <= slaThreshold;
917
+
918
+ if (!slaMet) {
919
+ logger.warn('SLA BREACH: Sync exceeded threshold', {
920
+ durationMinutes: durationMinutes.toFixed(2),
921
+ threshold: slaThreshold,
922
+ });
923
+ metrics.increment('sla_breaches');
924
+ // Alert via PagerDuty, Slack, etc.
925
+ }
926
+
927
+ return slaMet;
928
+ }
929
+ ```
930
+
931
+ **Why This Works**:
932
+
933
+ - **Clear threshold**: 15 minutes is measurable and actionable
934
+ - **Automated detection**: No manual checking needed
935
+ - **Alerting hook**: Can trigger notifications on breach
936
+ - **Metrics tracking**: Historical SLA compliance data
937
+
938
+ ### Pattern 7: Dry-Run Mode for Safe Testing
939
+
940
+ **Challenge**: Test sync logic without actually updating marketplaces
941
+
942
+ **Solution**: Dry-run flag that short-circuits API calls
943
+
944
+ ```javascript
945
+ async updateInventory(sku, quantity, dryRun = false) {
946
+ if (dryRun) {
947
+ this.logger.info(`[DRY RUN] Would update inventory`, { sku, quantity });
948
+ return { success: true, sku, quantity, dryRun: true };
949
+ }
950
+
951
+ // Real API call
952
+ return this.makeApiCall(sku, quantity);
953
+ }
954
+
955
+ // Usage
956
+ npm run sync:dry-run
957
+ ```
958
+
959
+ **Why This Works**:
960
+
961
+ - **Safe testing**: Validate logic without side effects
962
+ - **End-to-end flow**: Tests everything except final API call
963
+ - **Easy toggle**: Environment variable or CLI flag
964
+ - **Visible logging**: Clear indication of dry-run mode
965
+
966
+ ---
967
+
968
+ ## Testing
969
+
970
+ ### Dry-Run Test
971
+
972
+ ```bash
973
+ # Test sync without updating marketplaces
974
+ DRY_RUN=true npm run sync:once
975
+
976
+ # Expected output:
977
+ # [DRY RUN] Would update Amazon inventory { sku: 'PROD-001', quantity: 45 }
978
+ # [DRY RUN] Would update eBay inventory { sku: 'PROD-001', quantity: 47 }
979
+ # [DRY RUN] Would update Walmart inventory { sku: 'PROD-001', quantity: 40 }
980
+ ```
981
+
982
+ ### Single Sync Execution
983
+
984
+ ```bash
985
+ # Run once and exit
986
+ npm run sync:once
987
+
988
+ # Check logs
989
+ cat logs/inventory-sync.log | grep "COMPLETE"
990
+ ```
991
+
992
+ ### Continuous Sync Mode
993
+
994
+ ```bash
995
+ # Run continuously (every 15 minutes)
996
+ npm run sync:continuous
997
+
998
+ # Check next sync time in logs
999
+ ```
1000
+
1001
+ ---
1002
+
1003
+ ## Deployment Options
1004
+
1005
+ ### Option 1: Docker Container
1006
+
1007
+ Create `Dockerfile`:
1008
+
1009
+ ```dockerfile
1010
+ FROM node:18-alpine
1011
+
1012
+ WORKDIR /app
1013
+
1014
+ # Copy package files
1015
+ COPY package*.json ./
1016
+
1017
+ # Install dependencies
1018
+ RUN npm ci --only=production
1019
+
1020
+ # Copy application code
1021
+ COPY src ./src
1022
+
1023
+ # Create state directory
1024
+ RUN mkdir -p /app/state
1025
+
1026
+ # Run continuous sync
1027
+ CMD ["node", "src/index.js"]
1028
+ ```
1029
+
1030
+ Build and run:
1031
+
1032
+ ```bash
1033
+ # Build image
1034
+ docker build -t multi-channel-sync .
1035
+
1036
+ # Run container
1037
+ docker run -d \
1038
+ --name inventory-sync \
1039
+ --env-file .env \
1040
+ --restart unless-stopped \
1041
+ --volume ./state:/app/state \
1042
+ multi-channel-sync
1043
+ ```
1044
+
1045
+ ### Option 2: AWS ECS Task
1046
+
1047
+ Create `ecs-task-definition.json`:
1048
+
1049
+ ```json
1050
+ {
1051
+ "family": "multi-channel-inventory-sync",
1052
+ "networkMode": "awsvpc",
1053
+ "requiresCompatibilities": ["FARGATE"],
1054
+ "cpu": "1024",
1055
+ "memory": "2048",
1056
+ "containerDefinitions": [
1057
+ {
1058
+ "name": "inventory-sync",
1059
+ "image": "your-registry/multi-channel-sync:latest",
1060
+ "essential": true,
1061
+ "environment": [
1062
+ { "name": "LOG_LEVEL", "value": "info" },
1063
+ { "name": "SYNC_INTERVAL_MINUTES", "value": "15" }
1064
+ ],
1065
+ "secrets": [
1066
+ {
1067
+ "name": "FLUENT_CLIENT_ID",
1068
+ "valueFrom": "arn:aws:secretsmanager:us-east-1:123:secret:fluent-client-id"
1069
+ }
1070
+ ],
1071
+ "logConfiguration": {
1072
+ "logDriver": "awslogs",
1073
+ "options": {
1074
+ "awslogs-group": "/ecs/inventory-sync",
1075
+ "awslogs-region": "us-east-1",
1076
+ "awslogs-stream-prefix": "ecs"
1077
+ }
1078
+ }
1079
+ }
1080
+ ]
1081
+ }
1082
+ ```
1083
+
1084
+ Deploy:
1085
+
1086
+ ```bash
1087
+ aws ecs register-task-definition --cli-input-json file://ecs-task-definition.json
1088
+ aws ecs create-service \
1089
+ --cluster production \
1090
+ --service-name inventory-sync \
1091
+ --task-definition multi-channel-inventory-sync \
1092
+ --desired-count 1 \
1093
+ --launch-type FARGATE
1094
+ ```
1095
+
1096
+ ---
1097
+
1098
+ ## Common Issues & Solutions
1099
+
1100
+ ### Issue 1: SLA Breach (Sync Takes >15 Minutes)
1101
+
1102
+ **Symptoms**:
1103
+
1104
+ - Log shows "SLA BREACH" warning
1105
+ - Sync duration exceeds 15 minutes
1106
+
1107
+ **Solutions**:
1108
+
1109
+ 1. **Reduce page size** (faster initial response):
1110
+
1111
+ ```javascript
1112
+ variables: {
1113
+ first: 100;
1114
+ } // Instead of 200
1115
+ ```
1116
+
1117
+ 2. **Increase parallelism**:
1118
+
1119
+ ```javascript
1120
+ const limiter = pLimit(20); // Increase from 10
1121
+ ```
1122
+
1123
+ 3. **Optimize marketplace rate limits** (if APIs allow):
1124
+
1125
+ ```bash
1126
+ AMAZON_RATE_LIMIT=20 # Increase from 10
1127
+ ```
1128
+
1129
+ 4. **Split sync by marketplace** (run separately):
1130
+
1131
+ ```bash
1132
+ AMAZON_ENABLED=true EBAY_ENABLED=false WALMART_ENABLED=false npm run sync:once
1133
+ ```
1134
+
1135
+ ---
1136
+
1137
+ ## Related Guides
1138
+
1139
+ - **GraphQL Query Export**: [`./graphql-query-export.md`](./graphql-query-export.md) - GraphQL pagination patterns
1140
+ - **Multi-Source Aggregation**: `./04-multi-source-aggregation.md` - Data aggregation strategies
1141
+ - **Error Handling Patterns**: `../../03-PATTERN-GUIDES/error-handling/readme.md` - Retry and error handling
1142
+ - **Universal Mapping Guide**: `../../02-CORE-GUIDES/mapping/readme.md` - Field transformations
1143
+ - **SDK API Reference**: `../../readme.md` - Core SDK documentation
1144
+
1145
+ ---
1146
+
1147
+ ## Production Checklist
1148
+
1149
+ Before deploying to production:
1150
+
1151
+ - [ ] All marketplace credentials secured (AWS Secrets Manager, Vault)
1152
+ - [ ] Rate limits configured per marketplace API documentation
1153
+ - [ ] Buffer stock values tested and approved by business
1154
+ - [ ] SLA threshold aligned with business requirements
1155
+ - [ ] Monitoring dashboards created (sync duration, SLA compliance, error rates)
1156
+ - [ ] Alerting configured (PagerDuty, Slack, email)
1157
+ - [ ] Dry-run testing completed with production data
1158
+ - [ ] Load testing with 100k+ SKUs
1159
+ - [ ] State management enabled to prevent duplicate processing
1160
+ - [ ] Logging configured (CloudWatch, Datadog, Splunk)
1161
+ - [ ] Error tracking integrated (Sentry, Rollbar)
1162
+ - [ ] Documentation updated with runbooks
1163
+ - [ ] On-call team trained on troubleshooting
1164
+ - [ ] Disaster recovery plan documented
1165
+ - [ ] Metrics baseline established (average sync duration, success rate)
1166
+
1167
+ ---
1168
+
1169
+ **Next Steps**:
1170
+
1171
+ 1. Customize buffer stock values per marketplace and product category
1172
+ 2. Implement incremental sync (only process changed inventory)
1173
+ 3. Add webhook integration for real-time inventory updates
1174
+ 4. Set up monitoring dashboards (Grafana, Datadog)
1175
+ 5. Integrate with incident management (PagerDuty)
1176
+ 6. Add marketplace-specific SKU mapping (Fluent SKU → Marketplace SKU)
1177
+ 7. Implement A/B testing for buffer stock optimization
1178
+
1179
+ **Support**:
1180
+
1181
+ - SDK Issues: https://github.com/fluentcommerce/fc-connect-sdk/issues
1182
+ - Fluent Commerce API: https://docs.fluentcommerce.com
1183
+ - Amazon SP-API: https://developer-docs.amazon.com/sp-api/
1184
+ - eBay Trading API: https://developer.ebay.com/devzone/xml/docs/reference/ebay/
1185
+ - Walmart Seller API: https://developer.walmart.com/