@fluentcommerce/fc-connect-sdk 0.1.54 → 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 (475) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/clients/fluent-client.js +13 -6
  3. package/dist/cjs/utils/pagination-helpers.js +38 -2
  4. package/dist/cjs/versori/fluent-versori-client.js +11 -5
  5. package/dist/esm/clients/fluent-client.js +13 -6
  6. package/dist/esm/utils/pagination-helpers.js +38 -2
  7. package/dist/esm/versori/fluent-versori-client.js +11 -5
  8. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  9. package/dist/tsconfig.tsbuildinfo +1 -1
  10. package/dist/tsconfig.types.tsbuildinfo +1 -1
  11. package/docs/00-START-HERE/EXPORT-VALIDATION.md +158 -158
  12. package/docs/00-START-HERE/cli-analyze-source-structure-guide.md +655 -655
  13. package/docs/00-START-HERE/cli-documentation-index.md +202 -202
  14. package/docs/00-START-HERE/cli-quick-reference.md +252 -252
  15. package/docs/00-START-HERE/decision-tree.md +552 -552
  16. package/docs/00-START-HERE/getting-started.md +1070 -1070
  17. package/docs/00-START-HERE/mapper-quick-decision-guide.md +235 -235
  18. package/docs/00-START-HERE/readme.md +237 -237
  19. package/docs/00-START-HERE/retailerid-configuration.md +404 -404
  20. package/docs/00-START-HERE/sdk-philosophy.md +794 -794
  21. package/docs/00-START-HERE/troubleshooting-quick-reference.md +1086 -1086
  22. package/docs/01-TEMPLATES/faq.md +686 -686
  23. package/docs/01-TEMPLATES/patterns/pattern-templates-guide.md +68 -68
  24. package/docs/01-TEMPLATES/patterns/patterns-csv-schema-validation-and-rejection-report.md +233 -233
  25. package/docs/01-TEMPLATES/patterns/patterns-custom-resolvers.md +407 -407
  26. package/docs/01-TEMPLATES/patterns/patterns-error-handling-retry.md +511 -511
  27. package/docs/01-TEMPLATES/patterns/patterns-field-mapping-universal.md +701 -701
  28. package/docs/01-TEMPLATES/patterns/patterns-large-file-splitting.md +1430 -1430
  29. package/docs/01-TEMPLATES/patterns/patterns-master-data-etl.md +2399 -2399
  30. package/docs/01-TEMPLATES/patterns/patterns-pagination-streaming.md +447 -447
  31. package/docs/01-TEMPLATES/patterns/patterns-state-duplicate-prevention.md +385 -385
  32. package/docs/01-TEMPLATES/readme.md +957 -957
  33. package/docs/01-TEMPLATES/standalone/standalone-asn-inbound-processing.md +1209 -1209
  34. package/docs/01-TEMPLATES/standalone/standalone-graphql-query-export.md +1140 -1140
  35. package/docs/01-TEMPLATES/standalone/standalone-graphql-to-parquet-partitioned-s3.md +432 -432
  36. package/docs/01-TEMPLATES/standalone/standalone-multi-channel-inventory-sync.md +1185 -1185
  37. package/docs/01-TEMPLATES/standalone/standalone-multi-source-aggregation.md +1462 -1462
  38. package/docs/01-TEMPLATES/standalone/standalone-s3-csv-batch-api.md +1390 -1390
  39. package/docs/01-TEMPLATES/standalone/standalone-s3-csv-inventory-to-batch.md +330 -330
  40. package/docs/01-TEMPLATES/standalone/standalone-scripts-guide.md +87 -87
  41. package/docs/01-TEMPLATES/standalone/standalone-sftp-xml-graphql.md +1444 -1444
  42. package/docs/01-TEMPLATES/standalone/standalone-webhook-payload-processing.md +688 -688
  43. package/docs/01-TEMPLATES/versori/business-examples/business-examples-dropship-order-routing.md +193 -193
  44. package/docs/01-TEMPLATES/versori/business-examples/business-examples-graphql-parquet-extraction.md +518 -518
  45. package/docs/01-TEMPLATES/versori/business-examples/business-examples-inter-location-transfers.md +2162 -2162
  46. package/docs/01-TEMPLATES/versori/business-examples/business-examples-pre-order-allocation.md +2226 -2226
  47. package/docs/01-TEMPLATES/versori/business-examples/business-scenarios-guide.md +87 -87
  48. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-connection-validation-pattern.md +656 -656
  49. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-dual-workflow-connector.md +835 -835
  50. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-guide.md +108 -108
  51. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-kv-state-management.md +1533 -1533
  52. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-xml-response-patterns.md +1160 -1160
  53. package/docs/01-TEMPLATES/versori/versori-platform-guide.md +201 -201
  54. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-asn-purchase-order.md +1906 -1906
  55. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-dropship-routing.md +1074 -1074
  56. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-flash-sale-reserve.md +1395 -1395
  57. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-generic-xml-order.md +888 -888
  58. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-payment-gateway-integration.md +2478 -2478
  59. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-rma-returns-comprehensive.md +2240 -2240
  60. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-xml-order-ingestion.md +2029 -2029
  61. package/docs/01-TEMPLATES/versori/webhooks/webhook-templates-guide.md +140 -140
  62. package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/inventory-mapping.json +20 -20
  63. package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/products_2025-01-22.csv +11 -11
  64. package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/sample-data-guide.md +34 -34
  65. package/docs/01-TEMPLATES/versori/workflows/_examples/workflow-examples-guide.md +36 -36
  66. package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-modes-guide.md +1038 -1038
  67. package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-workflows-guide.md +138 -138
  68. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/graphql-extraction-guide.md +63 -63
  69. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-csv.md +2062 -2062
  70. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-xml.md +2294 -2294
  71. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-s3-csv.md +2461 -2461
  72. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-sftp-xml.md +2529 -2529
  73. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-csv.md +2464 -2464
  74. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-json.md +1959 -1959
  75. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-s3-csv.md +1953 -1953
  76. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-sftp-xml.md +2541 -2541
  77. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-s3-json.md +2384 -2384
  78. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-sftp-xml.md +2445 -2445
  79. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-csv.md +2355 -2355
  80. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-json.md +2042 -2042
  81. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-sftp-xml.md +2726 -2726
  82. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/batch-api-guide.md +206 -206
  83. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-cycle-count-reconciliation.md +2030 -2030
  84. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-multi-channel-inventory-sync.md +1882 -1882
  85. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-csv-inventory-batch.md +2827 -2827
  86. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-json-inventory-batch.md +1952 -1952
  87. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-xml-inventory-batch.md +3289 -3289
  88. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-csv-inventory-batch.md +3064 -3064
  89. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-json-inventory-batch.md +3238 -3238
  90. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-xml-inventory-batch.md +2977 -2977
  91. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/event-api-guide.md +321 -321
  92. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-json-order-cancel-event.md +959 -959
  93. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-xml-order-cancel-event.md +1170 -1170
  94. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-csv-product-event.md +2312 -2312
  95. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-json-product-event.md +2999 -2999
  96. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-parquet-product-event.md +2836 -2836
  97. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-xml-product-event.md +2395 -2395
  98. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-csv-product-event.md +2295 -2295
  99. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-json-product-event.md +2602 -2602
  100. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-parquet-product-event.md +2589 -2589
  101. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-xml-product-event.md +3578 -3578
  102. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/graphql-mutations-guide.md +93 -93
  103. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-json-order-update-graphql.md +1260 -1260
  104. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-xml-order-update-graphql.md +1472 -1472
  105. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-control-graphql.md +2417 -2417
  106. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-location-graphql.md +2811 -2811
  107. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-price-graphql.md +2619 -2619
  108. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-json-location-graphql.md +2807 -2807
  109. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-xml-location-graphql.md +2373 -2373
  110. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-control-graphql.md +2740 -2740
  111. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-location-graphql.md +2760 -2760
  112. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-json-location-graphql.md +1710 -1710
  113. package/docs/01-TEMPLATES/versori/workflows/ingestion/ingestion-workflows-guide.md +136 -136
  114. package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/rubix-webhooks-guide.md +520 -520
  115. package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-inline.md +1418 -1418
  116. package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-universal-mapper.md +1785 -1785
  117. package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-order-attribute-update.md +824 -824
  118. package/docs/01-TEMPLATES/versori/workflows/workflows-overview-guide.md +646 -646
  119. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-batch-archival.md +724 -724
  120. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-job-tracker.md +627 -627
  121. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-partial-batch-recovery.md +561 -561
  122. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-quick-reference.md +367 -367
  123. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-readme.md +407 -407
  124. package/docs/02-CORE-GUIDES/advanced-services/readme.md +49 -49
  125. package/docs/02-CORE-GUIDES/api-reference/api-reference-quick-reference.md +548 -548
  126. package/docs/02-CORE-GUIDES/api-reference/event-api-input-output-reference.md +702 -1171
  127. package/docs/02-CORE-GUIDES/api-reference/examples/client-initialization.ts +286 -286
  128. package/docs/02-CORE-GUIDES/api-reference/graphql-error-classification.md +337 -337
  129. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-01-client-api.md +399 -520
  130. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-03-authentication.md +199 -199
  131. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-04-graphql-mapping.md +925 -925
  132. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-05-services.md +1198 -1198
  133. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-06-data-sources.md +1083 -1083
  134. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-07-parsers.md +1097 -1097
  135. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-pagination.md +513 -513
  136. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-types.md +545 -597
  137. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-error-handling.md +527 -527
  138. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-webhook-validation.md +514 -514
  139. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-extraction.md +557 -557
  140. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-utilities.md +412 -412
  141. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-cli-tools.md +423 -423
  142. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-error-handling.md +716 -716
  143. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-analyze-source-structure.md +518 -518
  144. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-partial-responses.md +212 -212
  145. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-testing.md +300 -300
  146. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-13-resolver-builder.md +322 -322
  147. package/docs/02-CORE-GUIDES/api-reference/readme.md +279 -279
  148. package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-quick-reference.md +351 -351
  149. package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-readme.md +277 -277
  150. package/docs/02-CORE-GUIDES/auto-pagination/examples/auto-pagination-readme.md +178 -178
  151. package/docs/02-CORE-GUIDES/auto-pagination/examples/common-patterns.ts +351 -351
  152. package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-products.ts +384 -384
  153. package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-virtual-positions.ts +308 -308
  154. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-01-foundations.md +470 -470
  155. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-02-quick-start.md +713 -713
  156. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-03-configuration.md +754 -754
  157. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-04-advanced-patterns.md +732 -732
  158. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-05-sdk-integration.md +847 -847
  159. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-06-troubleshooting.md +359 -359
  160. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-07-api-reference.md +462 -462
  161. package/docs/02-CORE-GUIDES/auto-pagination/readme.md +54 -54
  162. package/docs/02-CORE-GUIDES/data-sources/data-sources-file-operations-error-handling.md +1487 -1487
  163. package/docs/02-CORE-GUIDES/data-sources/data-sources-quick-reference.md +836 -836
  164. package/docs/02-CORE-GUIDES/data-sources/data-sources-readme.md +276 -276
  165. package/docs/02-CORE-GUIDES/data-sources/data-sources-sftp-credential-access-security.md +553 -553
  166. package/docs/02-CORE-GUIDES/data-sources/examples/common-patterns.ts +409 -409
  167. package/docs/02-CORE-GUIDES/data-sources/examples/data-sources-readme.md +178 -178
  168. package/docs/02-CORE-GUIDES/data-sources/examples/s3-operations.ts +308 -308
  169. package/docs/02-CORE-GUIDES/data-sources/examples/sftp-operations.ts +371 -371
  170. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-01-foundations.md +735 -735
  171. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-02-s3-operations.md +1302 -1302
  172. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-03-sftp-operations.md +1379 -1379
  173. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-04-file-patterns.md +941 -941
  174. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-05-advanced-topics.md +813 -813
  175. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-06-integration-patterns.md +486 -486
  176. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-07-troubleshooting.md +387 -387
  177. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-08-api-reference.md +417 -417
  178. package/docs/02-CORE-GUIDES/data-sources/readme.md +77 -77
  179. package/docs/02-CORE-GUIDES/error-handling-guide.md +936 -936
  180. package/docs/02-CORE-GUIDES/extraction/examples/02-core-guides-extraction-readme.md +116 -116
  181. package/docs/02-CORE-GUIDES/extraction/examples/common-patterns.ts +428 -428
  182. package/docs/02-CORE-GUIDES/extraction/examples/extract-inventory-basic.ts +187 -187
  183. package/docs/02-CORE-GUIDES/extraction/extraction-quick-reference.md +596 -596
  184. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-01-foundations.md +514 -514
  185. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-02-basic-extraction.md +823 -823
  186. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-03-parquet-processing.md +507 -507
  187. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-04-data-enrichment.md +546 -546
  188. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-05-transformation.md +494 -494
  189. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-export-formats.md +458 -458
  190. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-performance.md +138 -138
  191. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-api-reference.md +148 -148
  192. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-optimization.md +692 -692
  193. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-08-extraction-orchestrator.md +1008 -1008
  194. package/docs/02-CORE-GUIDES/extraction/readme.md +151 -151
  195. package/docs/02-CORE-GUIDES/ingestion/examples/_simple-kv-store.ts +40 -40
  196. package/docs/02-CORE-GUIDES/ingestion/examples/error-recovery.ts +728 -728
  197. package/docs/02-CORE-GUIDES/ingestion/examples/event-driven.ts +501 -501
  198. package/docs/02-CORE-GUIDES/ingestion/examples/local-file-ingestion.ts +88 -88
  199. package/docs/02-CORE-GUIDES/ingestion/examples/parquet-ingestion.ts +117 -117
  200. package/docs/02-CORE-GUIDES/ingestion/examples/performance-optimized.ts +647 -647
  201. package/docs/02-CORE-GUIDES/ingestion/examples/s3-csv-ingestion.ts +169 -169
  202. package/docs/02-CORE-GUIDES/ingestion/examples/sftp-csv-ingestion.ts +134 -134
  203. package/docs/02-CORE-GUIDES/ingestion/ingestion-quick-reference.md +546 -546
  204. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-01-introduction.md +626 -626
  205. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-02-quick-start.md +658 -658
  206. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-03-data-sources.md +1052 -1052
  207. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-04-field-mapping.md +763 -763
  208. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-05-advanced-parsers.md +676 -676
  209. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-06-batch-api.md +1295 -1295
  210. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-api-reference.md +138 -138
  211. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-state-management.md +1037 -1037
  212. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-08-performance-optimization.md +1349 -1349
  213. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-09-best-practices.md +1893 -1893
  214. package/docs/02-CORE-GUIDES/ingestion/readme.md +160 -160
  215. package/docs/02-CORE-GUIDES/logging-guide.md +585 -585
  216. package/docs/02-CORE-GUIDES/mapping/error-handling-patterns.md +401 -401
  217. package/docs/02-CORE-GUIDES/mapping/examples/02-core-guides-mapping-readme.md +128 -128
  218. package/docs/02-CORE-GUIDES/mapping/examples/common-patterns.ts +273 -273
  219. package/docs/02-CORE-GUIDES/mapping/examples/csv-location-ingestion.json +36 -36
  220. package/docs/02-CORE-GUIDES/mapping/examples/csv-mapping.ts +242 -242
  221. package/docs/02-CORE-GUIDES/mapping/examples/graphql-to-parquet-extraction.json +36 -36
  222. package/docs/02-CORE-GUIDES/mapping/examples/json-mapping.ts +213 -213
  223. package/docs/02-CORE-GUIDES/mapping/examples/json-product-to-mutation.json +48 -48
  224. package/docs/02-CORE-GUIDES/mapping/examples/xml-mapping.ts +291 -291
  225. package/docs/02-CORE-GUIDES/mapping/examples/xml-order-to-mutation.json +45 -45
  226. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-quick-reference.md +463 -463
  227. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-readme.md +227 -227
  228. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-01-introduction.md +222 -222
  229. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-02-quick-start.md +351 -351
  230. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-03-schema-validation.md +569 -569
  231. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-04-mapping-patterns.md +471 -471
  232. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-05-configuration-reference.md +611 -611
  233. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-advanced-xpath.md +148 -148
  234. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-path-syntax.md +464 -464
  235. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-api-reference.md +94 -94
  236. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-array-handling.md +307 -307
  237. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-08-custom-resolvers.md +544 -544
  238. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-09-advanced-patterns.md +427 -427
  239. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-10-hooks-and-variables.md +336 -336
  240. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-11-error-handling.md +488 -488
  241. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-12-arguments-vs-nodes.md +383 -383
  242. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-13-best-practices.md +477 -477
  243. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/readme.md +62 -62
  244. package/docs/02-CORE-GUIDES/mapping/mapping-format-decision-tree.md +480 -480
  245. package/docs/02-CORE-GUIDES/mapping/mapping-graphql-alias-batching-guide.md +820 -820
  246. package/docs/02-CORE-GUIDES/mapping/mapping-javascript-objects.md +2369 -2369
  247. package/docs/02-CORE-GUIDES/mapping/mapping-mapper-comparison-guide.md +682 -682
  248. package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-07-api-reference.md +1327 -1327
  249. package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-08-error-handling.md +1142 -1142
  250. package/docs/02-CORE-GUIDES/mapping/modules/mapping-04-use-cases.md +891 -891
  251. package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-helpers-resolvers.md +1126 -1126
  252. package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-sdk-resolvers.md +199 -199
  253. package/docs/02-CORE-GUIDES/mapping/modules/mapping-07-api-reference.md +1319 -1319
  254. package/docs/02-CORE-GUIDES/mapping/readme.md +178 -178
  255. package/docs/02-CORE-GUIDES/mapping/resolver-registration.md +410 -410
  256. package/docs/02-CORE-GUIDES/mapping/resolvers/examples/common-patterns.ts +226 -226
  257. package/docs/02-CORE-GUIDES/mapping/resolvers/examples/custom-resolvers.ts +227 -227
  258. package/docs/02-CORE-GUIDES/mapping/resolvers/examples/sdk-resolvers-usage.ts +203 -203
  259. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-readme.md +274 -274
  260. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-api-reference.md +679 -679
  261. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-cookbook.md +826 -826
  262. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-guide.md +1330 -1330
  263. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-helpers-reference.md +1437 -1437
  264. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-parameters-reference.md +553 -553
  265. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-troubleshooting.md +854 -854
  266. package/docs/02-CORE-GUIDES/mapping/resolvers/readme.md +75 -75
  267. package/docs/02-CORE-GUIDES/parsers/examples/02-core-guides-parsers-readme.md +161 -161
  268. package/docs/02-CORE-GUIDES/parsers/examples/csv-parser-examples.ts +110 -110
  269. package/docs/02-CORE-GUIDES/parsers/examples/json-parser-examples.ts +33 -33
  270. package/docs/02-CORE-GUIDES/parsers/examples/parquet-parser-examples.ts +47 -47
  271. package/docs/02-CORE-GUIDES/parsers/examples/xml-parser-examples.ts +38 -38
  272. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-01-foundations.md +355 -355
  273. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-02-csv-parser.md +772 -772
  274. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-03-json-parser.md +789 -789
  275. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-04-xml-parser.md +857 -857
  276. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-05-parquet-parser.md +603 -603
  277. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-integration-patterns.md +702 -702
  278. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-streaming.md +121 -121
  279. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-api-reference.md +89 -89
  280. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-troubleshooting.md +727 -727
  281. package/docs/02-CORE-GUIDES/parsers/parsers-quick-reference.md +482 -482
  282. package/docs/02-CORE-GUIDES/parsers/parsers-readme.md +258 -258
  283. package/docs/02-CORE-GUIDES/parsers/readme.md +65 -65
  284. package/docs/02-CORE-GUIDES/readme.md +194 -194
  285. package/docs/02-CORE-GUIDES/webhook-validation/examples/basic-validation.ts +108 -108
  286. package/docs/02-CORE-GUIDES/webhook-validation/examples/common-patterns.ts +316 -316
  287. package/docs/02-CORE-GUIDES/webhook-validation/examples/webhook-validation-readme.md +61 -61
  288. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-01-foundations.md +440 -440
  289. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-02-quick-start.md +525 -525
  290. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-03-versori-integration.md +741 -741
  291. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-04-platform-integration.md +629 -629
  292. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-05-configuration.md +535 -535
  293. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-error-handling.md +611 -611
  294. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-troubleshooting.md +124 -124
  295. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-07-api-reference.md +511 -511
  296. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-08-rubix-webhooks.md +590 -590
  297. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-09-rubix-event-vs-http-call.md +432 -432
  298. package/docs/02-CORE-GUIDES/webhook-validation/readme.md +239 -239
  299. package/docs/02-CORE-GUIDES/webhook-validation/webhook-validation-quick-reference.md +392 -392
  300. package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-quick-reference.md +498 -498
  301. package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-readme.md +313 -313
  302. package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/common-patterns.ts +612 -612
  303. package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/connector-scenarios-readme.md +253 -253
  304. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-01-foundations.md +452 -452
  305. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-02-simple-scenarios.md +681 -681
  306. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-03-intermediate-scenarios.md +637 -637
  307. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-04-advanced-scenarios.md +650 -650
  308. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-05-bidirectional-sync.md +233 -233
  309. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-06-production-patterns.md +442 -442
  310. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-07-reference.md +445 -445
  311. package/docs/03-PATTERN-GUIDES/connector-scenarios/readme.md +31 -31
  312. package/docs/03-PATTERN-GUIDES/enterprise-integration-patterns.md +1528 -1528
  313. package/docs/03-PATTERN-GUIDES/error-handling/comprehensive-error-handling-guide.md +1437 -1437
  314. package/docs/03-PATTERN-GUIDES/error-handling/error-handling-quick-reference.md +390 -390
  315. package/docs/03-PATTERN-GUIDES/error-handling/examples/common-patterns.ts +438 -438
  316. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-01-foundations.md +362 -362
  317. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-02-error-types.md +850 -850
  318. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-03-utf8-handling.md +456 -456
  319. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-04-error-scenarios.md +658 -658
  320. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-05-calling-patterns.md +671 -671
  321. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-06-retry-strategies.md +1034 -1034
  322. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-07-monitoring.md +653 -653
  323. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-08-api-reference.md +847 -847
  324. package/docs/03-PATTERN-GUIDES/error-handling/readme.md +36 -36
  325. package/docs/03-PATTERN-GUIDES/examples/__tests__/readme.md +40 -40
  326. package/docs/03-PATTERN-GUIDES/examples/__tests__/resolver-examples.test.js +282 -282
  327. package/docs/03-PATTERN-GUIDES/examples/test-data/03-pattern-guides-readme.md +110 -110
  328. package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-inventory.json +123 -123
  329. package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-order.json +171 -171
  330. package/docs/03-PATTERN-GUIDES/examples/test-data/readme.md +28 -28
  331. package/docs/03-PATTERN-GUIDES/extraction/extraction-readme.md +15 -15
  332. package/docs/03-PATTERN-GUIDES/extraction/readme.md +25 -25
  333. package/docs/03-PATTERN-GUIDES/file-operations/examples/common-patterns.ts +407 -407
  334. package/docs/03-PATTERN-GUIDES/file-operations/examples/file-operations-readme.md +142 -142
  335. package/docs/03-PATTERN-GUIDES/file-operations/file-operations-quick-reference.md +462 -462
  336. package/docs/03-PATTERN-GUIDES/file-operations/file-operations-readme.md +379 -379
  337. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-01-foundations.md +430 -430
  338. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-02-quick-start.md +484 -484
  339. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-03-s3-operations.md +507 -507
  340. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-04-sftp-operations.md +963 -963
  341. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-05-streaming-performance.md +503 -503
  342. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-archive-patterns.md +386 -386
  343. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-error-handling.md +117 -117
  344. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-api-reference.md +78 -78
  345. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-testing-troubleshooting.md +567 -567
  346. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-08-api-reference.md +1055 -1055
  347. package/docs/03-PATTERN-GUIDES/file-operations/readme.md +32 -32
  348. package/docs/03-PATTERN-GUIDES/ingestion/ingestion-readme.md +15 -15
  349. package/docs/03-PATTERN-GUIDES/ingestion/readme.md +25 -25
  350. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/batch-processing.ts +130 -130
  351. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/common-patterns.ts +360 -360
  352. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/delta-sync.ts +130 -130
  353. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/integration-patterns-readme.md +100 -100
  354. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/real-time-webhook.ts +398 -398
  355. package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-quick-reference.md +962 -962
  356. package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-readme.md +134 -134
  357. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-01-real-time-processing.md +991 -991
  358. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-02-batch-processing.md +1547 -1547
  359. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-03-delta-sync.md +1108 -1108
  360. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-04-webhook-patterns.md +1181 -1181
  361. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-05-error-handling.md +1061 -1061
  362. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-advanced-integration-services.md +1547 -1547
  363. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-performance.md +109 -109
  364. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-07-api-reference.md +34 -34
  365. package/docs/03-PATTERN-GUIDES/integration-patterns/readme.md +30 -30
  366. package/docs/03-PATTERN-GUIDES/logging-minimal-mode.md +128 -128
  367. package/docs/03-PATTERN-GUIDES/multiple-connections/examples/common-patterns.ts +380 -380
  368. package/docs/03-PATTERN-GUIDES/multiple-connections/examples/multiple-connections-readme.md +139 -139
  369. package/docs/03-PATTERN-GUIDES/multiple-connections/examples/parallel-root-connections.ts +149 -149
  370. package/docs/03-PATTERN-GUIDES/multiple-connections/examples/real-world-scenarios.ts +405 -405
  371. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-01-foundations.md +378 -378
  372. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-02-quick-start.md +566 -566
  373. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-03-targeting-connections.md +659 -659
  374. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-04-parallel-queries.md +656 -656
  375. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-05-best-practices.md +624 -624
  376. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-api-reference.md +824 -824
  377. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-versori.md +119 -119
  378. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-07-api-reference.md +87 -87
  379. package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-quick-reference.md +353 -353
  380. package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-readme.md +270 -270
  381. package/docs/03-PATTERN-GUIDES/multiple-connections/readme.md +30 -30
  382. package/docs/03-PATTERN-GUIDES/pagination/pagination-readme.md +14 -14
  383. package/docs/03-PATTERN-GUIDES/pagination/readme.md +24 -24
  384. package/docs/03-PATTERN-GUIDES/parquet/examples/common-patterns.ts +180 -180
  385. package/docs/03-PATTERN-GUIDES/parquet/examples/read-parquet.ts +48 -48
  386. package/docs/03-PATTERN-GUIDES/parquet/examples/write-parquet.ts +65 -65
  387. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-01-introduction.md +393 -393
  388. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-02-quick-start.md +572 -572
  389. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-03-reading-parquet.md +525 -525
  390. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-04-writing-parquet.md +554 -554
  391. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-05-graphql-extraction.md +405 -405
  392. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-performance.md +104 -104
  393. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-s3-integration.md +511 -511
  394. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-api-reference.md +90 -90
  395. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-performance-optimization.md +525 -525
  396. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-08-best-practices.md +712 -712
  397. package/docs/03-PATTERN-GUIDES/parquet/parquet-quick-reference.md +683 -683
  398. package/docs/03-PATTERN-GUIDES/parquet/parquet-readme.md +248 -248
  399. package/docs/03-PATTERN-GUIDES/parquet/readme.md +32 -32
  400. package/docs/03-PATTERN-GUIDES/parsers/parsers-readme.md +12 -12
  401. package/docs/03-PATTERN-GUIDES/parsers/readme.md +24 -24
  402. package/docs/03-PATTERN-GUIDES/readme.md +159 -159
  403. package/docs/03-PATTERN-GUIDES/webhooks/readme.md +24 -24
  404. package/docs/03-PATTERN-GUIDES/webhooks/webhooks-readme.md +8 -8
  405. package/docs/04-REFERENCE/architecture/architecture-01-overview.md +427 -427
  406. package/docs/04-REFERENCE/architecture/architecture-02-client-architecture.md +424 -424
  407. package/docs/04-REFERENCE/architecture/architecture-03-data-flow.md +690 -690
  408. package/docs/04-REFERENCE/architecture/architecture-04-service-layer.md +834 -834
  409. package/docs/04-REFERENCE/architecture/architecture-05-integration-architecture.md +655 -655
  410. package/docs/04-REFERENCE/architecture/architecture-06-state-management.md +653 -653
  411. package/docs/04-REFERENCE/architecture/architecture-adding-new-data-sources.md +686 -686
  412. package/docs/04-REFERENCE/architecture/readme.md +279 -279
  413. package/docs/04-REFERENCE/platforms/deno/readme.md +117 -117
  414. package/docs/04-REFERENCE/platforms/nodejs/readme.md +146 -146
  415. package/docs/04-REFERENCE/platforms/readme.md +135 -135
  416. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-01-introduction.md +398 -398
  417. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-02-quick-start.md +560 -560
  418. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-03-authentication.md +757 -757
  419. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-04-workflows.md +2476 -2476
  420. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-05-connections.md +1167 -1167
  421. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-kv-storage.md +990 -990
  422. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-state-management.md +121 -121
  423. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-api-reference.md +68 -68
  424. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-deployment.md +731 -731
  425. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-08-best-practices.md +1111 -1111
  426. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-09-signature-reference.md +766 -766
  427. package/docs/04-REFERENCE/platforms/versori/platforms-versori-readme.md +299 -299
  428. package/docs/04-REFERENCE/platforms/versori/platforms-versori-s3-sftp-configuration-guide.md +1425 -1425
  429. package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-api-key-security.md +816 -816
  430. package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-connection-security.md +681 -681
  431. package/docs/04-REFERENCE/platforms/versori/platforms-versori-workflow-task-types.md +708 -708
  432. package/docs/04-REFERENCE/platforms/versori/readme.md +108 -108
  433. package/docs/04-REFERENCE/readme.md +148 -148
  434. package/docs/04-REFERENCE/resolver-signature/examples/advanced-resolvers.ts +482 -482
  435. package/docs/04-REFERENCE/resolver-signature/examples/async-resolvers.ts +496 -496
  436. package/docs/04-REFERENCE/resolver-signature/examples/basic-resolvers.ts +343 -343
  437. package/docs/04-REFERENCE/resolver-signature/examples/resolver-signature-readme.md +188 -188
  438. package/docs/04-REFERENCE/resolver-signature/examples/testing-resolvers.ts +463 -463
  439. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-01-foundations.md +286 -286
  440. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-02-parameter-reference.md +643 -643
  441. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-03-basic-examples.md +521 -521
  442. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-04-advanced-patterns.md +739 -739
  443. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-05-sdk-resolvers.md +531 -531
  444. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-migration-guide.md +650 -650
  445. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-testing.md +125 -125
  446. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-07-api-reference.md +794 -794
  447. package/docs/04-REFERENCE/resolver-signature/readme.md +64 -64
  448. package/docs/04-REFERENCE/resolver-signature/resolver-signature-quick-reference.md +270 -270
  449. package/docs/04-REFERENCE/resolver-signature/resolver-signature-readme.md +351 -351
  450. package/docs/04-REFERENCE/schema/fluent-commerce-schema.json +764 -764
  451. package/docs/04-REFERENCE/schema/readme.md +141 -141
  452. package/docs/04-REFERENCE/testing/examples/04-reference-testing-readme.md +158 -158
  453. package/docs/04-REFERENCE/testing/examples/fluent-testing.ts +62 -62
  454. package/docs/04-REFERENCE/testing/examples/health-check.ts +155 -155
  455. package/docs/04-REFERENCE/testing/examples/integration-test.ts +119 -119
  456. package/docs/04-REFERENCE/testing/examples/performance-test.ts +183 -183
  457. package/docs/04-REFERENCE/testing/examples/s3-testing.ts +127 -127
  458. package/docs/04-REFERENCE/testing/modules/04-reference-testing-01-foundations.md +267 -267
  459. package/docs/04-REFERENCE/testing/modules/04-reference-testing-02-s3-testing.md +599 -599
  460. package/docs/04-REFERENCE/testing/modules/04-reference-testing-03-fluent-testing.md +589 -589
  461. package/docs/04-REFERENCE/testing/modules/04-reference-testing-04-integration-testing.md +699 -699
  462. package/docs/04-REFERENCE/testing/modules/04-reference-testing-05-debugging.md +478 -478
  463. package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-cicd-integration.md +463 -463
  464. package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-preflight-validation.md +131 -131
  465. package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-best-practices.md +499 -499
  466. package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-coverage-ci.md +165 -165
  467. package/docs/04-REFERENCE/testing/modules/04-reference-testing-08-api-reference.md +634 -634
  468. package/docs/04-REFERENCE/testing/readme.md +86 -86
  469. package/docs/04-REFERENCE/testing/testing-quick-reference.md +667 -667
  470. package/docs/04-REFERENCE/testing/testing-readme.md +286 -286
  471. package/docs/04-REFERENCE/troubleshooting/readme.md +144 -144
  472. package/docs/04-REFERENCE/troubleshooting/troubleshooting-deno-sftp-compatibility.md +392 -392
  473. package/docs/template-loading-matrix.md +242 -242
  474. package/package.json +5 -3
  475. package/docs/02-CORE-GUIDES/api-reference/cli-profile-integration.md +0 -377
@@ -1,1437 +1,1437 @@
1
- # Comprehensive Error Handling Guide
2
-
3
- > **Complete guide** to error handling across GraphQL, Event API, Batch API, and Job API with live examples
4
-
5
- ## Table of Contents
6
-
7
- 1. [Error Types Overview](#error-types-overview)
8
- 2. [Where is the Status Code?](#where-is-the-status-code)
9
- 3. [Anatomy of an API Call](#anatomy-of-an-api-call)
10
- 4. [Event API Error Handling](#event-api-error-handling)
11
- 5. [GraphQL Error Handling](#graphql-error-handling)
12
- 6. [Batch API Error Handling](#batch-api-error-handling)
13
- 7. [Job API Error Handling](#job-api-error-handling)
14
- 8. [Common Patterns](#common-patterns)
15
- 9. [Live Examples](#live-examples)
16
-
17
- ---
18
-
19
- ## Error Types Overview
20
-
21
- > **📚 For complete error type reference**, see [Module 2: Error Types & Codes](./modules/error-handling-02-error-types.md)
22
-
23
- **Quick Summary:**
24
-
25
- | Error Type | When Thrown | HTTP Status | Auto-Retry |
26
- |------------|-------------|-------------|------------|
27
- | **FluentAPIError** | HTTP errors (4xx, 5xx) | 400, 404, 500, etc. | ✅ Yes (401, 5xx) |
28
- | **AuthenticationError** | OAuth2 auth fails after 3 retries | 401 | N/A (already retried) |
29
- | **GraphQLExecutionError** | GraphQL returns errors in response | 200 (with errors) | ❌ No |
30
-
31
- ### ⚡ How to Capture the Full Error Object
32
-
33
- Standard logging (like `JSON.stringify(error)`) often misses custom fields. Use this helper to capture the full structure for your logs:
34
-
35
- ```typescript
36
- /**
37
- * Helper to extract full error details including HTTP status and response body
38
- */
39
- function extractError(error: any) {
40
- // 1. Use toJSON() if available (e.g. GraphQLExecutionError, IngestionError)
41
- if (typeof error.toJSON === 'function') {
42
- return error.toJSON();
43
- }
44
-
45
- // 2. Manual extraction for FluentAPIError / Standard Errors
46
- return {
47
- name: error.name || 'Error',
48
- message: error.message,
49
- // Critical fields for FluentAPIError
50
- statusCode: error.statusCode,
51
- details: error.details,
52
- code: error.code,
53
- // Optional: stack trace
54
- stack: error.stack
55
- };
56
- }
57
-
58
- // Usage Example
59
- const event = {
60
- name: "UPSERT_PRODUCT",
61
- retailerId: "YOUR_RETAILER_ID",
62
- entityRef: "PC:MASTER:2",
63
- entityType: "PRODUCT_CATALOGUE",
64
- entitySubtype: "MASTER",
65
- rootEntityRef: "PC:MASTER:2",
66
- rootEntityType: "PRODUCT_CATALOGUE",
67
- attributes: {
68
- ref: "G_PROD_WITH_NO_STANDARD",
69
- type: "VARIANT",
70
- status: "ACTIVE",
71
- gtin: "MH01-XS-Orange",
72
- name: "Chaz Kangeroo Hoodie-XS-Orange main",
73
- summary: "<p>test short description</p>",
74
- categoryRefs: ["STANDARD_CATEGORY"],
75
- price: [
76
- { type: "DEFAULT", currency: "USD", value: "52.000000" },
77
- { type: "SPECIAL", currency: "USD", value: "9.000000" }
78
- ],
79
- taxType: {
80
- country: "AU",
81
- group: "Tax Group",
82
- tariff: "Tax Tariff"
83
- }
84
- }
85
- };
86
-
87
- try {
88
- await client.sendEvent(event);
89
- } catch (error) {
90
- const fullError = extractError(error);
91
- console.error('Error Thrown:', JSON.stringify(fullError, null, 2));
92
- }
93
- ```
94
-
95
- **Resulting Output:**
96
-
97
- ```json
98
- {
99
- "name": "FluentAPIError",
100
- "message": "Request failed: 404",
101
- "statusCode": 404,
102
- "details": "No workflow rule matched this event"
103
- }
104
- ```
105
-
106
- [Full error type documentation →](./modules/error-handling-02-error-types.md)
107
-
108
- ---
109
-
110
- ## ❓ Where is the Status Code?
111
-
112
- The location of the HTTP status code depends on whether the call **Succeeded** or **Failed**.
113
-
114
- ### Event API (sendEvent)
115
-
116
- | Outcome | Where is the Status Code? | Example Value |
117
- | :--- | :--- | :--- |
118
- | **✅ Success** | `response.statusCode` | `200`, `201` |
119
- | **❌ Failure** | `error.statusCode` | `400`, `404`, `500` |
120
-
121
- ### GraphQL API (graphql)
122
-
123
- | Outcome | Where is the Status Code? | Example Value |
124
- | :--- | :--- | :--- |
125
- | **✅ Success** | **Not returned** (Implicit 200 OK) | N/A |
126
- | **⚠️ Execution Error** | **Not returned** (Implicit 200 OK) | N/A |
127
- | **❌ HTTP Failure** | `error.statusCode` | `500`, `503` |
128
-
129
- ---
130
-
131
- ## 🔍 Anatomy of an API Call
132
-
133
- This section visualizes exactly what goes **IN** and what comes **OUT** of SDK operations.
134
-
135
- ### 1. Event API Anatomy
136
-
137
- **Scenario:** Sending a Product Upsert event.
138
-
139
- #### A. The Input (Event Payload)
140
- ```typescript
141
- const event = {
142
- name: "UPSERT_PRODUCT",
143
- retailerId: "2",
144
- entityRef: "PC:MASTER:2",
145
- entityType: "PRODUCT_CATALOGUE",
146
- // ...
147
- };
148
- ```
149
-
150
- #### B. The Call
151
- ```typescript
152
- try {
153
- const response = await client.sendEvent(event);
154
- console.log('Success:', response);
155
- } catch (error) {
156
- console.error('Error:', extractError(error));
157
- }
158
- ```
159
-
160
- #### C. The Output (Two Possible Outcomes)
161
-
162
- | Outcome | Structure Returned / Thrown | Status Code Location |
163
- | :--- | :--- | :--- |
164
- | **✅ SUCCESS** | **`EventResponse` Object**<br>Returned by `await` | **`response.statusCode`**<br>(e.g. 200) |
165
- | **❌ FAILURE** | **`FluentAPIError` Object**<br>Caught in `catch` block | **`error.statusCode`**<br>(e.g. 400) |
166
-
167
- ---
168
-
169
- ### 2. GraphQL API Anatomy
170
-
171
- **Scenario:** Querying an Order by Reference.
172
-
173
- #### A. The Input (Query & Variables)
174
- ```typescript
175
- const query = `
176
- query GetOrder($ref: String!) {
177
- order(ref: $ref) {
178
- id
179
- ref
180
- status
181
- }
182
- }
183
- `;
184
-
185
- const variables = {
186
- ref: "ORD-123"
187
- };
188
- ```
189
-
190
- #### B. The Call
191
- ```typescript
192
- try {
193
- const response = await client.graphql({ query, variables });
194
- console.log('Success:', response.data);
195
- } catch (error) {
196
- console.error('Error:', extractError(error));
197
- }
198
- ```
199
-
200
- #### C. The Output (Three Possible Outcomes)
201
-
202
- | Outcome | Structure Returned / Thrown | Status Code Location |
203
- | :--- | :--- | :--- |
204
- | **✅ SUCCESS** | **`GraphQLResponse` Object**<br>Returned by `await` | **None**<br>(Implicit 200 OK) |
205
- | **❌ HTTP FAILURE** | **`FluentAPIError` Object**<br>Caught in `catch` block | **`error.statusCode`**<br>(e.g. 500) |
206
- | **⚠️ EXECUTION ERROR** | **`GraphQLExecutionError` Object**<br>Caught in `catch` block | **None**<br>(Implicit 200 OK) |
207
-
208
- ---
209
-
210
- ## Event API Error Handling
211
-
212
- ### Success Response Structure
213
-
214
- ```typescript
215
- interface EventResponse {
216
- id?: string; // Event ID (if returned)
217
- success: boolean; // Always true for success
218
- status?: number; // Event status from Fluent API (CREATED, COMPLETED, etc.)
219
- statusCode?: number; // HTTP status code (200, 201, 202)
220
- message?: string; // Optional message
221
- }
222
- ```
223
-
224
- ### Basic Try-Catch Pattern
225
-
226
- ```typescript
227
- import { FluentClient, FluentAPIError, AuthenticationError } from '@fluentcommerce/fc-connect-sdk';
228
-
229
- const client = new FluentClient({
230
- baseUrl: 'https://api.fluentcommerce.com',
231
- clientId: 'YOUR_CLIENT_ID',
232
- clientSecret: 'YOUR_CLIENT_SECRET',
233
- username: 'YOUR_USERNAME',
234
- password: 'YOUR_PASSWORD',
235
- retailerId: 'YOUR_RETAILER_ID'
236
- });
237
-
238
- try {
239
- // SUCCESS CASE
240
- const result = await client.sendEvent({
241
- name: 'OrderCancel1',
242
- entityRef: 'G_TEST_FC_POSTMAN_34',
243
- entityType: 'ORDER',
244
- retailerId: '2'
245
- }, 'async');
246
-
247
- console.log('✅ Event sent successfully');
248
- console.log('HTTP Status:', result.statusCode); // 200
249
- console.log('Success:', result.success); // true
250
- console.log('Event ID:', result.id); // evt-123 (if available)
251
-
252
- } catch (error) {
253
- if (error instanceof FluentAPIError) {
254
- // API Error (400, 404, 500, etc.)
255
- console.error('❌ API Error');
256
- console.error('Status:', error.statusCode); // 400, 404, 500, etc.
257
- console.error('Message:', error.message); // "Request failed: 400"
258
- console.error('Details:', error.details); // Response body
259
-
260
- } else if (error instanceof AuthenticationError) {
261
- // Auth failed after 3 retries
262
- console.error('❌ Authentication Error');
263
- console.error('Message:', error.message);
264
- console.error('Status:', error.statusCode); // 401
265
-
266
- } else {
267
- // Unknown error
268
- console.error('❌ Unexpected Error:', error);
269
- }
270
- }
271
- ```
272
-
273
- ### Async Mode - Success Examples
274
-
275
- **Input:**
276
- ```json
277
- {
278
- "name": "OrderCancel1",
279
- "entityRef": "G_TEST_FC_POSTMAN_34",
280
- "entityType": "ORDER",
281
- "retailerId": "2"
282
- }
283
- ```
284
-
285
- **Output (Success):**
286
- ```json
287
- {
288
- "success": true,
289
- "statusCode": 200
290
- }
291
- ```
292
-
293
- **Code:**
294
- ```typescript
295
- const result = await client.sendEvent({
296
- name: 'OrderCancel1',
297
- entityRef: 'G_TEST_FC_POSTMAN_34',
298
- entityType: 'ORDER',
299
- retailerId: '2'
300
- }, 'async');
301
-
302
- // result.success = true
303
- // result.statusCode = 200
304
- ```
305
-
306
- ---
307
-
308
- ### ⚡ SDK Automatic Retry Behavior
309
-
310
- > **IMPORTANT:** The SDK automatically retries certain errors WITHOUT your intervention
311
-
312
- **✅ Automatically Retried (3 attempts with exponential backoff):**
313
- - `401 Unauthorized` - Token refresh attempt
314
- - `500 Internal Server Error` - Transient server issue
315
- - `503 Service Unavailable` - API temporarily overloaded
316
- - Network errors - Connection failures
317
-
318
- **❌ NOT Retried (Fail Immediately):**
319
- - `400 Bad Request` - Invalid event payload
320
- - `404 Not Found` - No workflow matched (sync mode)
321
- - `422 Unprocessable Entity` - Validation failed
322
- - All other 4xx errors
323
-
324
- **Example:**
325
- ```typescript
326
- try {
327
- await client.sendEvent(event);
328
- } catch (error) {
329
- if (error instanceof FluentAPIError && error.statusCode === 500) {
330
- // ⚠️ SDK already retried 3 times with exponential backoff
331
- // This error means all retries failed
332
- console.error('Server error after 3 automatic retries');
333
-
334
- // You may want to implement additional retry logic here
335
- // or send to a dead letter queue
336
- }
337
- }
338
- ```
339
-
340
- ---
341
-
342
- ### Async Mode - Error Examples
343
-
344
- #### Error 1: Invalid Event Name (400)
345
-
346
- **Input:**
347
- ```json
348
- {
349
- "name": "InvalidEventName",
350
- "entityRef": "TEST-123",
351
- "entityType": "ORDER",
352
- "retailerId": "2"
353
- }
354
- ```
355
-
356
- **Error Thrown:**
357
- ```typescript
358
- FluentAPIError {
359
- name: "FluentAPIError",
360
- message: "Request failed: 400",
361
- statusCode: 400,
362
- details: "Bad Request - Invalid event configuration"
363
- }
364
- ```
365
-
366
- **Handling:**
367
- ```typescript
368
- try {
369
- await client.sendEvent({
370
- name: 'InvalidEventName', // ❌ No workflow configured
371
- entityRef: 'TEST-123',
372
- entityType: 'ORDER',
373
- retailerId: '2'
374
- }, 'async');
375
- } catch (error) {
376
- if (error instanceof FluentAPIError && error.statusCode === 400) {
377
- console.error('Invalid event configuration');
378
- // ⚠️ SDK did NOT retry (4xx = client error)
379
- // Fix: Check event name in Rubix workflow configuration
380
- }
381
- }
382
- ```
383
-
384
- ---
385
-
386
- #### Error 2: Missing retailerId (SDK Validation)
387
-
388
- **Input:**
389
- ```json
390
- {
391
- "name": "TEST.EVENT",
392
- "entityRef": "TEST-123",
393
- "entityType": "ORDER"
394
- // ❌ Missing retailerId
395
- }
396
- ```
397
-
398
- **Error Thrown:**
399
- ```typescript
400
- FluentValidationError {
401
- name: "FluentValidationError",
402
- message: "retailerId is required for Event API. Provide it in the event payload or client config.",
403
- code: "VALIDATION_ERROR",
404
- statusCode: 400
405
- }
406
- ```
407
-
408
- **Key Point**: This error is thrown BEFORE the API call (fail-fast).
409
-
410
- **Handling:**
411
- ```typescript
412
- try {
413
- await client.sendEvent({
414
- name: 'TEST.EVENT',
415
- entityRef: 'TEST-123',
416
- entityType: 'ORDER'
417
- // ❌ Missing retailerId
418
- }, 'async');
419
- } catch (error) {
420
- if (error instanceof Error && error.message.includes('retailerId is required')) {
421
- console.error('❌ retailerId validation failed (caught BEFORE API call)');
422
- // Fix: Add retailerId to event or client config
423
- }
424
- }
425
- ```
426
-
427
- ---
428
-
429
- ### Sync Mode - Success and Error Examples
430
-
431
- #### Sync Mode Success
432
-
433
- **Input:**
434
- ```json
435
- {
436
- "name": "OrderCancel1",
437
- "entityRef": "ORDER-SYNC-123",
438
- "entityType": "ORDER",
439
- "retailerId": "2"
440
- }
441
- ```
442
-
443
- **Output (if workflow configured and succeeds):**
444
- ```json
445
- {
446
- "success": true,
447
- "status": "COMPLETED",
448
- "statusCode": 201,
449
- "message": "Workflow completed successfully"
450
- }
451
- ```
452
-
453
- **Code:**
454
- ```typescript
455
- const result = await client.sendEvent({
456
- name: 'OrderCancel1',
457
- entityRef: 'ORDER-SYNC-123',
458
- entityType: 'ORDER',
459
- retailerId: '2'
460
- }, 'sync'); // ← Sync mode waits for workflow
461
-
462
- console.log('Workflow completed:', result.status);
463
- console.log('HTTP Status:', result.statusCode);
464
- ```
465
-
466
- ---
467
-
468
- #### Sync Mode Error: No Workflow Match (404)
469
-
470
- **Input:**
471
- ```json
472
- {
473
- "name": "OrderCancel1",
474
- "entityRef": "SYNC-NO-MATCH",
475
- "entityType": "ORDER",
476
- "retailerId": "2"
477
- }
478
- ```
479
-
480
- **Error Thrown:**
481
- ```typescript
482
- FluentAPIError {
483
- name: "FluentAPIError",
484
- message: "Request failed: 404",
485
- statusCode: 404,
486
- details: "No workflow rule matched this event"
487
- }
488
- ```
489
-
490
- **Handling:**
491
- ```typescript
492
- try {
493
- await client.sendEvent({
494
- name: 'OrderCancel1',
495
- entityRef: 'SYNC-NO-MATCH',
496
- entityType: 'ORDER',
497
- retailerId: '2'
498
- }, 'sync');
499
- } catch (error) {
500
- if (error instanceof FluentAPIError && error.statusCode === 404) {
501
- console.error('No workflow rule matched (sync mode detected this)');
502
- // ⚠️ Async mode would return 200 (doesn't wait for workflow)
503
- // ✅ Sync mode detected the failure immediately
504
- }
505
- }
506
- ```
507
-
508
- ---
509
-
510
- ### Batch Processing with Per-Event Error Handling
511
-
512
- ```typescript
513
- interface EventResult {
514
- sku: string;
515
- success: boolean;
516
- statusCode?: number;
517
- error?: string;
518
- }
519
-
520
- async function processProducts(products: Product[]): Promise<EventResult[]> {
521
- const results: EventResult[] = [];
522
-
523
- for (const product of products) {
524
- try {
525
- const response = await client.sendEvent({
526
- name: 'PRODUCT.UPSERT',
527
- entityType: 'PRODUCT',
528
- entityRef: product.sku,
529
- retailerId: '2',
530
- attributes: product
531
- }, 'async');
532
-
533
- // SUCCESS
534
- results.push({
535
- sku: product.sku,
536
- success: true,
537
- statusCode: response.statusCode
538
- });
539
-
540
- console.log(`✅ ${product.sku} - HTTP ${response.statusCode}`);
541
-
542
- } catch (error) {
543
- if (error instanceof FluentAPIError) {
544
- // API ERROR (SDK already retried 401/5xx)
545
- results.push({
546
- sku: product.sku,
547
- success: false,
548
- error: `HTTP ${error.statusCode}: ${error.message}`
549
- });
550
-
551
- console.error(`❌ ${product.sku} - ${error.statusCode}: ${error.message}`);
552
-
553
- // Handle specific error codes
554
- if (error.statusCode === 400) {
555
- console.error(' → Invalid product data');
556
- } else if (error.statusCode === 422) {
557
- console.error(' → Validation failed');
558
- } else if (error.statusCode === 500) {
559
- console.error(' → Server error (SDK already retried 3x)');
560
- }
561
-
562
- } else if (error instanceof AuthenticationError) {
563
- // AUTH FAILED (after 3 retries)
564
- console.error(`❌ Auth failed: ${error.message}`);
565
- // Stop processing - credentials are invalid
566
- break;
567
-
568
- } else {
569
- // UNEXPECTED ERROR
570
- results.push({
571
- sku: product.sku,
572
- success: false,
573
- error: error.message
574
- });
575
- }
576
- }
577
- }
578
-
579
- return results;
580
- }
581
- ```
582
-
583
- ---
584
-
585
- ## GraphQL Error Handling
586
-
587
- ### Success Response Structure
588
-
589
- ```typescript
590
- interface GraphQLResponse {
591
- data: any; // Query/mutation result
592
- errors?: undefined; // No errors on success
593
- }
594
- ```
595
-
596
- ### Error Response Structure
597
-
598
- When GraphQL returns errors, SDK throws `GraphQLExecutionError`:
599
-
600
- ```typescript
601
- {
602
- name: 'GraphQLExecutionError',
603
- message: string, // First error message
604
- graphqlErrors: Array<{
605
- message: string,
606
- locations?: Array<{ line: number, column: number }>,
607
- path?: Array<string | number>,
608
- extensions?: { ... }
609
- }>,
610
- query: string,
611
- variables?: { ... }
612
- }
613
- ```
614
-
615
- ### Basic Try-Catch Pattern
616
-
617
- ```typescript
618
- try {
619
- // SUCCESS CASE
620
- const result = await client.graphql({
621
- query: `
622
- query GetOrder($ref: String!) {
623
- order(ref: $ref) {
624
- id
625
- ref
626
- status
627
- }
628
- }
629
- `,
630
- variables: { ref: 'ORDER-123' }
631
- });
632
-
633
- console.log('✅ GraphQL query succeeded');
634
- console.log('Data:', result.data);
635
- console.log('Order:', result.data.order);
636
-
637
- } catch (error) {
638
- if (error instanceof GraphQLExecutionError) {
639
- // GraphQL returned errors
640
- console.error('❌ GraphQL Execution Error');
641
- console.error('Message:', error.message);
642
- console.error('All errors:', error.getErrorMessages());
643
- console.error('Query:', error.query);
644
-
645
- // Check for specific errors
646
- const errorMessages = error.getErrorMessages();
647
- if (errorMessages.some(msg => msg.includes('invalidField'))) {
648
- console.error(' → Invalid field in query');
649
- }
650
-
651
- } else if (error instanceof FluentAPIError) {
652
- // HTTP error (400, 500, etc.)
653
- console.error('❌ API Error');
654
- console.error('Status:', error.statusCode);
655
- console.error('Message:', error.message);
656
-
657
- } else if (error instanceof AuthenticationError) {
658
- // Auth failed
659
- console.error('❌ Authentication failed');
660
-
661
- } else {
662
- console.error('❌ Unexpected error:', error);
663
- }
664
- }
665
- ```
666
-
667
- ### GraphQL Success Example
668
-
669
- **Input:**
670
- ```graphql
671
- query GetOrder($ref: String!) {
672
- order(ref: $ref) {
673
- id
674
- ref
675
- status
676
- }
677
- }
678
- ```
679
-
680
- **Variables:**
681
- ```json
682
- {
683
- "ref": "ORDER-123"
684
- }
685
- ```
686
-
687
- **Output (Success):**
688
- ```json
689
- {
690
- "data": {
691
- "order": {
692
- "id": "ORDER-123",
693
- "ref": "ORD-2024-123",
694
- "status": "CREATED"
695
- }
696
- }
697
- }
698
- ```
699
-
700
- **Code:**
701
- ```typescript
702
- const result = await client.graphql({
703
- query: `query GetOrder($ref: String!) { order(ref: $ref) { id ref status } }`,
704
- variables: { ref: 'ORDER-123' }
705
- });
706
-
707
- console.log('Order ID:', result.data.order.id);
708
- console.log('Order Ref:', result.data.order.ref);
709
- console.log('Order Status:', result.data.order.status);
710
- ```
711
-
712
- ---
713
-
714
- ### GraphQL Error Examples
715
-
716
- #### Error 1: Invalid Field
717
-
718
- **Input:**
719
- ```graphql
720
- query GetOrder {
721
- order(ref: "123") {
722
- id
723
- invalidField # ❌ Field doesn't exist
724
- }
725
- }
726
- ```
727
-
728
- **Error Thrown:**
729
- ```typescript
730
- GraphQLExecutionError {
731
- name: "GraphQLExecutionError",
732
- message: "Field \"invalidField\" doesn't exist on type \"Order\"",
733
- graphqlErrors: [
734
- {
735
- message: "Field \"invalidField\" doesn't exist on type \"Order\"",
736
- locations: [{ line: 4, column: 5 }],
737
- extensions: { ... }
738
- }
739
- ],
740
- query: "query GetOrder { ... }"
741
- }
742
- ```
743
-
744
- **Handling:**
745
- ```typescript
746
- try {
747
- await client.graphql({
748
- query: `query GetOrder { order(ref: "123") { id invalidField } }`
749
- });
750
- } catch (error) {
751
- if (error instanceof GraphQLExecutionError) {
752
- console.error('GraphQL Error:', error.message);
753
-
754
- // Get all error messages
755
- const messages = error.getErrorMessages();
756
- console.error('All errors:', messages);
757
-
758
- // Check for specific error
759
- const errorMessages = error.getErrorMessages();
760
- if (errorMessages.some(msg => msg.includes('invalidField'))) {
761
- console.error('Invalid field in query - check schema');
762
- }
763
- }
764
- }
765
- ```
766
-
767
- ---
768
-
769
- #### Error 2: Syntax Error
770
-
771
- **Input:**
772
- ```graphql
773
- query GetOrder {
774
- order(ref: "123" # ❌ Missing closing parenthesis
775
- id
776
- ref
777
- }
778
- }
779
- ```
780
-
781
- **Error Thrown:**
782
- ```typescript
783
- FluentAPIError {
784
- name: "FluentAPIError",
785
- message: "Request failed: 400",
786
- statusCode: 400,
787
- details: {
788
- errors: [
789
- {
790
- message: "Syntax Error: Expected ')', found Name 'id'",
791
- locations: [{ line: 3, column: 5 }]
792
- }
793
- ]
794
- }
795
- }
796
- ```
797
-
798
- **Note**: Syntax errors throw `FluentAPIError` (400), not `GraphQLExecutionError`.
799
-
800
- ---
801
-
802
- ### GraphQL with Pagination
803
-
804
- ```typescript
805
- try {
806
- const result = await client.graphql({
807
- query: `
808
- query GetOrders {
809
- orders(first: 50) {
810
- edges {
811
- node {
812
- id
813
- ref
814
- status
815
- }
816
- }
817
- pageInfo {
818
- hasNextPage
819
- endCursor
820
- }
821
- }
822
- }
823
- `,
824
- pagination: {
825
- enabled: true,
826
- maxPages: 10,
827
- maxRecords: 500
828
- }
829
- });
830
-
831
- console.log('✅ Fetched', result.data.orders.edges.length, 'orders');
832
- console.log('Total pages fetched:', result.extensions?.autoPagination?.totalPages);
833
-
834
- } catch (error) {
835
- if (error instanceof GraphQLExecutionError) {
836
- console.error('GraphQL error during pagination:', error.message);
837
- } else if (error instanceof FluentAPIError) {
838
- console.error('API error during pagination:', error.statusCode);
839
- }
840
- }
841
- ```
842
-
843
- ---
844
-
845
- ## Batch API Error Handling
846
-
847
- ### Success Response Structure
848
-
849
- ```typescript
850
- interface FluentBatchResponse {
851
- id: string; // Batch ID
852
- jobId: string; // Job ID
853
- status: string; // Batch status (CREATED, SUBMITTED, PROCESSING, COMPLETED, FAILED)
854
- processedEntities?: number; // Number of entities processed
855
- totalEntities?: number; // Total entities in batch
856
- createdAt?: string; // ISO timestamp
857
- updatedAt?: string; // ISO timestamp
858
- errors?: Array<{ // Failed entity details (if any)
859
- code: string;
860
- message: string;
861
- entityIndex?: number;
862
- }>;
863
- }
864
- ```
865
-
866
- ### Basic Try-Catch Pattern
867
-
868
- ```typescript
869
- try {
870
- // SUCCESS CASE
871
- const batch = await client.sendBatch('job-123', {
872
- entities: [
873
- { id: '1', sku: 'SKU-001', name: 'Product 1' },
874
- { id: '2', sku: 'SKU-002', name: 'Product 2' }
875
- ],
876
- action: 'UPSERT'
877
- });
878
-
879
- console.log('✅ Batch sent successfully');
880
- console.log('Batch ID:', batch.id);
881
- console.log('Status:', batch.status);
882
-
883
- } catch (error) {
884
- if (error instanceof FluentAPIError) {
885
- console.error('❌ Batch Error');
886
- console.error('Status:', error.statusCode);
887
- console.error('Message:', error.message);
888
-
889
- // Common errors
890
- if (error.statusCode === 404) {
891
- console.error(' → Job not found or expired');
892
- } else if (error.statusCode === 400) {
893
- console.error(' → Invalid batch payload');
894
- } else if (error.statusCode === 500) {
895
- console.error(' → Server error (SDK already retried 3x)');
896
- }
897
- }
898
- }
899
- ```
900
-
901
- ### Batch Success Example
902
-
903
- **Input:**
904
- ```typescript
905
- await client.sendBatch('job-123', {
906
- entities: [
907
- { id: '1', sku: 'SKU-001', name: 'Product 1', price: 19.99 },
908
- { id: '2', sku: 'SKU-002', name: 'Product 2', price: 29.99 }
909
- ],
910
- action: 'UPSERT'
911
- });
912
- ```
913
-
914
- **Output (Success):**
915
- ```json
916
- {
917
- "id": "batch-456",
918
- "jobId": "job-123",
919
- "status": "CREATED",
920
- "processedEntities": 2,
921
- "totalEntities": 2
922
- }
923
- ```
924
-
925
- ---
926
-
927
- ### Batch Error Examples
928
-
929
- #### Error 1: Job Expired (404)
930
-
931
- **Input:**
932
- ```typescript
933
- await client.sendBatch('job-expired-123', {
934
- entities: [...],
935
- action: 'UPSERT'
936
- });
937
- ```
938
-
939
- **Error Thrown:**
940
- ```typescript
941
- FluentAPIError {
942
- name: "FluentAPIError",
943
- message: "Request failed: 404",
944
- statusCode: 404,
945
- details: "Job not found or expired"
946
- }
947
- ```
948
-
949
- **Handling:**
950
- ```typescript
951
- try {
952
- await client.sendBatch(jobId, { entities, action: 'UPSERT' });
953
- } catch (error) {
954
- if (error instanceof FluentAPIError && error.statusCode === 404) {
955
- console.error('Job expired - recreating...');
956
-
957
- // Recreate job and retry
958
- const newJob = await client.createJob({
959
- name: 'inventory-sync',
960
- retailerId: '2'
961
- });
962
-
963
- await client.sendBatch(newJob.id, { entities, action: 'UPSERT' });
964
- }
965
- }
966
- ```
967
-
968
- ---
969
-
970
- #### Error 2: Invalid Batch Payload (400)
971
-
972
- **Input:**
973
- ```typescript
974
- await client.sendBatch('job-123', {
975
- entities: [], // ❌ Empty entities array
976
- action: 'UPSERT'
977
- });
978
- ```
979
-
980
- **Error Thrown:**
981
- ```typescript
982
- FluentAPIError {
983
- name: "FluentAPIError",
984
- message: "Request failed: 400",
985
- statusCode: 400,
986
- details: "Batch must contain at least one entity"
987
- }
988
- ```
989
-
990
- ---
991
-
992
- ### Batch Processing with Retry
993
-
994
- ```typescript
995
- async function sendBatchWithRetry(
996
- jobId: string,
997
- entities: any[],
998
- maxRetries: number = 3
999
- ): Promise<FluentBatchResponse> {
1000
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
1001
- try {
1002
- const batch = await client.sendBatch(jobId, {
1003
- entities,
1004
- action: 'UPSERT'
1005
- });
1006
-
1007
- console.log(`✅ Batch sent (attempt ${attempt + 1})`);
1008
- return batch;
1009
-
1010
- } catch (error) {
1011
- if (error instanceof FluentAPIError) {
1012
- if (error.statusCode === 404 && attempt < maxRetries) {
1013
- // Job expired - recreate
1014
- console.log(`⚠️ Job expired, recreating... (attempt ${attempt + 1})`);
1015
-
1016
- const newJob = await client.createJob({
1017
- name: 'inventory-sync',
1018
- retailerId: '2'
1019
- });
1020
-
1021
- jobId = newJob.id;
1022
- // Retry with new job ID
1023
- continue;
1024
-
1025
- } else if (error.statusCode === 500 && attempt < maxRetries) {
1026
- // Server error - SDK already retried 3x
1027
- console.log(`⚠️ Server error, waiting before retry...`);
1028
- await new Promise(resolve => setTimeout(resolve, 5000));
1029
- continue;
1030
-
1031
- } else {
1032
- // Non-retryable error or max retries reached
1033
- throw error;
1034
- }
1035
- }
1036
- throw error;
1037
- }
1038
- }
1039
-
1040
- throw new Error('Max retries exceeded');
1041
- }
1042
- ```
1043
-
1044
- ---
1045
-
1046
- ## Job API Error Handling
1047
-
1048
- ### Success Response Structure
1049
-
1050
- ```typescript
1051
- interface FluentJobResponse {
1052
- id: string; // Job ID
1053
- name: string; // Job name
1054
- retailerId: string;
1055
- status?: string; // Job status (CREATED, ACTIVE, PROCESSING, COMPLETED, FAILED)
1056
- meta?: FluentJobMetadata; // Job metadata (preprocessing, source, etc.)
1057
- createdAt?: string; // ISO timestamp
1058
- updatedAt?: string; // ISO timestamp
1059
- }
1060
- ```
1061
-
1062
- ### Basic Try-Catch Pattern
1063
-
1064
- ```typescript
1065
- try {
1066
- // SUCCESS CASE
1067
- const job = await client.createJob({
1068
- name: 'inventory-sync',
1069
- retailerId: '2'
1070
- });
1071
-
1072
- console.log('✅ Job created successfully');
1073
- console.log('Job ID:', job.id);
1074
- console.log('Status:', job.status);
1075
- console.log('Created:', job.createdAt);
1076
-
1077
- } catch (error) {
1078
- if (error instanceof FluentAPIError) {
1079
- console.error('❌ Job Creation Error');
1080
- console.error('Status:', error.statusCode);
1081
- console.error('Message:', error.message);
1082
-
1083
- if (error.statusCode === 400) {
1084
- console.error(' → Invalid job payload');
1085
- } else if (error.statusCode === 403) {
1086
- console.error(' → Permission denied');
1087
- }
1088
- }
1089
- }
1090
- ```
1091
-
1092
- ### Job Success Example
1093
-
1094
- **Input:**
1095
- ```typescript
1096
- await client.createJob({
1097
- name: 'product-import-batch',
1098
- retailerId: '2'
1099
- });
1100
- ```
1101
-
1102
- **Output (Success):**
1103
- ```json
1104
- {
1105
- "id": "job-789",
1106
- "name": "product-import-batch",
1107
- "status": "CREATED",
1108
- "retailerId": "2",
1109
- "createdAt": "2025-01-19T10:30:00Z",
1110
- "updatedAt": "2025-01-19T10:30:00Z"
1111
- }
1112
- ```
1113
-
1114
- ---
1115
-
1116
- ### Job Status Checking
1117
-
1118
- **Response Structure:**
1119
- ```typescript
1120
- interface FluentJobStatus {
1121
- id: string;
1122
- status: string; // Job status (CREATED, ACTIVE, PROCESSING, COMPLETED, FAILED)
1123
- progress?: number; // Progress percentage (0-100)
1124
- message?: string; // Status message
1125
- completedAt?: string; // ISO timestamp when completed
1126
- failedAt?: string; // ISO timestamp when failed
1127
- errors?: Array<{ // Error details (if failed)
1128
- code: string;
1129
- message: string;
1130
- }>;
1131
- }
1132
- ```
1133
-
1134
- **Example:**
1135
- ```typescript
1136
- try {
1137
- const status = await client.getJobStatus('job-789');
1138
-
1139
- console.log('Job Status:', status.status);
1140
- console.log('Progress:', status.progress);
1141
-
1142
- if (status.status === 'FAILED') {
1143
- console.warn('⚠️ Job failed - check errors');
1144
- console.error('Errors:', status.errors);
1145
- }
1146
-
1147
- } catch (error) {
1148
- if (error instanceof FluentAPIError && error.statusCode === 404) {
1149
- console.error('Job not found');
1150
- }
1151
- }
1152
- ```
1153
-
1154
- ---
1155
-
1156
- ## Common Patterns
1157
-
1158
- ### Pattern 1: Centralized Error Handler
1159
-
1160
- ```typescript
1161
- function handleSDKError(error: unknown, context: string): void {
1162
- if (error instanceof FluentAPIError) {
1163
- console.error(`[${context}] API Error:`, {
1164
- status: error.statusCode,
1165
- message: error.message,
1166
- details: error.details
1167
- });
1168
-
1169
- // Log to monitoring service
1170
- logger.error('Fluent API Error', {
1171
- context,
1172
- status: error.statusCode,
1173
- message: error.message
1174
- });
1175
-
1176
- } else if (error instanceof GraphQLExecutionError) {
1177
- console.error(`[${context}] GraphQL Error:`, {
1178
- message: error.message,
1179
- errors: error.getErrorMessages(),
1180
- query: error.query
1181
- });
1182
-
1183
- logger.error('GraphQL Execution Error', {
1184
- context,
1185
- errors: error.getErrorMessages()
1186
- });
1187
-
1188
- } else if (error instanceof AuthenticationError) {
1189
- console.error(`[${context}] Auth Error:`, {
1190
- message: error.message,
1191
- status: error.statusCode
1192
- });
1193
-
1194
- // Alert - credentials may be invalid
1195
- alertService.send('Fluent Auth Failure', error.message);
1196
-
1197
- } else {
1198
- console.error(`[${context}] Unexpected Error:`, error);
1199
- logger.error('Unexpected SDK Error', { context, error });
1200
- }
1201
- }
1202
-
1203
- // Usage
1204
- try {
1205
- await client.sendEvent(event);
1206
- } catch (error) {
1207
- handleSDKError(error, 'Event API');
1208
- throw error; // Re-throw if needed
1209
- }
1210
- ```
1211
-
1212
- ---
1213
-
1214
- ### Pattern 2: Retry with Backoff
1215
-
1216
- ```typescript
1217
- async function retryWithBackoff<T>(
1218
- operation: () => Promise<T>,
1219
- maxRetries: number = 3,
1220
- baseDelay: number = 1000
1221
- ): Promise<T> {
1222
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
1223
- try {
1224
- return await operation();
1225
- } catch (error) {
1226
- if (error instanceof FluentAPIError) {
1227
- // Only retry 5xx server errors
1228
- if (error.statusCode >= 500 && attempt < maxRetries) {
1229
- const delay = baseDelay * Math.pow(2, attempt);
1230
- console.log(`⚠️ Server error, retrying in ${delay}ms...`);
1231
- await new Promise(resolve => setTimeout(resolve, delay));
1232
- continue;
1233
- }
1234
- }
1235
- throw error;
1236
- }
1237
- }
1238
- throw new Error('Max retries exceeded');
1239
- }
1240
-
1241
- // Usage
1242
- const result = await retryWithBackoff(
1243
- () => client.sendEvent(event),
1244
- 3,
1245
- 1000
1246
- );
1247
- ```
1248
-
1249
- ---
1250
-
1251
- ### Pattern 3: Batch with Dead Letter Queue
1252
-
1253
- ```typescript
1254
- interface ProcessingResult {
1255
- successful: any[];
1256
- failed: Array<{ item: any; error: string }>;
1257
- }
1258
-
1259
- async function processBatchWithDLQ(
1260
- items: any[]
1261
- ): Promise<ProcessingResult> {
1262
- const result: ProcessingResult = {
1263
- successful: [],
1264
- failed: []
1265
- };
1266
-
1267
- for (const item of items) {
1268
- try {
1269
- const response = await client.sendEvent({
1270
- name: 'PRODUCT.UPSERT',
1271
- entityType: 'PRODUCT',
1272
- entityRef: item.sku,
1273
- retailerId: '2',
1274
- attributes: item
1275
- });
1276
-
1277
- result.successful.push(item);
1278
-
1279
- } catch (error) {
1280
- if (error instanceof FluentAPIError) {
1281
- // Add to dead letter queue
1282
- result.failed.push({
1283
- item,
1284
- error: `HTTP ${error.statusCode}: ${error.message}`
1285
- });
1286
-
1287
- // Log to DLQ for manual review
1288
- await deadLetterQueue.add({
1289
- item,
1290
- error: error.message,
1291
- status: error.statusCode,
1292
- timestamp: new Date().toISOString()
1293
- });
1294
- }
1295
- }
1296
- }
1297
-
1298
- return result;
1299
- }
1300
- ```
1301
-
1302
- ---
1303
-
1304
- ## Live Examples
1305
-
1306
- ### Test Environment
1307
-
1308
- ```yaml
1309
- Base URL: https://api.fluentcommerce.com
1310
- Retailer ID: YOUR_RETAILER_ID
1311
- Client ID: YOUR_CLIENT_ID
1312
- ```
1313
-
1314
- ### Example 1: Event API Success
1315
-
1316
- **Code:**
1317
- ```typescript
1318
- const client = new FluentClient({
1319
- baseUrl: 'https://api.fluentcommerce.com',
1320
- clientId: 'YOUR_CLIENT_ID',
1321
- clientSecret: 'YOUR_CLIENT_SECRET',
1322
- username: 'YOUR_USERNAME',
1323
- password: 'YOUR_PASSWORD',
1324
- retailerId: 'YOUR_RETAILER_ID'
1325
- });
1326
-
1327
- const result = await client.sendEvent({
1328
- name: 'OrderCancel1',
1329
- entityRef: 'G_TEST_FC_POSTMAN_34',
1330
- entityType: 'ORDER',
1331
- retailerId: '2'
1332
- }, 'async');
1333
-
1334
- console.log('Success:', result.success); // true
1335
- console.log('HTTP Status:', result.statusCode); // 200
1336
- ```
1337
-
1338
- **Console Output:**
1339
- ```
1340
- Success: true
1341
- HTTP Status: 200
1342
- ```
1343
-
1344
- ---
1345
-
1346
- ### Example 2: Event API Error (400)
1347
-
1348
- **Code:**
1349
- ```typescript
1350
- try {
1351
- await client.sendEvent({
1352
- name: 'InvalidEventName',
1353
- entityRef: 'TEST-123',
1354
- entityType: 'ORDER',
1355
- retailerId: '2'
1356
- }, 'async');
1357
- } catch (error) {
1358
- if (error instanceof FluentAPIError) {
1359
- console.error('Error Status:', error.statusCode);
1360
- console.error('Error Message:', error.message);
1361
- }
1362
- }
1363
- ```
1364
-
1365
- **Console Output:**
1366
- ```
1367
- Error Status: 400
1368
- Error Message: Request failed: 400
1369
- ```
1370
-
1371
- ---
1372
-
1373
- ### Example 3: Sync Mode - No Workflow Match (404)
1374
-
1375
- **Code:**
1376
- ```typescript
1377
- try {
1378
- await client.sendEvent({
1379
- name: 'OrderCancel1',
1380
- entityRef: 'SYNC-NO-MATCH',
1381
- entityType: 'ORDER',
1382
- retailerId: '2'
1383
- }, 'sync');
1384
- } catch (error) {
1385
- if (error instanceof FluentAPIError) {
1386
- console.error('Sync mode detected workflow failure');
1387
- console.error('Status:', error.statusCode); // 404
1388
- }
1389
- }
1390
- ```
1391
-
1392
- **Console Output:**
1393
- ```
1394
- Sync mode detected workflow failure
1395
- Status: 404
1396
- ```
1397
-
1398
- ---
1399
-
1400
- ## Summary Table
1401
-
1402
- | API | Success Type | Error Type | SDK Retries | Notes |
1403
- |-----|-------------|------------|-------------|-------|
1404
- | **Event API** | `EventResponse` | `FluentAPIError`, `AuthenticationError` | ✅ 401 (3x), 5xx (3x) | Async = fast, Sync = detects workflow errors |
1405
- | **GraphQL** | `GraphQLResponse` | `GraphQLExecutionError`, `FluentAPIError`, `AuthenticationError` | ✅ 401 (3x), 5xx (3x) | GraphQL errors vs HTTP errors |
1406
- | **Batch API** | `FluentBatchResponse` | `FluentAPIError`, `AuthenticationError` | ✅ 401 (3x), 5xx (3x) | Watch for job expiry (404) |
1407
- | **Job API** | `FluentJobResponse` | `FluentAPIError`, `AuthenticationError` | ✅ 401 (3x), 5xx (3x) | Jobs expire after 1 hour |
1408
-
1409
- ---
1410
-
1411
- ## Quick Reference
1412
-
1413
- ### When to Use Try-Catch
1414
-
1415
- ✅ **Always use try-catch** for:
1416
- - `sendEvent()`
1417
- - `graphql()`
1418
- - `sendBatch()`
1419
- - `createJob()`
1420
- - `getJobStatus()`
1421
- - Any SDK method that makes API calls
1422
-
1423
- ### Error Handling Checklist
1424
-
1425
- - [ ] Catch `FluentAPIError` for HTTP errors
1426
- - [ ] Catch `AuthenticationError` for auth failures
1427
- - [ ] Catch `GraphQLExecutionError` for GraphQL errors
1428
- - [ ] Check `error.statusCode` to determine error type
1429
- - [ ] Log errors with context for debugging
1430
- - [ ] Implement retry logic for transient errors (5xx)
1431
- - [ ] Use dead letter queue for persistent failures
1432
- - [ ] Alert on authentication failures
1433
-
1434
- ---
1435
-
1436
- **SDK Version**: 0.1.46
1437
- **Date**: 2025-01-19
1
+ # Comprehensive Error Handling Guide
2
+
3
+ > **Complete guide** to error handling across GraphQL, Event API, Batch API, and Job API with live examples
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Error Types Overview](#error-types-overview)
8
+ 2. [Where is the Status Code?](#where-is-the-status-code)
9
+ 3. [Anatomy of an API Call](#anatomy-of-an-api-call)
10
+ 4. [Event API Error Handling](#event-api-error-handling)
11
+ 5. [GraphQL Error Handling](#graphql-error-handling)
12
+ 6. [Batch API Error Handling](#batch-api-error-handling)
13
+ 7. [Job API Error Handling](#job-api-error-handling)
14
+ 8. [Common Patterns](#common-patterns)
15
+ 9. [Live Examples](#live-examples)
16
+
17
+ ---
18
+
19
+ ## Error Types Overview
20
+
21
+ > **📚 For complete error type reference**, see [Module 2: Error Types & Codes](./modules/error-handling-02-error-types.md)
22
+
23
+ **Quick Summary:**
24
+
25
+ | Error Type | When Thrown | HTTP Status | Auto-Retry |
26
+ |------------|-------------|-------------|------------|
27
+ | **FluentAPIError** | HTTP errors (4xx, 5xx) | 400, 404, 500, etc. | ✅ Yes (401, 5xx) |
28
+ | **AuthenticationError** | OAuth2 auth fails after 3 retries | 401 | N/A (already retried) |
29
+ | **GraphQLExecutionError** | GraphQL returns errors in response | 200 (with errors) | ❌ No |
30
+
31
+ ### ⚡ How to Capture the Full Error Object
32
+
33
+ Standard logging (like `JSON.stringify(error)`) often misses custom fields. Use this helper to capture the full structure for your logs:
34
+
35
+ ```typescript
36
+ /**
37
+ * Helper to extract full error details including HTTP status and response body
38
+ */
39
+ function extractError(error: any) {
40
+ // 1. Use toJSON() if available (e.g. GraphQLExecutionError, IngestionError)
41
+ if (typeof error.toJSON === 'function') {
42
+ return error.toJSON();
43
+ }
44
+
45
+ // 2. Manual extraction for FluentAPIError / Standard Errors
46
+ return {
47
+ name: error.name || 'Error',
48
+ message: error.message,
49
+ // Critical fields for FluentAPIError
50
+ statusCode: error.statusCode,
51
+ details: error.details,
52
+ code: error.code,
53
+ // Optional: stack trace
54
+ stack: error.stack
55
+ };
56
+ }
57
+
58
+ // Usage Example
59
+ const event = {
60
+ name: "UPSERT_PRODUCT",
61
+ retailerId: "YOUR_RETAILER_ID",
62
+ entityRef: "PC:MASTER:2",
63
+ entityType: "PRODUCT_CATALOGUE",
64
+ entitySubtype: "MASTER",
65
+ rootEntityRef: "PC:MASTER:2",
66
+ rootEntityType: "PRODUCT_CATALOGUE",
67
+ attributes: {
68
+ ref: "G_PROD_WITH_NO_STANDARD",
69
+ type: "VARIANT",
70
+ status: "ACTIVE",
71
+ gtin: "MH01-XS-Orange",
72
+ name: "Chaz Kangeroo Hoodie-XS-Orange main",
73
+ summary: "<p>test short description</p>",
74
+ categoryRefs: ["STANDARD_CATEGORY"],
75
+ price: [
76
+ { type: "DEFAULT", currency: "USD", value: "52.000000" },
77
+ { type: "SPECIAL", currency: "USD", value: "9.000000" }
78
+ ],
79
+ taxType: {
80
+ country: "AU",
81
+ group: "Tax Group",
82
+ tariff: "Tax Tariff"
83
+ }
84
+ }
85
+ };
86
+
87
+ try {
88
+ await client.sendEvent(event);
89
+ } catch (error) {
90
+ const fullError = extractError(error);
91
+ console.error('Error Thrown:', JSON.stringify(fullError, null, 2));
92
+ }
93
+ ```
94
+
95
+ **Resulting Output:**
96
+
97
+ ```json
98
+ {
99
+ "name": "FluentAPIError",
100
+ "message": "Request failed: 404",
101
+ "statusCode": 404,
102
+ "details": "No workflow rule matched this event"
103
+ }
104
+ ```
105
+
106
+ [Full error type documentation →](./modules/error-handling-02-error-types.md)
107
+
108
+ ---
109
+
110
+ ## ❓ Where is the Status Code?
111
+
112
+ The location of the HTTP status code depends on whether the call **Succeeded** or **Failed**.
113
+
114
+ ### Event API (sendEvent)
115
+
116
+ | Outcome | Where is the Status Code? | Example Value |
117
+ | :--- | :--- | :--- |
118
+ | **✅ Success** | `response.statusCode` | `200`, `201` |
119
+ | **❌ Failure** | `error.statusCode` | `400`, `404`, `500` |
120
+
121
+ ### GraphQL API (graphql)
122
+
123
+ | Outcome | Where is the Status Code? | Example Value |
124
+ | :--- | :--- | :--- |
125
+ | **✅ Success** | **Not returned** (Implicit 200 OK) | N/A |
126
+ | **⚠️ Execution Error** | **Not returned** (Implicit 200 OK) | N/A |
127
+ | **❌ HTTP Failure** | `error.statusCode` | `500`, `503` |
128
+
129
+ ---
130
+
131
+ ## 🔍 Anatomy of an API Call
132
+
133
+ This section visualizes exactly what goes **IN** and what comes **OUT** of SDK operations.
134
+
135
+ ### 1. Event API Anatomy
136
+
137
+ **Scenario:** Sending a Product Upsert event.
138
+
139
+ #### A. The Input (Event Payload)
140
+ ```typescript
141
+ const event = {
142
+ name: "UPSERT_PRODUCT",
143
+ retailerId: "2",
144
+ entityRef: "PC:MASTER:2",
145
+ entityType: "PRODUCT_CATALOGUE",
146
+ // ...
147
+ };
148
+ ```
149
+
150
+ #### B. The Call
151
+ ```typescript
152
+ try {
153
+ const response = await client.sendEvent(event);
154
+ console.log('Success:', response);
155
+ } catch (error) {
156
+ console.error('Error:', extractError(error));
157
+ }
158
+ ```
159
+
160
+ #### C. The Output (Two Possible Outcomes)
161
+
162
+ | Outcome | Structure Returned / Thrown | Status Code Location |
163
+ | :--- | :--- | :--- |
164
+ | **✅ SUCCESS** | **`EventResponse` Object**<br>Returned by `await` | **`response.statusCode`**<br>(e.g. 200) |
165
+ | **❌ FAILURE** | **`FluentAPIError` Object**<br>Caught in `catch` block | **`error.statusCode`**<br>(e.g. 400) |
166
+
167
+ ---
168
+
169
+ ### 2. GraphQL API Anatomy
170
+
171
+ **Scenario:** Querying an Order by Reference.
172
+
173
+ #### A. The Input (Query & Variables)
174
+ ```typescript
175
+ const query = `
176
+ query GetOrder($ref: String!) {
177
+ order(ref: $ref) {
178
+ id
179
+ ref
180
+ status
181
+ }
182
+ }
183
+ `;
184
+
185
+ const variables = {
186
+ ref: "ORD-123"
187
+ };
188
+ ```
189
+
190
+ #### B. The Call
191
+ ```typescript
192
+ try {
193
+ const response = await client.graphql({ query, variables });
194
+ console.log('Success:', response.data);
195
+ } catch (error) {
196
+ console.error('Error:', extractError(error));
197
+ }
198
+ ```
199
+
200
+ #### C. The Output (Three Possible Outcomes)
201
+
202
+ | Outcome | Structure Returned / Thrown | Status Code Location |
203
+ | :--- | :--- | :--- |
204
+ | **✅ SUCCESS** | **`GraphQLResponse` Object**<br>Returned by `await` | **None**<br>(Implicit 200 OK) |
205
+ | **❌ HTTP FAILURE** | **`FluentAPIError` Object**<br>Caught in `catch` block | **`error.statusCode`**<br>(e.g. 500) |
206
+ | **⚠️ EXECUTION ERROR** | **`GraphQLExecutionError` Object**<br>Caught in `catch` block | **None**<br>(Implicit 200 OK) |
207
+
208
+ ---
209
+
210
+ ## Event API Error Handling
211
+
212
+ ### Success Response Structure
213
+
214
+ ```typescript
215
+ interface EventResponse {
216
+ id?: string; // Event ID (if returned)
217
+ success: boolean; // Always true for success
218
+ status?: number; // Event status from Fluent API (CREATED, COMPLETED, etc.)
219
+ statusCode?: number; // HTTP status code (200, 201, 202)
220
+ message?: string; // Optional message
221
+ }
222
+ ```
223
+
224
+ ### Basic Try-Catch Pattern
225
+
226
+ ```typescript
227
+ import { FluentClient, FluentAPIError, AuthenticationError } from '@fluentcommerce/fc-connect-sdk';
228
+
229
+ const client = new FluentClient({
230
+ baseUrl: 'https://api.fluentcommerce.com',
231
+ clientId: 'YOUR_CLIENT_ID',
232
+ clientSecret: 'YOUR_CLIENT_SECRET',
233
+ username: 'YOUR_USERNAME',
234
+ password: 'YOUR_PASSWORD',
235
+ retailerId: 'YOUR_RETAILER_ID'
236
+ });
237
+
238
+ try {
239
+ // SUCCESS CASE
240
+ const result = await client.sendEvent({
241
+ name: 'OrderCancel1',
242
+ entityRef: 'G_TEST_FC_POSTMAN_34',
243
+ entityType: 'ORDER',
244
+ retailerId: '2'
245
+ }, 'async');
246
+
247
+ console.log('✅ Event sent successfully');
248
+ console.log('HTTP Status:', result.statusCode); // 200
249
+ console.log('Success:', result.success); // true
250
+ console.log('Event ID:', result.id); // evt-123 (if available)
251
+
252
+ } catch (error) {
253
+ if (error instanceof FluentAPIError) {
254
+ // API Error (400, 404, 500, etc.)
255
+ console.error('❌ API Error');
256
+ console.error('Status:', error.statusCode); // 400, 404, 500, etc.
257
+ console.error('Message:', error.message); // "Request failed: 400"
258
+ console.error('Details:', error.details); // Response body
259
+
260
+ } else if (error instanceof AuthenticationError) {
261
+ // Auth failed after 3 retries
262
+ console.error('❌ Authentication Error');
263
+ console.error('Message:', error.message);
264
+ console.error('Status:', error.statusCode); // 401
265
+
266
+ } else {
267
+ // Unknown error
268
+ console.error('❌ Unexpected Error:', error);
269
+ }
270
+ }
271
+ ```
272
+
273
+ ### Async Mode - Success Examples
274
+
275
+ **Input:**
276
+ ```json
277
+ {
278
+ "name": "OrderCancel1",
279
+ "entityRef": "G_TEST_FC_POSTMAN_34",
280
+ "entityType": "ORDER",
281
+ "retailerId": "2"
282
+ }
283
+ ```
284
+
285
+ **Output (Success):**
286
+ ```json
287
+ {
288
+ "success": true,
289
+ "statusCode": 200
290
+ }
291
+ ```
292
+
293
+ **Code:**
294
+ ```typescript
295
+ const result = await client.sendEvent({
296
+ name: 'OrderCancel1',
297
+ entityRef: 'G_TEST_FC_POSTMAN_34',
298
+ entityType: 'ORDER',
299
+ retailerId: '2'
300
+ }, 'async');
301
+
302
+ // result.success = true
303
+ // result.statusCode = 200
304
+ ```
305
+
306
+ ---
307
+
308
+ ### ⚡ SDK Automatic Retry Behavior
309
+
310
+ > **IMPORTANT:** The SDK automatically retries certain errors WITHOUT your intervention
311
+
312
+ **✅ Automatically Retried (3 attempts with exponential backoff):**
313
+ - `401 Unauthorized` - Token refresh attempt
314
+ - `500 Internal Server Error` - Transient server issue
315
+ - `503 Service Unavailable` - API temporarily overloaded
316
+ - Network errors - Connection failures
317
+
318
+ **❌ NOT Retried (Fail Immediately):**
319
+ - `400 Bad Request` - Invalid event payload
320
+ - `404 Not Found` - No workflow matched (sync mode)
321
+ - `422 Unprocessable Entity` - Validation failed
322
+ - All other 4xx errors
323
+
324
+ **Example:**
325
+ ```typescript
326
+ try {
327
+ await client.sendEvent(event);
328
+ } catch (error) {
329
+ if (error instanceof FluentAPIError && error.statusCode === 500) {
330
+ // ⚠️ SDK already retried 3 times with exponential backoff
331
+ // This error means all retries failed
332
+ console.error('Server error after 3 automatic retries');
333
+
334
+ // You may want to implement additional retry logic here
335
+ // or send to a dead letter queue
336
+ }
337
+ }
338
+ ```
339
+
340
+ ---
341
+
342
+ ### Async Mode - Error Examples
343
+
344
+ #### Error 1: Invalid Event Name (400)
345
+
346
+ **Input:**
347
+ ```json
348
+ {
349
+ "name": "InvalidEventName",
350
+ "entityRef": "TEST-123",
351
+ "entityType": "ORDER",
352
+ "retailerId": "2"
353
+ }
354
+ ```
355
+
356
+ **Error Thrown:**
357
+ ```typescript
358
+ FluentAPIError {
359
+ name: "FluentAPIError",
360
+ message: "Request failed: 400",
361
+ statusCode: 400,
362
+ details: "Bad Request - Invalid event configuration"
363
+ }
364
+ ```
365
+
366
+ **Handling:**
367
+ ```typescript
368
+ try {
369
+ await client.sendEvent({
370
+ name: 'InvalidEventName', // ❌ No workflow configured
371
+ entityRef: 'TEST-123',
372
+ entityType: 'ORDER',
373
+ retailerId: '2'
374
+ }, 'async');
375
+ } catch (error) {
376
+ if (error instanceof FluentAPIError && error.statusCode === 400) {
377
+ console.error('Invalid event configuration');
378
+ // ⚠️ SDK did NOT retry (4xx = client error)
379
+ // Fix: Check event name in Rubix workflow configuration
380
+ }
381
+ }
382
+ ```
383
+
384
+ ---
385
+
386
+ #### Error 2: Missing retailerId (SDK Validation)
387
+
388
+ **Input:**
389
+ ```json
390
+ {
391
+ "name": "TEST.EVENT",
392
+ "entityRef": "TEST-123",
393
+ "entityType": "ORDER"
394
+ // ❌ Missing retailerId
395
+ }
396
+ ```
397
+
398
+ **Error Thrown:**
399
+ ```typescript
400
+ FluentValidationError {
401
+ name: "FluentValidationError",
402
+ message: "retailerId is required for Event API. Provide it in the event payload or client config.",
403
+ code: "VALIDATION_ERROR",
404
+ statusCode: 400
405
+ }
406
+ ```
407
+
408
+ **Key Point**: This error is thrown BEFORE the API call (fail-fast).
409
+
410
+ **Handling:**
411
+ ```typescript
412
+ try {
413
+ await client.sendEvent({
414
+ name: 'TEST.EVENT',
415
+ entityRef: 'TEST-123',
416
+ entityType: 'ORDER'
417
+ // ❌ Missing retailerId
418
+ }, 'async');
419
+ } catch (error) {
420
+ if (error instanceof Error && error.message.includes('retailerId is required')) {
421
+ console.error('❌ retailerId validation failed (caught BEFORE API call)');
422
+ // Fix: Add retailerId to event or client config
423
+ }
424
+ }
425
+ ```
426
+
427
+ ---
428
+
429
+ ### Sync Mode - Success and Error Examples
430
+
431
+ #### Sync Mode Success
432
+
433
+ **Input:**
434
+ ```json
435
+ {
436
+ "name": "OrderCancel1",
437
+ "entityRef": "ORDER-SYNC-123",
438
+ "entityType": "ORDER",
439
+ "retailerId": "2"
440
+ }
441
+ ```
442
+
443
+ **Output (if workflow configured and succeeds):**
444
+ ```json
445
+ {
446
+ "success": true,
447
+ "status": "COMPLETED",
448
+ "statusCode": 201,
449
+ "message": "Workflow completed successfully"
450
+ }
451
+ ```
452
+
453
+ **Code:**
454
+ ```typescript
455
+ const result = await client.sendEvent({
456
+ name: 'OrderCancel1',
457
+ entityRef: 'ORDER-SYNC-123',
458
+ entityType: 'ORDER',
459
+ retailerId: '2'
460
+ }, 'sync'); // ← Sync mode waits for workflow
461
+
462
+ console.log('Workflow completed:', result.status);
463
+ console.log('HTTP Status:', result.statusCode);
464
+ ```
465
+
466
+ ---
467
+
468
+ #### Sync Mode Error: No Workflow Match (404)
469
+
470
+ **Input:**
471
+ ```json
472
+ {
473
+ "name": "OrderCancel1",
474
+ "entityRef": "SYNC-NO-MATCH",
475
+ "entityType": "ORDER",
476
+ "retailerId": "2"
477
+ }
478
+ ```
479
+
480
+ **Error Thrown:**
481
+ ```typescript
482
+ FluentAPIError {
483
+ name: "FluentAPIError",
484
+ message: "Request failed: 404",
485
+ statusCode: 404,
486
+ details: "No workflow rule matched this event"
487
+ }
488
+ ```
489
+
490
+ **Handling:**
491
+ ```typescript
492
+ try {
493
+ await client.sendEvent({
494
+ name: 'OrderCancel1',
495
+ entityRef: 'SYNC-NO-MATCH',
496
+ entityType: 'ORDER',
497
+ retailerId: '2'
498
+ }, 'sync');
499
+ } catch (error) {
500
+ if (error instanceof FluentAPIError && error.statusCode === 404) {
501
+ console.error('No workflow rule matched (sync mode detected this)');
502
+ // ⚠️ Async mode would return 200 (doesn't wait for workflow)
503
+ // ✅ Sync mode detected the failure immediately
504
+ }
505
+ }
506
+ ```
507
+
508
+ ---
509
+
510
+ ### Batch Processing with Per-Event Error Handling
511
+
512
+ ```typescript
513
+ interface EventResult {
514
+ sku: string;
515
+ success: boolean;
516
+ statusCode?: number;
517
+ error?: string;
518
+ }
519
+
520
+ async function processProducts(products: Product[]): Promise<EventResult[]> {
521
+ const results: EventResult[] = [];
522
+
523
+ for (const product of products) {
524
+ try {
525
+ const response = await client.sendEvent({
526
+ name: 'PRODUCT.UPSERT',
527
+ entityType: 'PRODUCT',
528
+ entityRef: product.sku,
529
+ retailerId: '2',
530
+ attributes: product
531
+ }, 'async');
532
+
533
+ // SUCCESS
534
+ results.push({
535
+ sku: product.sku,
536
+ success: true,
537
+ statusCode: response.statusCode
538
+ });
539
+
540
+ console.log(`✅ ${product.sku} - HTTP ${response.statusCode}`);
541
+
542
+ } catch (error) {
543
+ if (error instanceof FluentAPIError) {
544
+ // API ERROR (SDK already retried 401/5xx)
545
+ results.push({
546
+ sku: product.sku,
547
+ success: false,
548
+ error: `HTTP ${error.statusCode}: ${error.message}`
549
+ });
550
+
551
+ console.error(`❌ ${product.sku} - ${error.statusCode}: ${error.message}`);
552
+
553
+ // Handle specific error codes
554
+ if (error.statusCode === 400) {
555
+ console.error(' → Invalid product data');
556
+ } else if (error.statusCode === 422) {
557
+ console.error(' → Validation failed');
558
+ } else if (error.statusCode === 500) {
559
+ console.error(' → Server error (SDK already retried 3x)');
560
+ }
561
+
562
+ } else if (error instanceof AuthenticationError) {
563
+ // AUTH FAILED (after 3 retries)
564
+ console.error(`❌ Auth failed: ${error.message}`);
565
+ // Stop processing - credentials are invalid
566
+ break;
567
+
568
+ } else {
569
+ // UNEXPECTED ERROR
570
+ results.push({
571
+ sku: product.sku,
572
+ success: false,
573
+ error: error.message
574
+ });
575
+ }
576
+ }
577
+ }
578
+
579
+ return results;
580
+ }
581
+ ```
582
+
583
+ ---
584
+
585
+ ## GraphQL Error Handling
586
+
587
+ ### Success Response Structure
588
+
589
+ ```typescript
590
+ interface GraphQLResponse {
591
+ data: any; // Query/mutation result
592
+ errors?: undefined; // No errors on success
593
+ }
594
+ ```
595
+
596
+ ### Error Response Structure
597
+
598
+ When GraphQL returns errors, SDK throws `GraphQLExecutionError`:
599
+
600
+ ```typescript
601
+ {
602
+ name: 'GraphQLExecutionError',
603
+ message: string, // First error message
604
+ graphqlErrors: Array<{
605
+ message: string,
606
+ locations?: Array<{ line: number, column: number }>,
607
+ path?: Array<string | number>,
608
+ extensions?: { ... }
609
+ }>,
610
+ query: string,
611
+ variables?: { ... }
612
+ }
613
+ ```
614
+
615
+ ### Basic Try-Catch Pattern
616
+
617
+ ```typescript
618
+ try {
619
+ // SUCCESS CASE
620
+ const result = await client.graphql({
621
+ query: `
622
+ query GetOrder($ref: String!) {
623
+ order(ref: $ref) {
624
+ id
625
+ ref
626
+ status
627
+ }
628
+ }
629
+ `,
630
+ variables: { ref: 'ORDER-123' }
631
+ });
632
+
633
+ console.log('✅ GraphQL query succeeded');
634
+ console.log('Data:', result.data);
635
+ console.log('Order:', result.data.order);
636
+
637
+ } catch (error) {
638
+ if (error instanceof GraphQLExecutionError) {
639
+ // GraphQL returned errors
640
+ console.error('❌ GraphQL Execution Error');
641
+ console.error('Message:', error.message);
642
+ console.error('All errors:', error.getErrorMessages());
643
+ console.error('Query:', error.query);
644
+
645
+ // Check for specific errors
646
+ const errorMessages = error.getErrorMessages();
647
+ if (errorMessages.some(msg => msg.includes('invalidField'))) {
648
+ console.error(' → Invalid field in query');
649
+ }
650
+
651
+ } else if (error instanceof FluentAPIError) {
652
+ // HTTP error (400, 500, etc.)
653
+ console.error('❌ API Error');
654
+ console.error('Status:', error.statusCode);
655
+ console.error('Message:', error.message);
656
+
657
+ } else if (error instanceof AuthenticationError) {
658
+ // Auth failed
659
+ console.error('❌ Authentication failed');
660
+
661
+ } else {
662
+ console.error('❌ Unexpected error:', error);
663
+ }
664
+ }
665
+ ```
666
+
667
+ ### GraphQL Success Example
668
+
669
+ **Input:**
670
+ ```graphql
671
+ query GetOrder($ref: String!) {
672
+ order(ref: $ref) {
673
+ id
674
+ ref
675
+ status
676
+ }
677
+ }
678
+ ```
679
+
680
+ **Variables:**
681
+ ```json
682
+ {
683
+ "ref": "ORDER-123"
684
+ }
685
+ ```
686
+
687
+ **Output (Success):**
688
+ ```json
689
+ {
690
+ "data": {
691
+ "order": {
692
+ "id": "ORDER-123",
693
+ "ref": "ORD-2024-123",
694
+ "status": "CREATED"
695
+ }
696
+ }
697
+ }
698
+ ```
699
+
700
+ **Code:**
701
+ ```typescript
702
+ const result = await client.graphql({
703
+ query: `query GetOrder($ref: String!) { order(ref: $ref) { id ref status } }`,
704
+ variables: { ref: 'ORDER-123' }
705
+ });
706
+
707
+ console.log('Order ID:', result.data.order.id);
708
+ console.log('Order Ref:', result.data.order.ref);
709
+ console.log('Order Status:', result.data.order.status);
710
+ ```
711
+
712
+ ---
713
+
714
+ ### GraphQL Error Examples
715
+
716
+ #### Error 1: Invalid Field
717
+
718
+ **Input:**
719
+ ```graphql
720
+ query GetOrder {
721
+ order(ref: "123") {
722
+ id
723
+ invalidField # ❌ Field doesn't exist
724
+ }
725
+ }
726
+ ```
727
+
728
+ **Error Thrown:**
729
+ ```typescript
730
+ GraphQLExecutionError {
731
+ name: "GraphQLExecutionError",
732
+ message: "Field \"invalidField\" doesn't exist on type \"Order\"",
733
+ graphqlErrors: [
734
+ {
735
+ message: "Field \"invalidField\" doesn't exist on type \"Order\"",
736
+ locations: [{ line: 4, column: 5 }],
737
+ extensions: { ... }
738
+ }
739
+ ],
740
+ query: "query GetOrder { ... }"
741
+ }
742
+ ```
743
+
744
+ **Handling:**
745
+ ```typescript
746
+ try {
747
+ await client.graphql({
748
+ query: `query GetOrder { order(ref: "123") { id invalidField } }`
749
+ });
750
+ } catch (error) {
751
+ if (error instanceof GraphQLExecutionError) {
752
+ console.error('GraphQL Error:', error.message);
753
+
754
+ // Get all error messages
755
+ const messages = error.getErrorMessages();
756
+ console.error('All errors:', messages);
757
+
758
+ // Check for specific error
759
+ const errorMessages = error.getErrorMessages();
760
+ if (errorMessages.some(msg => msg.includes('invalidField'))) {
761
+ console.error('Invalid field in query - check schema');
762
+ }
763
+ }
764
+ }
765
+ ```
766
+
767
+ ---
768
+
769
+ #### Error 2: Syntax Error
770
+
771
+ **Input:**
772
+ ```graphql
773
+ query GetOrder {
774
+ order(ref: "123" # ❌ Missing closing parenthesis
775
+ id
776
+ ref
777
+ }
778
+ }
779
+ ```
780
+
781
+ **Error Thrown:**
782
+ ```typescript
783
+ FluentAPIError {
784
+ name: "FluentAPIError",
785
+ message: "Request failed: 400",
786
+ statusCode: 400,
787
+ details: {
788
+ errors: [
789
+ {
790
+ message: "Syntax Error: Expected ')', found Name 'id'",
791
+ locations: [{ line: 3, column: 5 }]
792
+ }
793
+ ]
794
+ }
795
+ }
796
+ ```
797
+
798
+ **Note**: Syntax errors throw `FluentAPIError` (400), not `GraphQLExecutionError`.
799
+
800
+ ---
801
+
802
+ ### GraphQL with Pagination
803
+
804
+ ```typescript
805
+ try {
806
+ const result = await client.graphql({
807
+ query: `
808
+ query GetOrders {
809
+ orders(first: 50) {
810
+ edges {
811
+ node {
812
+ id
813
+ ref
814
+ status
815
+ }
816
+ }
817
+ pageInfo {
818
+ hasNextPage
819
+ endCursor
820
+ }
821
+ }
822
+ }
823
+ `,
824
+ pagination: {
825
+ enabled: true,
826
+ maxPages: 10,
827
+ maxRecords: 500
828
+ }
829
+ });
830
+
831
+ console.log('✅ Fetched', result.data.orders.edges.length, 'orders');
832
+ console.log('Total pages fetched:', result.extensions?.autoPagination?.totalPages);
833
+
834
+ } catch (error) {
835
+ if (error instanceof GraphQLExecutionError) {
836
+ console.error('GraphQL error during pagination:', error.message);
837
+ } else if (error instanceof FluentAPIError) {
838
+ console.error('API error during pagination:', error.statusCode);
839
+ }
840
+ }
841
+ ```
842
+
843
+ ---
844
+
845
+ ## Batch API Error Handling
846
+
847
+ ### Success Response Structure
848
+
849
+ ```typescript
850
+ interface FluentBatchResponse {
851
+ id: string; // Batch ID
852
+ jobId: string; // Job ID
853
+ status: string; // Batch status (CREATED, SUBMITTED, PROCESSING, COMPLETED, FAILED)
854
+ processedEntities?: number; // Number of entities processed
855
+ totalEntities?: number; // Total entities in batch
856
+ createdAt?: string; // ISO timestamp
857
+ updatedAt?: string; // ISO timestamp
858
+ errors?: Array<{ // Failed entity details (if any)
859
+ code: string;
860
+ message: string;
861
+ entityIndex?: number;
862
+ }>;
863
+ }
864
+ ```
865
+
866
+ ### Basic Try-Catch Pattern
867
+
868
+ ```typescript
869
+ try {
870
+ // SUCCESS CASE
871
+ const batch = await client.sendBatch('job-123', {
872
+ entities: [
873
+ { id: '1', sku: 'SKU-001', name: 'Product 1' },
874
+ { id: '2', sku: 'SKU-002', name: 'Product 2' }
875
+ ],
876
+ action: 'UPSERT'
877
+ });
878
+
879
+ console.log('✅ Batch sent successfully');
880
+ console.log('Batch ID:', batch.id);
881
+ console.log('Status:', batch.status);
882
+
883
+ } catch (error) {
884
+ if (error instanceof FluentAPIError) {
885
+ console.error('❌ Batch Error');
886
+ console.error('Status:', error.statusCode);
887
+ console.error('Message:', error.message);
888
+
889
+ // Common errors
890
+ if (error.statusCode === 404) {
891
+ console.error(' → Job not found or expired');
892
+ } else if (error.statusCode === 400) {
893
+ console.error(' → Invalid batch payload');
894
+ } else if (error.statusCode === 500) {
895
+ console.error(' → Server error (SDK already retried 3x)');
896
+ }
897
+ }
898
+ }
899
+ ```
900
+
901
+ ### Batch Success Example
902
+
903
+ **Input:**
904
+ ```typescript
905
+ await client.sendBatch('job-123', {
906
+ entities: [
907
+ { id: '1', sku: 'SKU-001', name: 'Product 1', price: 19.99 },
908
+ { id: '2', sku: 'SKU-002', name: 'Product 2', price: 29.99 }
909
+ ],
910
+ action: 'UPSERT'
911
+ });
912
+ ```
913
+
914
+ **Output (Success):**
915
+ ```json
916
+ {
917
+ "id": "batch-456",
918
+ "jobId": "job-123",
919
+ "status": "CREATED",
920
+ "processedEntities": 2,
921
+ "totalEntities": 2
922
+ }
923
+ ```
924
+
925
+ ---
926
+
927
+ ### Batch Error Examples
928
+
929
+ #### Error 1: Job Expired (404)
930
+
931
+ **Input:**
932
+ ```typescript
933
+ await client.sendBatch('job-expired-123', {
934
+ entities: [...],
935
+ action: 'UPSERT'
936
+ });
937
+ ```
938
+
939
+ **Error Thrown:**
940
+ ```typescript
941
+ FluentAPIError {
942
+ name: "FluentAPIError",
943
+ message: "Request failed: 404",
944
+ statusCode: 404,
945
+ details: "Job not found or expired"
946
+ }
947
+ ```
948
+
949
+ **Handling:**
950
+ ```typescript
951
+ try {
952
+ await client.sendBatch(jobId, { entities, action: 'UPSERT' });
953
+ } catch (error) {
954
+ if (error instanceof FluentAPIError && error.statusCode === 404) {
955
+ console.error('Job expired - recreating...');
956
+
957
+ // Recreate job and retry
958
+ const newJob = await client.createJob({
959
+ name: 'inventory-sync',
960
+ retailerId: '2'
961
+ });
962
+
963
+ await client.sendBatch(newJob.id, { entities, action: 'UPSERT' });
964
+ }
965
+ }
966
+ ```
967
+
968
+ ---
969
+
970
+ #### Error 2: Invalid Batch Payload (400)
971
+
972
+ **Input:**
973
+ ```typescript
974
+ await client.sendBatch('job-123', {
975
+ entities: [], // ❌ Empty entities array
976
+ action: 'UPSERT'
977
+ });
978
+ ```
979
+
980
+ **Error Thrown:**
981
+ ```typescript
982
+ FluentAPIError {
983
+ name: "FluentAPIError",
984
+ message: "Request failed: 400",
985
+ statusCode: 400,
986
+ details: "Batch must contain at least one entity"
987
+ }
988
+ ```
989
+
990
+ ---
991
+
992
+ ### Batch Processing with Retry
993
+
994
+ ```typescript
995
+ async function sendBatchWithRetry(
996
+ jobId: string,
997
+ entities: any[],
998
+ maxRetries: number = 3
999
+ ): Promise<FluentBatchResponse> {
1000
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
1001
+ try {
1002
+ const batch = await client.sendBatch(jobId, {
1003
+ entities,
1004
+ action: 'UPSERT'
1005
+ });
1006
+
1007
+ console.log(`✅ Batch sent (attempt ${attempt + 1})`);
1008
+ return batch;
1009
+
1010
+ } catch (error) {
1011
+ if (error instanceof FluentAPIError) {
1012
+ if (error.statusCode === 404 && attempt < maxRetries) {
1013
+ // Job expired - recreate
1014
+ console.log(`⚠️ Job expired, recreating... (attempt ${attempt + 1})`);
1015
+
1016
+ const newJob = await client.createJob({
1017
+ name: 'inventory-sync',
1018
+ retailerId: '2'
1019
+ });
1020
+
1021
+ jobId = newJob.id;
1022
+ // Retry with new job ID
1023
+ continue;
1024
+
1025
+ } else if (error.statusCode === 500 && attempt < maxRetries) {
1026
+ // Server error - SDK already retried 3x
1027
+ console.log(`⚠️ Server error, waiting before retry...`);
1028
+ await new Promise(resolve => setTimeout(resolve, 5000));
1029
+ continue;
1030
+
1031
+ } else {
1032
+ // Non-retryable error or max retries reached
1033
+ throw error;
1034
+ }
1035
+ }
1036
+ throw error;
1037
+ }
1038
+ }
1039
+
1040
+ throw new Error('Max retries exceeded');
1041
+ }
1042
+ ```
1043
+
1044
+ ---
1045
+
1046
+ ## Job API Error Handling
1047
+
1048
+ ### Success Response Structure
1049
+
1050
+ ```typescript
1051
+ interface FluentJobResponse {
1052
+ id: string; // Job ID
1053
+ name: string; // Job name
1054
+ retailerId: string;
1055
+ status?: string; // Job status (CREATED, ACTIVE, PROCESSING, COMPLETED, FAILED)
1056
+ meta?: FluentJobMetadata; // Job metadata (preprocessing, source, etc.)
1057
+ createdAt?: string; // ISO timestamp
1058
+ updatedAt?: string; // ISO timestamp
1059
+ }
1060
+ ```
1061
+
1062
+ ### Basic Try-Catch Pattern
1063
+
1064
+ ```typescript
1065
+ try {
1066
+ // SUCCESS CASE
1067
+ const job = await client.createJob({
1068
+ name: 'inventory-sync',
1069
+ retailerId: '2'
1070
+ });
1071
+
1072
+ console.log('✅ Job created successfully');
1073
+ console.log('Job ID:', job.id);
1074
+ console.log('Status:', job.status);
1075
+ console.log('Created:', job.createdAt);
1076
+
1077
+ } catch (error) {
1078
+ if (error instanceof FluentAPIError) {
1079
+ console.error('❌ Job Creation Error');
1080
+ console.error('Status:', error.statusCode);
1081
+ console.error('Message:', error.message);
1082
+
1083
+ if (error.statusCode === 400) {
1084
+ console.error(' → Invalid job payload');
1085
+ } else if (error.statusCode === 403) {
1086
+ console.error(' → Permission denied');
1087
+ }
1088
+ }
1089
+ }
1090
+ ```
1091
+
1092
+ ### Job Success Example
1093
+
1094
+ **Input:**
1095
+ ```typescript
1096
+ await client.createJob({
1097
+ name: 'product-import-batch',
1098
+ retailerId: '2'
1099
+ });
1100
+ ```
1101
+
1102
+ **Output (Success):**
1103
+ ```json
1104
+ {
1105
+ "id": "job-789",
1106
+ "name": "product-import-batch",
1107
+ "status": "CREATED",
1108
+ "retailerId": "2",
1109
+ "createdAt": "2025-01-19T10:30:00Z",
1110
+ "updatedAt": "2025-01-19T10:30:00Z"
1111
+ }
1112
+ ```
1113
+
1114
+ ---
1115
+
1116
+ ### Job Status Checking
1117
+
1118
+ **Response Structure:**
1119
+ ```typescript
1120
+ interface FluentJobStatus {
1121
+ id: string;
1122
+ status: string; // Job status (CREATED, ACTIVE, PROCESSING, COMPLETED, FAILED)
1123
+ progress?: number; // Progress percentage (0-100)
1124
+ message?: string; // Status message
1125
+ completedAt?: string; // ISO timestamp when completed
1126
+ failedAt?: string; // ISO timestamp when failed
1127
+ errors?: Array<{ // Error details (if failed)
1128
+ code: string;
1129
+ message: string;
1130
+ }>;
1131
+ }
1132
+ ```
1133
+
1134
+ **Example:**
1135
+ ```typescript
1136
+ try {
1137
+ const status = await client.getJobStatus('job-789');
1138
+
1139
+ console.log('Job Status:', status.status);
1140
+ console.log('Progress:', status.progress);
1141
+
1142
+ if (status.status === 'FAILED') {
1143
+ console.warn('⚠️ Job failed - check errors');
1144
+ console.error('Errors:', status.errors);
1145
+ }
1146
+
1147
+ } catch (error) {
1148
+ if (error instanceof FluentAPIError && error.statusCode === 404) {
1149
+ console.error('Job not found');
1150
+ }
1151
+ }
1152
+ ```
1153
+
1154
+ ---
1155
+
1156
+ ## Common Patterns
1157
+
1158
+ ### Pattern 1: Centralized Error Handler
1159
+
1160
+ ```typescript
1161
+ function handleSDKError(error: unknown, context: string): void {
1162
+ if (error instanceof FluentAPIError) {
1163
+ console.error(`[${context}] API Error:`, {
1164
+ status: error.statusCode,
1165
+ message: error.message,
1166
+ details: error.details
1167
+ });
1168
+
1169
+ // Log to monitoring service
1170
+ logger.error('Fluent API Error', {
1171
+ context,
1172
+ status: error.statusCode,
1173
+ message: error.message
1174
+ });
1175
+
1176
+ } else if (error instanceof GraphQLExecutionError) {
1177
+ console.error(`[${context}] GraphQL Error:`, {
1178
+ message: error.message,
1179
+ errors: error.getErrorMessages(),
1180
+ query: error.query
1181
+ });
1182
+
1183
+ logger.error('GraphQL Execution Error', {
1184
+ context,
1185
+ errors: error.getErrorMessages()
1186
+ });
1187
+
1188
+ } else if (error instanceof AuthenticationError) {
1189
+ console.error(`[${context}] Auth Error:`, {
1190
+ message: error.message,
1191
+ status: error.statusCode
1192
+ });
1193
+
1194
+ // Alert - credentials may be invalid
1195
+ alertService.send('Fluent Auth Failure', error.message);
1196
+
1197
+ } else {
1198
+ console.error(`[${context}] Unexpected Error:`, error);
1199
+ logger.error('Unexpected SDK Error', { context, error });
1200
+ }
1201
+ }
1202
+
1203
+ // Usage
1204
+ try {
1205
+ await client.sendEvent(event);
1206
+ } catch (error) {
1207
+ handleSDKError(error, 'Event API');
1208
+ throw error; // Re-throw if needed
1209
+ }
1210
+ ```
1211
+
1212
+ ---
1213
+
1214
+ ### Pattern 2: Retry with Backoff
1215
+
1216
+ ```typescript
1217
+ async function retryWithBackoff<T>(
1218
+ operation: () => Promise<T>,
1219
+ maxRetries: number = 3,
1220
+ baseDelay: number = 1000
1221
+ ): Promise<T> {
1222
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
1223
+ try {
1224
+ return await operation();
1225
+ } catch (error) {
1226
+ if (error instanceof FluentAPIError) {
1227
+ // Only retry 5xx server errors
1228
+ if (error.statusCode >= 500 && attempt < maxRetries) {
1229
+ const delay = baseDelay * Math.pow(2, attempt);
1230
+ console.log(`⚠️ Server error, retrying in ${delay}ms...`);
1231
+ await new Promise(resolve => setTimeout(resolve, delay));
1232
+ continue;
1233
+ }
1234
+ }
1235
+ throw error;
1236
+ }
1237
+ }
1238
+ throw new Error('Max retries exceeded');
1239
+ }
1240
+
1241
+ // Usage
1242
+ const result = await retryWithBackoff(
1243
+ () => client.sendEvent(event),
1244
+ 3,
1245
+ 1000
1246
+ );
1247
+ ```
1248
+
1249
+ ---
1250
+
1251
+ ### Pattern 3: Batch with Dead Letter Queue
1252
+
1253
+ ```typescript
1254
+ interface ProcessingResult {
1255
+ successful: any[];
1256
+ failed: Array<{ item: any; error: string }>;
1257
+ }
1258
+
1259
+ async function processBatchWithDLQ(
1260
+ items: any[]
1261
+ ): Promise<ProcessingResult> {
1262
+ const result: ProcessingResult = {
1263
+ successful: [],
1264
+ failed: []
1265
+ };
1266
+
1267
+ for (const item of items) {
1268
+ try {
1269
+ const response = await client.sendEvent({
1270
+ name: 'PRODUCT.UPSERT',
1271
+ entityType: 'PRODUCT',
1272
+ entityRef: item.sku,
1273
+ retailerId: '2',
1274
+ attributes: item
1275
+ });
1276
+
1277
+ result.successful.push(item);
1278
+
1279
+ } catch (error) {
1280
+ if (error instanceof FluentAPIError) {
1281
+ // Add to dead letter queue
1282
+ result.failed.push({
1283
+ item,
1284
+ error: `HTTP ${error.statusCode}: ${error.message}`
1285
+ });
1286
+
1287
+ // Log to DLQ for manual review
1288
+ await deadLetterQueue.add({
1289
+ item,
1290
+ error: error.message,
1291
+ status: error.statusCode,
1292
+ timestamp: new Date().toISOString()
1293
+ });
1294
+ }
1295
+ }
1296
+ }
1297
+
1298
+ return result;
1299
+ }
1300
+ ```
1301
+
1302
+ ---
1303
+
1304
+ ## Live Examples
1305
+
1306
+ ### Test Environment
1307
+
1308
+ ```yaml
1309
+ Base URL: https://api.fluentcommerce.com
1310
+ Retailer ID: YOUR_RETAILER_ID
1311
+ Client ID: YOUR_CLIENT_ID
1312
+ ```
1313
+
1314
+ ### Example 1: Event API Success
1315
+
1316
+ **Code:**
1317
+ ```typescript
1318
+ const client = new FluentClient({
1319
+ baseUrl: 'https://api.fluentcommerce.com',
1320
+ clientId: 'YOUR_CLIENT_ID',
1321
+ clientSecret: 'YOUR_CLIENT_SECRET',
1322
+ username: 'YOUR_USERNAME',
1323
+ password: 'YOUR_PASSWORD',
1324
+ retailerId: 'YOUR_RETAILER_ID'
1325
+ });
1326
+
1327
+ const result = await client.sendEvent({
1328
+ name: 'OrderCancel1',
1329
+ entityRef: 'G_TEST_FC_POSTMAN_34',
1330
+ entityType: 'ORDER',
1331
+ retailerId: '2'
1332
+ }, 'async');
1333
+
1334
+ console.log('Success:', result.success); // true
1335
+ console.log('HTTP Status:', result.statusCode); // 200
1336
+ ```
1337
+
1338
+ **Console Output:**
1339
+ ```
1340
+ Success: true
1341
+ HTTP Status: 200
1342
+ ```
1343
+
1344
+ ---
1345
+
1346
+ ### Example 2: Event API Error (400)
1347
+
1348
+ **Code:**
1349
+ ```typescript
1350
+ try {
1351
+ await client.sendEvent({
1352
+ name: 'InvalidEventName',
1353
+ entityRef: 'TEST-123',
1354
+ entityType: 'ORDER',
1355
+ retailerId: '2'
1356
+ }, 'async');
1357
+ } catch (error) {
1358
+ if (error instanceof FluentAPIError) {
1359
+ console.error('Error Status:', error.statusCode);
1360
+ console.error('Error Message:', error.message);
1361
+ }
1362
+ }
1363
+ ```
1364
+
1365
+ **Console Output:**
1366
+ ```
1367
+ Error Status: 400
1368
+ Error Message: Request failed: 400
1369
+ ```
1370
+
1371
+ ---
1372
+
1373
+ ### Example 3: Sync Mode - No Workflow Match (404)
1374
+
1375
+ **Code:**
1376
+ ```typescript
1377
+ try {
1378
+ await client.sendEvent({
1379
+ name: 'OrderCancel1',
1380
+ entityRef: 'SYNC-NO-MATCH',
1381
+ entityType: 'ORDER',
1382
+ retailerId: '2'
1383
+ }, 'sync');
1384
+ } catch (error) {
1385
+ if (error instanceof FluentAPIError) {
1386
+ console.error('Sync mode detected workflow failure');
1387
+ console.error('Status:', error.statusCode); // 404
1388
+ }
1389
+ }
1390
+ ```
1391
+
1392
+ **Console Output:**
1393
+ ```
1394
+ Sync mode detected workflow failure
1395
+ Status: 404
1396
+ ```
1397
+
1398
+ ---
1399
+
1400
+ ## Summary Table
1401
+
1402
+ | API | Success Type | Error Type | SDK Retries | Notes |
1403
+ |-----|-------------|------------|-------------|-------|
1404
+ | **Event API** | `EventResponse` | `FluentAPIError`, `AuthenticationError` | ✅ 401 (3x), 5xx (3x) | Async = fast, Sync = detects workflow errors |
1405
+ | **GraphQL** | `GraphQLResponse` | `GraphQLExecutionError`, `FluentAPIError`, `AuthenticationError` | ✅ 401 (3x), 5xx (3x) | GraphQL errors vs HTTP errors |
1406
+ | **Batch API** | `FluentBatchResponse` | `FluentAPIError`, `AuthenticationError` | ✅ 401 (3x), 5xx (3x) | Watch for job expiry (404) |
1407
+ | **Job API** | `FluentJobResponse` | `FluentAPIError`, `AuthenticationError` | ✅ 401 (3x), 5xx (3x) | Jobs expire after 1 hour |
1408
+
1409
+ ---
1410
+
1411
+ ## Quick Reference
1412
+
1413
+ ### When to Use Try-Catch
1414
+
1415
+ ✅ **Always use try-catch** for:
1416
+ - `sendEvent()`
1417
+ - `graphql()`
1418
+ - `sendBatch()`
1419
+ - `createJob()`
1420
+ - `getJobStatus()`
1421
+ - Any SDK method that makes API calls
1422
+
1423
+ ### Error Handling Checklist
1424
+
1425
+ - [ ] Catch `FluentAPIError` for HTTP errors
1426
+ - [ ] Catch `AuthenticationError` for auth failures
1427
+ - [ ] Catch `GraphQLExecutionError` for GraphQL errors
1428
+ - [ ] Check `error.statusCode` to determine error type
1429
+ - [ ] Log errors with context for debugging
1430
+ - [ ] Implement retry logic for transient errors (5xx)
1431
+ - [ ] Use dead letter queue for persistent failures
1432
+ - [ ] Alert on authentication failures
1433
+
1434
+ ---
1435
+
1436
+ **SDK Version**: 0.1.46
1437
+ **Date**: 2025-01-19