@fluentcommerce/fc-connect-sdk 0.1.54 → 0.1.56

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 (476) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +11 -0
  3. package/dist/cjs/clients/fluent-client.js +13 -6
  4. package/dist/cjs/utils/pagination-helpers.js +38 -2
  5. package/dist/cjs/versori/fluent-versori-client.js +11 -5
  6. package/dist/esm/clients/fluent-client.js +13 -6
  7. package/dist/esm/utils/pagination-helpers.js +38 -2
  8. package/dist/esm/versori/fluent-versori-client.js +11 -5
  9. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  10. package/dist/tsconfig.tsbuildinfo +1 -1
  11. package/dist/tsconfig.types.tsbuildinfo +1 -1
  12. package/docs/00-START-HERE/EXPORT-VALIDATION.md +158 -158
  13. package/docs/00-START-HERE/cli-analyze-source-structure-guide.md +655 -655
  14. package/docs/00-START-HERE/cli-documentation-index.md +202 -202
  15. package/docs/00-START-HERE/cli-quick-reference.md +252 -252
  16. package/docs/00-START-HERE/decision-tree.md +552 -552
  17. package/docs/00-START-HERE/getting-started.md +1070 -1070
  18. package/docs/00-START-HERE/mapper-quick-decision-guide.md +235 -235
  19. package/docs/00-START-HERE/readme.md +237 -237
  20. package/docs/00-START-HERE/retailerid-configuration.md +404 -404
  21. package/docs/00-START-HERE/sdk-philosophy.md +794 -794
  22. package/docs/00-START-HERE/troubleshooting-quick-reference.md +1086 -1086
  23. package/docs/01-TEMPLATES/faq.md +686 -686
  24. package/docs/01-TEMPLATES/patterns/pattern-templates-guide.md +68 -68
  25. package/docs/01-TEMPLATES/patterns/patterns-csv-schema-validation-and-rejection-report.md +233 -233
  26. package/docs/01-TEMPLATES/patterns/patterns-custom-resolvers.md +407 -407
  27. package/docs/01-TEMPLATES/patterns/patterns-error-handling-retry.md +511 -511
  28. package/docs/01-TEMPLATES/patterns/patterns-field-mapping-universal.md +701 -701
  29. package/docs/01-TEMPLATES/patterns/patterns-large-file-splitting.md +1430 -1430
  30. package/docs/01-TEMPLATES/patterns/patterns-master-data-etl.md +2399 -2399
  31. package/docs/01-TEMPLATES/patterns/patterns-pagination-streaming.md +447 -447
  32. package/docs/01-TEMPLATES/patterns/patterns-state-duplicate-prevention.md +385 -385
  33. package/docs/01-TEMPLATES/readme.md +957 -957
  34. package/docs/01-TEMPLATES/standalone/standalone-asn-inbound-processing.md +1209 -1209
  35. package/docs/01-TEMPLATES/standalone/standalone-graphql-query-export.md +1140 -1140
  36. package/docs/01-TEMPLATES/standalone/standalone-graphql-to-parquet-partitioned-s3.md +432 -432
  37. package/docs/01-TEMPLATES/standalone/standalone-multi-channel-inventory-sync.md +1185 -1185
  38. package/docs/01-TEMPLATES/standalone/standalone-multi-source-aggregation.md +1462 -1462
  39. package/docs/01-TEMPLATES/standalone/standalone-s3-csv-batch-api.md +1390 -1390
  40. package/docs/01-TEMPLATES/standalone/standalone-s3-csv-inventory-to-batch.md +330 -330
  41. package/docs/01-TEMPLATES/standalone/standalone-scripts-guide.md +87 -87
  42. package/docs/01-TEMPLATES/standalone/standalone-sftp-xml-graphql.md +1444 -1444
  43. package/docs/01-TEMPLATES/standalone/standalone-webhook-payload-processing.md +688 -688
  44. package/docs/01-TEMPLATES/versori/business-examples/business-examples-dropship-order-routing.md +193 -193
  45. package/docs/01-TEMPLATES/versori/business-examples/business-examples-graphql-parquet-extraction.md +518 -518
  46. package/docs/01-TEMPLATES/versori/business-examples/business-examples-inter-location-transfers.md +2162 -2162
  47. package/docs/01-TEMPLATES/versori/business-examples/business-examples-pre-order-allocation.md +2226 -2226
  48. package/docs/01-TEMPLATES/versori/business-examples/business-scenarios-guide.md +87 -87
  49. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-connection-validation-pattern.md +656 -656
  50. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-dual-workflow-connector.md +835 -835
  51. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-guide.md +108 -108
  52. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-kv-state-management.md +1533 -1533
  53. package/docs/01-TEMPLATES/versori/patterns/versori-patterns-xml-response-patterns.md +1160 -1160
  54. package/docs/01-TEMPLATES/versori/versori-platform-guide.md +201 -201
  55. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-asn-purchase-order.md +1906 -1906
  56. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-dropship-routing.md +1074 -1074
  57. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-flash-sale-reserve.md +1395 -1395
  58. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-generic-xml-order.md +888 -888
  59. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-payment-gateway-integration.md +2478 -2478
  60. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-rma-returns-comprehensive.md +2240 -2240
  61. package/docs/01-TEMPLATES/versori/webhooks/template-webhook-xml-order-ingestion.md +2029 -2029
  62. package/docs/01-TEMPLATES/versori/webhooks/webhook-templates-guide.md +140 -140
  63. package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/inventory-mapping.json +20 -20
  64. package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/products_2025-01-22.csv +11 -11
  65. package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/sample-data-guide.md +34 -34
  66. package/docs/01-TEMPLATES/versori/workflows/_examples/workflow-examples-guide.md +36 -36
  67. package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-modes-guide.md +1038 -1038
  68. package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-workflows-guide.md +138 -138
  69. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/graphql-extraction-guide.md +63 -63
  70. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-csv.md +2062 -2062
  71. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-xml.md +2294 -2294
  72. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-s3-csv.md +2461 -2461
  73. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-sftp-xml.md +2529 -2529
  74. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-csv.md +2464 -2464
  75. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-json.md +1959 -1959
  76. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-s3-csv.md +1953 -1953
  77. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-sftp-xml.md +2541 -2541
  78. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-s3-json.md +2384 -2384
  79. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-sftp-xml.md +2445 -2445
  80. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-csv.md +2355 -2355
  81. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-json.md +2042 -2042
  82. package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-sftp-xml.md +2726 -2726
  83. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/batch-api-guide.md +206 -206
  84. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-cycle-count-reconciliation.md +2030 -2030
  85. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-multi-channel-inventory-sync.md +1882 -1882
  86. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-csv-inventory-batch.md +2827 -2827
  87. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-json-inventory-batch.md +1952 -1952
  88. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-xml-inventory-batch.md +3289 -3289
  89. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-csv-inventory-batch.md +3064 -3064
  90. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-json-inventory-batch.md +3238 -3238
  91. package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-xml-inventory-batch.md +2977 -2977
  92. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/event-api-guide.md +321 -321
  93. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-json-order-cancel-event.md +959 -959
  94. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-xml-order-cancel-event.md +1170 -1170
  95. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-csv-product-event.md +2312 -2312
  96. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-json-product-event.md +2999 -2999
  97. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-parquet-product-event.md +2836 -2836
  98. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-xml-product-event.md +2395 -2395
  99. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-csv-product-event.md +2295 -2295
  100. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-json-product-event.md +2602 -2602
  101. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-parquet-product-event.md +2589 -2589
  102. package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-xml-product-event.md +3578 -3578
  103. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/graphql-mutations-guide.md +93 -93
  104. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-json-order-update-graphql.md +1260 -1260
  105. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-xml-order-update-graphql.md +1472 -1472
  106. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-control-graphql.md +2417 -2417
  107. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-location-graphql.md +2811 -2811
  108. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-price-graphql.md +2619 -2619
  109. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-json-location-graphql.md +2807 -2807
  110. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-xml-location-graphql.md +2373 -2373
  111. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-control-graphql.md +2740 -2740
  112. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-location-graphql.md +2760 -2760
  113. package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-json-location-graphql.md +1710 -1710
  114. package/docs/01-TEMPLATES/versori/workflows/ingestion/ingestion-workflows-guide.md +136 -136
  115. package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/rubix-webhooks-guide.md +520 -520
  116. package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-inline.md +1418 -1418
  117. package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-universal-mapper.md +1785 -1785
  118. package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-order-attribute-update.md +824 -824
  119. package/docs/01-TEMPLATES/versori/workflows/workflows-overview-guide.md +646 -646
  120. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-batch-archival.md +724 -724
  121. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-job-tracker.md +627 -627
  122. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-partial-batch-recovery.md +561 -561
  123. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-quick-reference.md +367 -367
  124. package/docs/02-CORE-GUIDES/advanced-services/advanced-services-readme.md +407 -407
  125. package/docs/02-CORE-GUIDES/advanced-services/readme.md +49 -49
  126. package/docs/02-CORE-GUIDES/api-reference/api-reference-quick-reference.md +548 -548
  127. package/docs/02-CORE-GUIDES/api-reference/event-api-input-output-reference.md +702 -1171
  128. package/docs/02-CORE-GUIDES/api-reference/examples/client-initialization.ts +286 -286
  129. package/docs/02-CORE-GUIDES/api-reference/graphql-error-classification.md +337 -337
  130. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-01-client-api.md +399 -520
  131. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-03-authentication.md +199 -199
  132. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-04-graphql-mapping.md +925 -925
  133. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-05-services.md +1198 -1198
  134. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-06-data-sources.md +1083 -1083
  135. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-07-parsers.md +1097 -1097
  136. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-pagination.md +513 -513
  137. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-types.md +545 -597
  138. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-error-handling.md +527 -527
  139. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-webhook-validation.md +514 -514
  140. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-extraction.md +557 -557
  141. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-utilities.md +412 -412
  142. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-cli-tools.md +423 -423
  143. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-error-handling.md +716 -716
  144. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-analyze-source-structure.md +518 -518
  145. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-partial-responses.md +212 -212
  146. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-testing.md +300 -300
  147. package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-13-resolver-builder.md +322 -322
  148. package/docs/02-CORE-GUIDES/api-reference/readme.md +279 -279
  149. package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-quick-reference.md +351 -351
  150. package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-readme.md +277 -277
  151. package/docs/02-CORE-GUIDES/auto-pagination/examples/auto-pagination-readme.md +178 -178
  152. package/docs/02-CORE-GUIDES/auto-pagination/examples/common-patterns.ts +351 -351
  153. package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-products.ts +384 -384
  154. package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-virtual-positions.ts +308 -308
  155. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-01-foundations.md +470 -470
  156. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-02-quick-start.md +713 -713
  157. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-03-configuration.md +754 -754
  158. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-04-advanced-patterns.md +732 -732
  159. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-05-sdk-integration.md +847 -847
  160. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-06-troubleshooting.md +359 -359
  161. package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-07-api-reference.md +462 -462
  162. package/docs/02-CORE-GUIDES/auto-pagination/readme.md +54 -54
  163. package/docs/02-CORE-GUIDES/data-sources/data-sources-file-operations-error-handling.md +1487 -1487
  164. package/docs/02-CORE-GUIDES/data-sources/data-sources-quick-reference.md +836 -836
  165. package/docs/02-CORE-GUIDES/data-sources/data-sources-readme.md +276 -276
  166. package/docs/02-CORE-GUIDES/data-sources/data-sources-sftp-credential-access-security.md +553 -553
  167. package/docs/02-CORE-GUIDES/data-sources/examples/common-patterns.ts +409 -409
  168. package/docs/02-CORE-GUIDES/data-sources/examples/data-sources-readme.md +178 -178
  169. package/docs/02-CORE-GUIDES/data-sources/examples/s3-operations.ts +308 -308
  170. package/docs/02-CORE-GUIDES/data-sources/examples/sftp-operations.ts +371 -371
  171. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-01-foundations.md +735 -735
  172. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-02-s3-operations.md +1302 -1302
  173. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-03-sftp-operations.md +1379 -1379
  174. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-04-file-patterns.md +941 -941
  175. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-05-advanced-topics.md +813 -813
  176. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-06-integration-patterns.md +486 -486
  177. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-07-troubleshooting.md +387 -387
  178. package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-08-api-reference.md +417 -417
  179. package/docs/02-CORE-GUIDES/data-sources/readme.md +77 -77
  180. package/docs/02-CORE-GUIDES/error-handling-guide.md +936 -936
  181. package/docs/02-CORE-GUIDES/extraction/examples/02-core-guides-extraction-readme.md +116 -116
  182. package/docs/02-CORE-GUIDES/extraction/examples/common-patterns.ts +428 -428
  183. package/docs/02-CORE-GUIDES/extraction/examples/extract-inventory-basic.ts +187 -187
  184. package/docs/02-CORE-GUIDES/extraction/extraction-quick-reference.md +596 -596
  185. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-01-foundations.md +514 -514
  186. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-02-basic-extraction.md +823 -823
  187. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-03-parquet-processing.md +507 -507
  188. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-04-data-enrichment.md +546 -546
  189. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-05-transformation.md +494 -494
  190. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-export-formats.md +458 -458
  191. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-performance.md +138 -138
  192. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-api-reference.md +148 -148
  193. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-optimization.md +692 -692
  194. package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-08-extraction-orchestrator.md +1008 -1008
  195. package/docs/02-CORE-GUIDES/extraction/readme.md +151 -151
  196. package/docs/02-CORE-GUIDES/ingestion/examples/_simple-kv-store.ts +40 -40
  197. package/docs/02-CORE-GUIDES/ingestion/examples/error-recovery.ts +728 -728
  198. package/docs/02-CORE-GUIDES/ingestion/examples/event-driven.ts +501 -501
  199. package/docs/02-CORE-GUIDES/ingestion/examples/local-file-ingestion.ts +88 -88
  200. package/docs/02-CORE-GUIDES/ingestion/examples/parquet-ingestion.ts +117 -117
  201. package/docs/02-CORE-GUIDES/ingestion/examples/performance-optimized.ts +647 -647
  202. package/docs/02-CORE-GUIDES/ingestion/examples/s3-csv-ingestion.ts +169 -169
  203. package/docs/02-CORE-GUIDES/ingestion/examples/sftp-csv-ingestion.ts +134 -134
  204. package/docs/02-CORE-GUIDES/ingestion/ingestion-quick-reference.md +546 -546
  205. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-01-introduction.md +626 -626
  206. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-02-quick-start.md +658 -658
  207. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-03-data-sources.md +1052 -1052
  208. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-04-field-mapping.md +763 -763
  209. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-05-advanced-parsers.md +676 -676
  210. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-06-batch-api.md +1295 -1295
  211. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-api-reference.md +138 -138
  212. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-state-management.md +1037 -1037
  213. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-08-performance-optimization.md +1349 -1349
  214. package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-09-best-practices.md +1893 -1893
  215. package/docs/02-CORE-GUIDES/ingestion/readme.md +160 -160
  216. package/docs/02-CORE-GUIDES/logging-guide.md +585 -585
  217. package/docs/02-CORE-GUIDES/mapping/error-handling-patterns.md +401 -401
  218. package/docs/02-CORE-GUIDES/mapping/examples/02-core-guides-mapping-readme.md +128 -128
  219. package/docs/02-CORE-GUIDES/mapping/examples/common-patterns.ts +273 -273
  220. package/docs/02-CORE-GUIDES/mapping/examples/csv-location-ingestion.json +36 -36
  221. package/docs/02-CORE-GUIDES/mapping/examples/csv-mapping.ts +242 -242
  222. package/docs/02-CORE-GUIDES/mapping/examples/graphql-to-parquet-extraction.json +36 -36
  223. package/docs/02-CORE-GUIDES/mapping/examples/json-mapping.ts +213 -213
  224. package/docs/02-CORE-GUIDES/mapping/examples/json-product-to-mutation.json +48 -48
  225. package/docs/02-CORE-GUIDES/mapping/examples/xml-mapping.ts +291 -291
  226. package/docs/02-CORE-GUIDES/mapping/examples/xml-order-to-mutation.json +45 -45
  227. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-quick-reference.md +463 -463
  228. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-readme.md +227 -227
  229. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-01-introduction.md +222 -222
  230. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-02-quick-start.md +351 -351
  231. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-03-schema-validation.md +569 -569
  232. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-04-mapping-patterns.md +471 -471
  233. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-05-configuration-reference.md +611 -611
  234. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-advanced-xpath.md +148 -148
  235. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-path-syntax.md +464 -464
  236. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-api-reference.md +94 -94
  237. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-array-handling.md +307 -307
  238. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-08-custom-resolvers.md +544 -544
  239. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-09-advanced-patterns.md +427 -427
  240. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-10-hooks-and-variables.md +336 -336
  241. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-11-error-handling.md +488 -488
  242. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-12-arguments-vs-nodes.md +383 -383
  243. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-13-best-practices.md +477 -477
  244. package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/readme.md +62 -62
  245. package/docs/02-CORE-GUIDES/mapping/mapping-format-decision-tree.md +480 -480
  246. package/docs/02-CORE-GUIDES/mapping/mapping-graphql-alias-batching-guide.md +820 -820
  247. package/docs/02-CORE-GUIDES/mapping/mapping-javascript-objects.md +2369 -2369
  248. package/docs/02-CORE-GUIDES/mapping/mapping-mapper-comparison-guide.md +682 -682
  249. package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-07-api-reference.md +1327 -1327
  250. package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-08-error-handling.md +1142 -1142
  251. package/docs/02-CORE-GUIDES/mapping/modules/mapping-04-use-cases.md +891 -891
  252. package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-helpers-resolvers.md +1126 -1126
  253. package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-sdk-resolvers.md +199 -199
  254. package/docs/02-CORE-GUIDES/mapping/modules/mapping-07-api-reference.md +1319 -1319
  255. package/docs/02-CORE-GUIDES/mapping/readme.md +178 -178
  256. package/docs/02-CORE-GUIDES/mapping/resolver-registration.md +410 -410
  257. package/docs/02-CORE-GUIDES/mapping/resolvers/examples/common-patterns.ts +226 -226
  258. package/docs/02-CORE-GUIDES/mapping/resolvers/examples/custom-resolvers.ts +227 -227
  259. package/docs/02-CORE-GUIDES/mapping/resolvers/examples/sdk-resolvers-usage.ts +203 -203
  260. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-readme.md +274 -274
  261. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-api-reference.md +679 -679
  262. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-cookbook.md +826 -826
  263. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-guide.md +1330 -1330
  264. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-helpers-reference.md +1437 -1437
  265. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-parameters-reference.md +553 -553
  266. package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-troubleshooting.md +854 -854
  267. package/docs/02-CORE-GUIDES/mapping/resolvers/readme.md +75 -75
  268. package/docs/02-CORE-GUIDES/parsers/examples/02-core-guides-parsers-readme.md +161 -161
  269. package/docs/02-CORE-GUIDES/parsers/examples/csv-parser-examples.ts +110 -110
  270. package/docs/02-CORE-GUIDES/parsers/examples/json-parser-examples.ts +33 -33
  271. package/docs/02-CORE-GUIDES/parsers/examples/parquet-parser-examples.ts +47 -47
  272. package/docs/02-CORE-GUIDES/parsers/examples/xml-parser-examples.ts +38 -38
  273. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-01-foundations.md +355 -355
  274. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-02-csv-parser.md +772 -772
  275. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-03-json-parser.md +789 -789
  276. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-04-xml-parser.md +857 -857
  277. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-05-parquet-parser.md +603 -603
  278. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-integration-patterns.md +702 -702
  279. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-streaming.md +121 -121
  280. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-api-reference.md +89 -89
  281. package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-troubleshooting.md +727 -727
  282. package/docs/02-CORE-GUIDES/parsers/parsers-quick-reference.md +482 -482
  283. package/docs/02-CORE-GUIDES/parsers/parsers-readme.md +258 -258
  284. package/docs/02-CORE-GUIDES/parsers/readme.md +65 -65
  285. package/docs/02-CORE-GUIDES/readme.md +194 -194
  286. package/docs/02-CORE-GUIDES/webhook-validation/examples/basic-validation.ts +108 -108
  287. package/docs/02-CORE-GUIDES/webhook-validation/examples/common-patterns.ts +316 -316
  288. package/docs/02-CORE-GUIDES/webhook-validation/examples/webhook-validation-readme.md +61 -61
  289. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-01-foundations.md +440 -440
  290. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-02-quick-start.md +525 -525
  291. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-03-versori-integration.md +741 -741
  292. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-04-platform-integration.md +629 -629
  293. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-05-configuration.md +535 -535
  294. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-error-handling.md +611 -611
  295. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-troubleshooting.md +124 -124
  296. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-07-api-reference.md +511 -511
  297. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-08-rubix-webhooks.md +590 -590
  298. package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-09-rubix-event-vs-http-call.md +432 -432
  299. package/docs/02-CORE-GUIDES/webhook-validation/readme.md +239 -239
  300. package/docs/02-CORE-GUIDES/webhook-validation/webhook-validation-quick-reference.md +392 -392
  301. package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-quick-reference.md +498 -498
  302. package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-readme.md +313 -313
  303. package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/common-patterns.ts +612 -612
  304. package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/connector-scenarios-readme.md +253 -253
  305. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-01-foundations.md +452 -452
  306. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-02-simple-scenarios.md +681 -681
  307. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-03-intermediate-scenarios.md +637 -637
  308. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-04-advanced-scenarios.md +650 -650
  309. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-05-bidirectional-sync.md +233 -233
  310. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-06-production-patterns.md +442 -442
  311. package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-07-reference.md +445 -445
  312. package/docs/03-PATTERN-GUIDES/connector-scenarios/readme.md +31 -31
  313. package/docs/03-PATTERN-GUIDES/enterprise-integration-patterns.md +1528 -1528
  314. package/docs/03-PATTERN-GUIDES/error-handling/comprehensive-error-handling-guide.md +1437 -1437
  315. package/docs/03-PATTERN-GUIDES/error-handling/error-handling-quick-reference.md +390 -390
  316. package/docs/03-PATTERN-GUIDES/error-handling/examples/common-patterns.ts +438 -438
  317. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-01-foundations.md +362 -362
  318. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-02-error-types.md +850 -850
  319. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-03-utf8-handling.md +456 -456
  320. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-04-error-scenarios.md +658 -658
  321. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-05-calling-patterns.md +671 -671
  322. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-06-retry-strategies.md +1034 -1034
  323. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-07-monitoring.md +653 -653
  324. package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-08-api-reference.md +847 -847
  325. package/docs/03-PATTERN-GUIDES/error-handling/readme.md +36 -36
  326. package/docs/03-PATTERN-GUIDES/examples/__tests__/readme.md +40 -40
  327. package/docs/03-PATTERN-GUIDES/examples/__tests__/resolver-examples.test.js +282 -282
  328. package/docs/03-PATTERN-GUIDES/examples/test-data/03-pattern-guides-readme.md +110 -110
  329. package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-inventory.json +123 -123
  330. package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-order.json +171 -171
  331. package/docs/03-PATTERN-GUIDES/examples/test-data/readme.md +28 -28
  332. package/docs/03-PATTERN-GUIDES/extraction/extraction-readme.md +15 -15
  333. package/docs/03-PATTERN-GUIDES/extraction/readme.md +25 -25
  334. package/docs/03-PATTERN-GUIDES/file-operations/examples/common-patterns.ts +407 -407
  335. package/docs/03-PATTERN-GUIDES/file-operations/examples/file-operations-readme.md +142 -142
  336. package/docs/03-PATTERN-GUIDES/file-operations/file-operations-quick-reference.md +462 -462
  337. package/docs/03-PATTERN-GUIDES/file-operations/file-operations-readme.md +379 -379
  338. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-01-foundations.md +430 -430
  339. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-02-quick-start.md +484 -484
  340. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-03-s3-operations.md +507 -507
  341. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-04-sftp-operations.md +963 -963
  342. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-05-streaming-performance.md +503 -503
  343. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-archive-patterns.md +386 -386
  344. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-error-handling.md +117 -117
  345. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-api-reference.md +78 -78
  346. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-testing-troubleshooting.md +567 -567
  347. package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-08-api-reference.md +1055 -1055
  348. package/docs/03-PATTERN-GUIDES/file-operations/readme.md +32 -32
  349. package/docs/03-PATTERN-GUIDES/ingestion/ingestion-readme.md +15 -15
  350. package/docs/03-PATTERN-GUIDES/ingestion/readme.md +25 -25
  351. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/batch-processing.ts +130 -130
  352. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/common-patterns.ts +360 -360
  353. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/delta-sync.ts +130 -130
  354. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/integration-patterns-readme.md +100 -100
  355. package/docs/03-PATTERN-GUIDES/integration-patterns/examples/real-time-webhook.ts +398 -398
  356. package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-quick-reference.md +962 -962
  357. package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-readme.md +134 -134
  358. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-01-real-time-processing.md +991 -991
  359. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-02-batch-processing.md +1547 -1547
  360. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-03-delta-sync.md +1108 -1108
  361. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-04-webhook-patterns.md +1181 -1181
  362. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-05-error-handling.md +1061 -1061
  363. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-advanced-integration-services.md +1547 -1547
  364. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-performance.md +109 -109
  365. package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-07-api-reference.md +34 -34
  366. package/docs/03-PATTERN-GUIDES/integration-patterns/readme.md +30 -30
  367. package/docs/03-PATTERN-GUIDES/logging-minimal-mode.md +128 -128
  368. package/docs/03-PATTERN-GUIDES/multiple-connections/examples/common-patterns.ts +380 -380
  369. package/docs/03-PATTERN-GUIDES/multiple-connections/examples/multiple-connections-readme.md +139 -139
  370. package/docs/03-PATTERN-GUIDES/multiple-connections/examples/parallel-root-connections.ts +149 -149
  371. package/docs/03-PATTERN-GUIDES/multiple-connections/examples/real-world-scenarios.ts +405 -405
  372. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-01-foundations.md +378 -378
  373. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-02-quick-start.md +566 -566
  374. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-03-targeting-connections.md +659 -659
  375. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-04-parallel-queries.md +656 -656
  376. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-05-best-practices.md +624 -624
  377. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-api-reference.md +824 -824
  378. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-versori.md +119 -119
  379. package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-07-api-reference.md +87 -87
  380. package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-quick-reference.md +353 -353
  381. package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-readme.md +270 -270
  382. package/docs/03-PATTERN-GUIDES/multiple-connections/readme.md +30 -30
  383. package/docs/03-PATTERN-GUIDES/pagination/pagination-readme.md +14 -14
  384. package/docs/03-PATTERN-GUIDES/pagination/readme.md +24 -24
  385. package/docs/03-PATTERN-GUIDES/parquet/examples/common-patterns.ts +180 -180
  386. package/docs/03-PATTERN-GUIDES/parquet/examples/read-parquet.ts +48 -48
  387. package/docs/03-PATTERN-GUIDES/parquet/examples/write-parquet.ts +65 -65
  388. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-01-introduction.md +393 -393
  389. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-02-quick-start.md +572 -572
  390. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-03-reading-parquet.md +525 -525
  391. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-04-writing-parquet.md +554 -554
  392. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-05-graphql-extraction.md +405 -405
  393. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-performance.md +104 -104
  394. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-s3-integration.md +511 -511
  395. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-api-reference.md +90 -90
  396. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-performance-optimization.md +525 -525
  397. package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-08-best-practices.md +712 -712
  398. package/docs/03-PATTERN-GUIDES/parquet/parquet-quick-reference.md +683 -683
  399. package/docs/03-PATTERN-GUIDES/parquet/parquet-readme.md +248 -248
  400. package/docs/03-PATTERN-GUIDES/parquet/readme.md +32 -32
  401. package/docs/03-PATTERN-GUIDES/parsers/parsers-readme.md +12 -12
  402. package/docs/03-PATTERN-GUIDES/parsers/readme.md +24 -24
  403. package/docs/03-PATTERN-GUIDES/readme.md +159 -159
  404. package/docs/03-PATTERN-GUIDES/webhooks/readme.md +24 -24
  405. package/docs/03-PATTERN-GUIDES/webhooks/webhooks-readme.md +8 -8
  406. package/docs/04-REFERENCE/architecture/architecture-01-overview.md +427 -427
  407. package/docs/04-REFERENCE/architecture/architecture-02-client-architecture.md +424 -424
  408. package/docs/04-REFERENCE/architecture/architecture-03-data-flow.md +690 -690
  409. package/docs/04-REFERENCE/architecture/architecture-04-service-layer.md +834 -834
  410. package/docs/04-REFERENCE/architecture/architecture-05-integration-architecture.md +655 -655
  411. package/docs/04-REFERENCE/architecture/architecture-06-state-management.md +653 -653
  412. package/docs/04-REFERENCE/architecture/architecture-adding-new-data-sources.md +686 -686
  413. package/docs/04-REFERENCE/architecture/readme.md +279 -279
  414. package/docs/04-REFERENCE/platforms/deno/readme.md +117 -117
  415. package/docs/04-REFERENCE/platforms/nodejs/readme.md +146 -146
  416. package/docs/04-REFERENCE/platforms/readme.md +135 -135
  417. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-01-introduction.md +398 -398
  418. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-02-quick-start.md +560 -560
  419. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-03-authentication.md +757 -757
  420. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-04-workflows.md +2476 -2476
  421. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-05-connections.md +1167 -1167
  422. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-kv-storage.md +990 -990
  423. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-state-management.md +121 -121
  424. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-api-reference.md +68 -68
  425. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-deployment.md +731 -731
  426. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-08-best-practices.md +1111 -1111
  427. package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-09-signature-reference.md +766 -766
  428. package/docs/04-REFERENCE/platforms/versori/platforms-versori-readme.md +299 -299
  429. package/docs/04-REFERENCE/platforms/versori/platforms-versori-s3-sftp-configuration-guide.md +1425 -1425
  430. package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-api-key-security.md +816 -816
  431. package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-connection-security.md +681 -681
  432. package/docs/04-REFERENCE/platforms/versori/platforms-versori-workflow-task-types.md +708 -708
  433. package/docs/04-REFERENCE/platforms/versori/readme.md +108 -108
  434. package/docs/04-REFERENCE/readme.md +148 -148
  435. package/docs/04-REFERENCE/resolver-signature/examples/advanced-resolvers.ts +482 -482
  436. package/docs/04-REFERENCE/resolver-signature/examples/async-resolvers.ts +496 -496
  437. package/docs/04-REFERENCE/resolver-signature/examples/basic-resolvers.ts +343 -343
  438. package/docs/04-REFERENCE/resolver-signature/examples/resolver-signature-readme.md +188 -188
  439. package/docs/04-REFERENCE/resolver-signature/examples/testing-resolvers.ts +463 -463
  440. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-01-foundations.md +286 -286
  441. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-02-parameter-reference.md +643 -643
  442. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-03-basic-examples.md +521 -521
  443. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-04-advanced-patterns.md +739 -739
  444. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-05-sdk-resolvers.md +531 -531
  445. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-migration-guide.md +650 -650
  446. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-testing.md +125 -125
  447. package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-07-api-reference.md +794 -794
  448. package/docs/04-REFERENCE/resolver-signature/readme.md +64 -64
  449. package/docs/04-REFERENCE/resolver-signature/resolver-signature-quick-reference.md +270 -270
  450. package/docs/04-REFERENCE/resolver-signature/resolver-signature-readme.md +351 -351
  451. package/docs/04-REFERENCE/schema/fluent-commerce-schema.json +764 -764
  452. package/docs/04-REFERENCE/schema/readme.md +141 -141
  453. package/docs/04-REFERENCE/testing/examples/04-reference-testing-readme.md +158 -158
  454. package/docs/04-REFERENCE/testing/examples/fluent-testing.ts +62 -62
  455. package/docs/04-REFERENCE/testing/examples/health-check.ts +155 -155
  456. package/docs/04-REFERENCE/testing/examples/integration-test.ts +119 -119
  457. package/docs/04-REFERENCE/testing/examples/performance-test.ts +183 -183
  458. package/docs/04-REFERENCE/testing/examples/s3-testing.ts +127 -127
  459. package/docs/04-REFERENCE/testing/modules/04-reference-testing-01-foundations.md +267 -267
  460. package/docs/04-REFERENCE/testing/modules/04-reference-testing-02-s3-testing.md +599 -599
  461. package/docs/04-REFERENCE/testing/modules/04-reference-testing-03-fluent-testing.md +589 -589
  462. package/docs/04-REFERENCE/testing/modules/04-reference-testing-04-integration-testing.md +699 -699
  463. package/docs/04-REFERENCE/testing/modules/04-reference-testing-05-debugging.md +478 -478
  464. package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-cicd-integration.md +463 -463
  465. package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-preflight-validation.md +131 -131
  466. package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-best-practices.md +499 -499
  467. package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-coverage-ci.md +165 -165
  468. package/docs/04-REFERENCE/testing/modules/04-reference-testing-08-api-reference.md +634 -634
  469. package/docs/04-REFERENCE/testing/readme.md +86 -86
  470. package/docs/04-REFERENCE/testing/testing-quick-reference.md +667 -667
  471. package/docs/04-REFERENCE/testing/testing-readme.md +286 -286
  472. package/docs/04-REFERENCE/troubleshooting/readme.md +144 -144
  473. package/docs/04-REFERENCE/troubleshooting/troubleshooting-deno-sftp-compatibility.md +392 -392
  474. package/docs/template-loading-matrix.md +242 -242
  475. package/package.json +5 -3
  476. 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