@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,1167 +1,1167 @@
1
- # Module 5: Connection Management & Security
2
-
3
- [← Back to Versori Platform Guide](../platforms-versori-readme.md)
4
-
5
- **Module 5 of 8** | **Level**: Intermediate | **Time**: 20 minutes
6
-
7
- ---
8
-
9
- ## Learning Objectives
10
-
11
- By the end of this module, you will:
12
-
13
- - ✅ Understand different connection types in Versori
14
- - ✅ Configure OAuth2 connections for Fluent Commerce
15
- - ✅ Manage API key connections for S3 and other services
16
- - ✅ Validate connections before deployment
17
- - ✅ Implement connection security best practices
18
- - ✅ Handle multi-connection scenarios
19
- - ✅ Troubleshoot connection issues
20
-
21
- ---
22
-
23
- ## Connection Types Overview
24
-
25
- Versori supports multiple connection types for different authentication methods:
26
-
27
- | Connection Type | Use Case | Examples | Auth Method |
28
- | --------------- | ---------------------------------------- | ------------------------------ | ---------------------------------- |
29
- | **OAuth2** | API authentication with token management | Fluent Commerce, Salesforce | Client credentials, password grant |
30
- | **API Key** | Simple token-based auth | AWS S3, third-party APIs | Static API key |
31
- | **Basic Auth** | Username/password auth | Older APIs, internal services | HTTP Basic |
32
- | **Custom** | Proprietary auth methods | Custom headers, signatures | Custom implementation |
33
-
34
- ---
35
-
36
- ## OAuth2 Connections
37
-
38
- ### Fluent Commerce OAuth2 Configuration
39
-
40
- The most common connection type for Fluent Commerce integrations.
41
-
42
- #### Step-by-Step Configuration
43
-
44
- 1. **Navigate to Versori Dashboard**
45
- - Go to **Connections** tab
46
- - Click **"Add Connection"**
47
-
48
- 2. **Basic Information**
49
-
50
- ```
51
- Name: fluent_commerce
52
- Description: Fluent Commerce Production API
53
- Type: OAuth2
54
- ```
55
-
56
- 3. **OAuth2 Settings**
57
-
58
- ```
59
- Grant Type: client_credentials
60
- Auth URL: https://api.fluentcommerce.com/oauth/token
61
- Token URL: https://api.fluentcommerce.com/oauth/token
62
- Scope: (leave empty for Fluent)
63
- ```
64
-
65
- 4. **Client Credentials**
66
-
67
- ```
68
- Client ID: [Your Fluent OAuth2 Client ID]
69
- Client Secret: [Your Fluent OAuth2 Client Secret]
70
- ```
71
-
72
- 5. **Additional Configuration**
73
-
74
- ```
75
- Base URL: https://api.fluentcommerce.com
76
- Custom Headers: {"Content-Type": "application/json"}
77
- Custom Parameters: {"retailerId": "1"}
78
- ```
79
-
80
- 6. **Test Connection**
81
- - Click **"Test Connection"**
82
- - Verify successful token retrieval
83
- - Check token expiration settings
84
-
85
- ### Accessing OAuth2 Connection in Code
86
-
87
- ```typescript
88
- import { http } from '@versori/run';
89
- import { createClient } from '@fluentcommerce/fc-connect-sdk';
90
-
91
- export const useConnection = http(
92
- 'use-connection',
93
- {
94
- connection: 'fluent_commerce', // Must match connection name in UI
95
- },
96
- async ctx => {
97
- // Auto-configured client from connection
98
- const client = await createClient(ctx);
99
-
100
- // Access connection metadata
101
- const connectionInfo = ctx.activation?.connection;
102
- ctx.log('info', 'Connection details', {
103
- url: connectionInfo?.url,
104
- hasHeaders: !!connectionInfo?.headers,
105
- retailerId: connectionInfo?.params?.retailerId,
106
- });
107
-
108
- // Use client normally
109
- const result = await client.graphql({
110
- query: `query { products(first: 10) { edges { node { id ref } } } }`,
111
- });
112
-
113
- return result.data;
114
- }
115
- );
116
- ```
117
-
118
- ### OAuth2 Token Management
119
-
120
- Versori automatically handles:
121
-
122
- - **Token acquisition** on first request
123
- - **Token caching** for subsequent requests
124
- - **Token refresh** when expired
125
- - **Error handling** on token failures
126
-
127
- **You don't need to manage tokens manually!**
128
-
129
- ---
130
-
131
- ## API Key Connections
132
-
133
- For services that use simple API key authentication (e.g., AWS S3, third-party APIs).
134
-
135
- ### AWS S3 Connection Example
136
-
137
- 1. **Create Connection**
138
-
139
- ```
140
- Name: aws_s3
141
- Description: AWS S3 for inventory files
142
- Type: API Key
143
- ```
144
-
145
- 2. **Configuration**
146
-
147
- ```
148
- Authentication: Configure on the connection (no inline headers)
149
- Additional Headers:
150
- - x-secret-key: [Your AWS Secret Key]
151
- - x-region: us-east-1
152
- ```
153
-
154
- 3. **Access in Code**
155
-
156
- ```typescript
157
- export const readFromS3 = http(
158
- 'read-s3',
159
- {
160
- connection: 'aws_s3',
161
- },
162
- async ctx => {
163
- const s3Client = new S3Client({
164
- credentials: {
165
- accessKeyId: ctx.activation?.connection?.headers?.['x-api-key'],
166
- secretAccessKey: ctx.activation?.connection?.headers?.['x-secret-key'],
167
- },
168
- region: ctx.activation?.connection?.headers?.['x-region'],
169
- });
170
-
171
- // Use S3 client...
172
- }
173
- );
174
- ```
175
-
176
- ### Third-Party API Key Example
177
-
178
- ```typescript
179
- export const callThirdParty = http(
180
- 'third-party-api',
181
- {
182
- connection: 'third_party_service',
183
- },
184
- async ctx => {
185
- // API key is automatically included in headers
186
- const response = await ctx.fetch('https://api.thirdparty.com/data', {
187
- method: 'GET',
188
- // Headers from connection are automatically included
189
- });
190
-
191
- const data = await response.json();
192
- return data;
193
- }
194
- );
195
- ```
196
-
197
- ---
198
-
199
- ## Multi-Connection Scenarios
200
-
201
- Many integrations require multiple connections (e.g., Fluent + S3).
202
-
203
- ### Pattern 1: Primary Connection + SDK Client
204
-
205
- ```typescript
206
- import { http } from '@versori/run';
207
- import { createClient, S3DataSource } from '@fluentcommerce/fc-connect-sdk';
208
-
209
- /**
210
- * Fetch from S3, send to Fluent
211
- *
212
- * Uses: fluent_commerce (primary connection) + S3 credentials from env vars
213
- */
214
- export const s3ToFluent = http(
215
- 's3-to-fluent',
216
- {
217
- connection: 'fluent_commerce', // Primary connection
218
- },
219
- async ctx => {
220
- // Fluent client from primary connection
221
- const client = await createClient(ctx);
222
-
223
- // S3 client from environment variables
224
- const s3 = new S3DataSource({
225
- region: ctx.vars?.AWS_REGION || 'us-east-1',
226
- credentials: {
227
- accessKeyId: ctx.vars?.AWS_ACCESS_KEY_ID,
228
- secretAccessKey: ctx.vars?.AWS_SECRET_ACCESS_KEY,
229
- },
230
- });
231
-
232
- // Fetch from S3
233
- const csvData = await s3.readFile('inventory-bucket', 'inventory.csv');
234
-
235
- // Parse and send to Fluent
236
- const records = parseCSV(csvData);
237
- const job = await client.createJob({ name: 'S3 Import' });
238
- await client.sendBatch(job.id, {
239
- action: 'UPSERT',
240
- entityType: 'INVENTORY',
241
- entities: records,
242
- });
243
-
244
- return { success: true, recordCount: records.length };
245
- }
246
- );
247
- ```
248
-
249
- ### Pattern 2: Multiple Connections via ctx.connections
250
-
251
- ```typescript
252
- export const multiConnection = http(
253
- 'multi-connection',
254
- {
255
- connection: 'fluent_commerce',
256
- },
257
- async ctx => {
258
- // Primary connection (Fluent)
259
- const fluentClient = await createClient(ctx);
260
-
261
- // Access other connections
262
- const s3Connection = ctx.connections?.aws_s3;
263
- const sfccConnection = ctx.connections?.sfcc_api;
264
-
265
- // Use multiple services
266
- const fluentData = await fluentClient.graphql({ query: '...' });
267
- const s3Data = await fetchFromS3WithConnection(s3Connection);
268
- const sfccData = await fetchFromSFCCWithConnection(sfccConnection);
269
-
270
- return {
271
- fluent: fluentData,
272
- s3: s3Data,
273
- sfcc: sfccData,
274
- };
275
- }
276
- );
277
- ```
278
-
279
- ---
280
-
281
- ## Connection Validation
282
-
283
- ### Pre-Deployment Validation
284
-
285
- Before deploying, validate all connections:
286
-
287
- ```typescript
288
- import { fn } from '@versori/run';
289
-
290
- /**
291
- * Validate all required connections
292
- *
293
- * Run manually before deployment
294
- */
295
- export const validateConnections = fn('validate-connections', async ctx => {
296
- const requiredConnections = ['fluent_commerce', 'aws_s3', 'sfcc_api'];
297
-
298
- const results = {};
299
-
300
- for (const connName of requiredConnections) {
301
- const conn = ctx.connections?.[connName];
302
-
303
- if (!conn) {
304
- results[connName] = {
305
- status: 'missing',
306
- error: 'Connection not configured',
307
- };
308
- continue;
309
- }
310
-
311
- // Basic validation
312
- results[connName] = {
313
- status: 'configured',
314
- hasUrl: !!conn.url,
315
- hasHeaders: !!conn.headers,
316
- hasParams: !!conn.params,
317
- };
318
- }
319
-
320
- ctx.log('info', 'Connection validation complete', results);
321
-
322
- return results;
323
- });
324
- ```
325
-
326
- ### Runtime Connection Testing
327
-
328
- ```typescript
329
- import { http } from '@versori/run';
330
- import { createClient } from '@fluentcommerce/fc-connect-sdk';
331
-
332
- /**
333
- * Test Fluent Commerce connection
334
- *
335
- * GET https://{workspace}.versori.run/test-connection
336
- */
337
- export const testConnection = http(
338
- 'test-connection',
339
- {
340
- connection: 'fluent_commerce',
341
- },
342
- async ctx => {
343
- try {
344
- const client = await createClient(ctx);
345
-
346
- // Simple query to test connection
347
- const result = await client.graphql({
348
- query: `query { __typename }`,
349
- });
350
-
351
- if (result.errors?.length) {
352
- return {
353
- success: false,
354
- error: 'GraphQL error',
355
- details: result.errors[0].message,
356
- };
357
- }
358
-
359
- ctx.log('info', 'Connection test successful');
360
-
361
- return {
362
- success: true,
363
- message: 'Connection working',
364
- timestamp: new Date().toISOString(),
365
- };
366
- } catch (error) {
367
- ctx.log('error', 'Connection test failed', {
368
- error: error instanceof Error ? error.message : String(error),
369
- });
370
-
371
- return {
372
- success: false,
373
- error: error instanceof Error ? error.message : 'Connection failed',
374
- };
375
- }
376
- }
377
- );
378
- ```
379
-
380
- ---
381
-
382
- ## Security Best Practices
383
-
384
- ### 1. Never Hardcode Credentials
385
-
386
- ```typescript
387
- // ❌ WRONG - Hardcoded credentials
388
- export const bad = http(
389
- 'bad',
390
- {
391
- connection: 'fluent',
392
- },
393
- async ctx => {
394
- const clientId = 'my-client-id'; // NEVER do this!
395
- const clientSecret = 'my-secret'; // NEVER do this!
396
- }
397
- );
398
-
399
- // ✅ CORRECT - Use connection or environment variables
400
- export const good = http(
401
- 'good',
402
- {
403
- connection: 'fluent_commerce',
404
- },
405
- async ctx => {
406
- const client = await createClient(ctx); // Credentials from connection
407
- }
408
- );
409
- ```
410
-
411
- ### 2. Use Connector Variables for Secrets
412
-
413
- Configure sensitive values in Versori UI:
414
-
415
- **Versori Dashboard → Connector → Variables**:
416
-
417
- ```
418
- Name: FLUENT_WEBHOOK_PUBLIC_KEY
419
- Value: -----BEGIN PUBLIC KEY-----...
420
- Type: Secret
421
- ```
422
-
423
- **Access in code**:
424
-
425
- ```typescript
426
- export const useSecrets = webhook('use-secrets', async ctx => {
427
- // Access secret variable
428
- const publicKey = ctx.vars?.FLUENT_WEBHOOK_PUBLIC_KEY;
429
-
430
- if (!publicKey) {
431
- return { error: 'Missing public key configuration' };
432
- }
433
-
434
- // Use securely
435
- const validator = new WebhookValidationService({ publicKey });
436
- // ...
437
- });
438
- ```
439
-
440
- ### 3. Environment-Specific Connections
441
-
442
- Maintain separate connections for each environment:
443
-
444
- ```
445
- Development:
446
- - fluent_commerce_dev
447
- - aws_s3_dev
448
-
449
- Staging:
450
- - fluent_commerce_staging
451
- - aws_s3_staging
452
-
453
- Production:
454
- - fluent_commerce_prod
455
- - aws_s3_prod
456
- ```
457
-
458
- **Code pattern**:
459
-
460
- ```typescript
461
- export const envAwareWorkflow = http(
462
- 'env-aware',
463
- {
464
- connection:
465
- process.env.NODE_ENV === 'production' ? 'fluent_commerce_prod' : 'fluent_commerce_dev',
466
- },
467
- async ctx => {
468
- const client = await createClient(ctx);
469
- // ...
470
- }
471
- );
472
- ```
473
-
474
- ### 4. Rotate Credentials Regularly
475
-
476
- - **OAuth2 Client Secrets**: Rotate every 90 days
477
- - **API Keys**: Rotate every 180 days
478
- - **Webhook Public Keys**: Rotate on security events
479
-
480
- **Update process**:
481
-
482
- 1. Generate new credentials in source system
483
- 2. Update connection in Versori UI
484
- 3. Test connection
485
- 4. Deactivate old credentials after confirmation
486
-
487
- ### 5. Audit Connection Access
488
-
489
- ```typescript
490
- export const auditedWorkflow = http(
491
- 'audited',
492
- {
493
- connection: 'fluent_commerce',
494
- },
495
- async ctx => {
496
- // Log connection usage
497
- ctx.log('info', 'Connection accessed', {
498
- workflow: 'audited',
499
- connection: 'fluent_commerce',
500
- timestamp: Date.now(),
501
- executionId: ctx.executionId,
502
- user: ctx.activation?.user || 'system',
503
- });
504
-
505
- const client = await createClient(ctx);
506
- // ... rest of workflow
507
- }
508
- );
509
- ```
510
-
511
- ---
512
-
513
- ## Accessing All Connections (v0.4.x+)
514
-
515
- ### NEW: activation.connections Array
516
-
517
- As of @versori/run v0.4.x, you can access **all configured connections** for the current activation via `ctx.activation.connections`.
518
-
519
- #### Connection Structure
520
-
521
- ```typescript
522
- type Connection = {
523
- id: string; // Unique connection ID
524
- name: string; // Connection name (matches UI)
525
- templateId: string; // Connection template/type ID
526
- dynamic: boolean; // Whether connection is dynamic
527
- baseUrl: string; // Base URL for the connection
528
- createdAt: string; // ISO timestamp
529
- updatedAt: string; // ISO timestamp
530
- credentials: ConnectionCredential[]; // Credential details
531
- }
532
- ```
533
-
534
- #### Listing All Available Connections
535
-
536
- ```typescript
537
- import { fn } from '@versori/run';
538
-
539
- /**
540
- * List all connections for current activation
541
- */
542
- export const listConnections = fn('list-connections', ctx => {
543
- const connections = ctx.activation.connections;
544
-
545
- if (!connections || connections.length === 0) {
546
- return { message: 'No connections configured', count: 0 };
547
- }
548
-
549
- ctx.log.info('Available connections', {
550
- count: connections.length,
551
- names: connections.map(c => c.name)
552
- });
553
-
554
- return {
555
- count: connections.length,
556
- connections: connections.map(c => ({
557
- name: c.name,
558
- id: c.id,
559
- baseUrl: c.baseUrl,
560
- dynamic: c.dynamic,
561
- createdAt: c.createdAt
562
- }))
563
- };
564
- });
565
- ```
566
-
567
- #### Finding Specific Connection
568
-
569
- ```typescript
570
- import { fn } from '@versori/run';
571
-
572
- /**
573
- * Check if Fluent Commerce connection exists
574
- */
575
- export const checkFluentConnection = fn('check-fluent-connection', ctx => {
576
- const connections = ctx.activation.connections;
577
- const fluentConn = connections?.find(c => c.name === 'fluent_commerce');
578
-
579
- if (!fluentConn) {
580
- throw new Error('Fluent Commerce connection not configured');
581
- }
582
-
583
- ctx.log.info('Fluent connection found', {
584
- id: fluentConn.id,
585
- baseUrl: fluentConn.baseUrl,
586
- dynamic: fluentConn.dynamic
587
- });
588
-
589
- return {
590
- found: true,
591
- connectionId: fluentConn.id,
592
- baseUrl: fluentConn.baseUrl
593
- };
594
- });
595
- ```
596
-
597
- ### Multi-Tenant Pattern with activation.connections
598
-
599
- **Use Case**: One connector serves multiple customers, each with their own Fluent instance.
600
-
601
- ```typescript
602
- import { webhook, fn, http } from '@versori/run';
603
- import { createClient } from '@fluentcommerce/fc-connect-sdk';
604
-
605
- /**
606
- * Multi-tenant order creation
607
- *
608
- * POST https://{workspace}.versori.run/create-order
609
- * Body: { customerId: "customer-a", orderData: {...} }
610
- */
611
- export const multiTenantOrderCreate = webhook('multi-tenant-order-create', {
612
- response: { mode: 'sync' },
613
- })
614
- // Step 1: Route to correct Fluent connection (fn)
615
- .then(fn('route-connection', ctx => {
616
- const { customerId, orderData } = ctx.data;
617
-
618
- if (!customerId) {
619
- throw new Error('customerId is required');
620
- }
621
-
622
- // Access all connections
623
- const connections = ctx.activation.connections;
624
-
625
- if (!connections || connections.length === 0) {
626
- throw new Error('No connections configured for this activation');
627
- }
628
-
629
- // Find customer-specific connection
630
- // Convention: connections named fluent_customer-a, fluent_customer-b, etc.
631
- const connectionName = `fluent_${customerId.toLowerCase()}`;
632
- const connection = connections.find(c => c.name === connectionName);
633
-
634
- if (!connection) {
635
- throw new Error(`No Fluent connection found for customer: ${customerId}`);
636
- }
637
-
638
- ctx.log.info('Routed to customer connection', {
639
- customerId,
640
- connectionName: connection.name,
641
- connectionId: connection.id,
642
- baseUrl: connection.baseUrl
643
- });
644
-
645
- return {
646
- connectionName: connection.name,
647
- customerId,
648
- orderData
649
- };
650
- }))
651
-
652
- // Step 2: Create order in customer's Fluent instance (http)
653
- .then(http('create-order', (ctx) => {
654
- // Return dynamic connection based on routing
655
- return { connection: ctx.data.connectionName };
656
- }, async ctx => {
657
- const { customerId, orderData } = ctx.data;
658
-
659
- // Create client with customer-specific connection
660
- const client = await createClient(ctx);
661
-
662
- // Create order
663
- const result = await client.graphql({
664
- query: `
665
- mutation CreateOrder($input: CreateOrderInput!) {
666
- createOrder(input: $input) {
667
- id
668
- ref
669
- status
670
- }
671
- }
672
- `,
673
- variables: { input: orderData }
674
- });
675
-
676
- if (result.errors?.length) {
677
- throw new Error(`Order creation failed: ${result.errors[0].message}`);
678
- }
679
-
680
- ctx.log.info('Order created', {
681
- customerId,
682
- orderId: result.data.createOrder.id
683
- });
684
-
685
- return {
686
- success: true,
687
- customerId,
688
- orderId: result.data.createOrder.id,
689
- orderRef: result.data.createOrder.ref
690
- };
691
- }))
692
-
693
- .catch(({ data }) => ({
694
- success: false,
695
- error: data instanceof Error ? data.message : String(data),
696
- status: 500
697
- }));
698
- ```
699
-
700
- ### Iterating Through Multiple Connections
701
-
702
- **Use Case**: Health check across all Fluent connections.
703
-
704
- ```typescript
705
- import { fn, http } from '@versori/run';
706
- import { createClient } from '@fluentcommerce/fc-connect-sdk';
707
-
708
- /**
709
- * Test all Fluent connections
710
- *
711
- * GET https://{workspace}.versori.run/test-all-connections
712
- */
713
- export const testAllConnections = fn('test-all-fluent', async ctx => {
714
- const connections = ctx.activation.connections;
715
-
716
- // Filter to only Fluent connections (by name convention)
717
- const fluentConnections = connections?.filter(c =>
718
- c.name.startsWith('fluent_')
719
- ) || [];
720
-
721
- if (fluentConnections.length === 0) {
722
- return { message: 'No Fluent connections found', count: 0 };
723
- }
724
-
725
- ctx.log.info('Testing Fluent connections', {
726
- count: fluentConnections.length
727
- });
728
-
729
- const results = [];
730
-
731
- // Test each connection
732
- for (const conn of fluentConnections) {
733
- try {
734
- // Note: To actually test, we'd need to use http() with the connection
735
- // This example shows discovery only
736
- results.push({
737
- name: conn.name,
738
- id: conn.id,
739
- baseUrl: conn.baseUrl,
740
- status: 'configured',
741
- available: true
742
- });
743
- } catch (error) {
744
- results.push({
745
- name: conn.name,
746
- id: conn.id,
747
- status: 'error',
748
- available: false,
749
- error: error instanceof Error ? error.message : String(error)
750
- });
751
- }
752
- }
753
-
754
- return {
755
- totalConnections: fluentConnections.length,
756
- results
757
- };
758
- });
759
- ```
760
-
761
- ### Validation Pattern: Required Connections
762
-
763
- ```typescript
764
- import { fn } from '@versori/run';
765
-
766
- /**
767
- * Validate required connections exist
768
- *
769
- * Recommended to run at connector startup
770
- */
771
- export const validateRequiredConnections = fn('validate-required', ctx => {
772
- const required = ['fluent_commerce', 'aws_s3', 'sftp_warehouse'];
773
- const connections = ctx.activation.connections || [];
774
- const connectionNames = new Set(connections.map(c => c.name));
775
-
776
- const missing = required.filter(name => !connectionNames.has(name));
777
-
778
- if (missing.length > 0) {
779
- throw new Error(`Missing required connections: ${missing.join(', ')}`);
780
- }
781
-
782
- ctx.log.info('All required connections configured', {
783
- required: required.length,
784
- configured: connections.length
785
- });
786
-
787
- return {
788
- valid: true,
789
- requiredConnections: required,
790
- totalConnections: connections.length
791
- };
792
- });
793
- ```
794
-
795
- ---
796
-
797
- ## Activation Environment & Dynamic Variables (v0.4.x+)
798
-
799
- ### activation.environment
800
-
801
- Access the current activation's environment information:
802
-
803
- ```typescript
804
- import { fn } from '@versori/run';
805
-
806
- /**
807
- * Check environment and apply environment-specific logic
808
- */
809
- export const envAwareWorkflow = fn('env-aware', ctx => {
810
- const env = ctx.activation.environment;
811
-
812
- if (!env) {
813
- ctx.log.warn('No environment information available');
814
- return { environment: 'unknown' };
815
- }
816
-
817
- ctx.log.info('Environment details', {
818
- id: env.id,
819
- name: env.name,
820
- type: env.type // e.g., 'development', 'staging', 'production'
821
- });
822
-
823
- // Conditional logic based on environment
824
- if (env.name === 'production') {
825
- // Use production-specific settings
826
- return {
827
- environment: 'production',
828
- batchSize: 1000,
829
- retryAttempts: 5,
830
- timeout: 60000
831
- };
832
- } else if (env.name === 'staging') {
833
- return {
834
- environment: 'staging',
835
- batchSize: 100,
836
- retryAttempts: 3,
837
- timeout: 30000
838
- };
839
- } else {
840
- return {
841
- environment: 'development',
842
- batchSize: 10,
843
- retryAttempts: 1,
844
- timeout: 10000
845
- };
846
- }
847
- });
848
- ```
849
-
850
- ### activation.dynamicVariables
851
-
852
- Access dynamic variables set at the activation level:
853
-
854
- ```typescript
855
- import { fn } from '@versori/run';
856
-
857
- /**
858
- * Access activation-level dynamic variables
859
- */
860
- export const useDynamicVars = fn('use-dynamic-vars', ctx => {
861
- // Get variables using getVariable
862
- const apiKey = ctx.activation.getVariable<string>('API_KEY');
863
- const retailerId = ctx.activation.getVariable<number>('RETAILER_ID');
864
- const region = ctx.activation.getVariable<string>('AWS_REGION');
865
-
866
- ctx.log.info('Dynamic variables', {
867
- hasApiKey: !!apiKey,
868
- retailerId,
869
- region
870
- });
871
-
872
- // Use variables in your workflow
873
- return {
874
- retailerId,
875
- region,
876
- configured: !!apiKey && !!retailerId
877
- };
878
- });
879
- ```
880
-
881
- ### Setting Variables Programmatically
882
-
883
- ```typescript
884
- import { http } from '@versori/run';
885
- import { createClient } from '@fluentcommerce/fc-connect-sdk';
886
-
887
- /**
888
- * Cache frequently-used data in activation variables
889
- */
890
- export const cacheRetailerConfig = http(
891
- 'cache-retailer-config',
892
- { connection: 'fluent_commerce' },
893
- async ctx => {
894
- const client = await createClient(ctx);
895
-
896
- // Query Fluent for retailer configuration
897
- const result = await client.graphql({
898
- query: `
899
- query GetRetailer($id: Int!) {
900
- retailer(id: $id) {
901
- id
902
- name
903
- tradingName
904
- supportEmail
905
- primaryLocation {
906
- ref
907
- }
908
- }
909
- }
910
- `,
911
- variables: { id: 1 }
912
- });
913
-
914
- const retailer = result.data.retailer;
915
-
916
- // Cache in activation variables for future workflows
917
- await ctx.activation.setVariable('CACHED_RETAILER_ID', retailer.id);
918
- await ctx.activation.setVariable('CACHED_RETAILER_NAME', retailer.name);
919
- await ctx.activation.setVariable('CACHED_PRIMARY_LOCATION', retailer.primaryLocation.ref);
920
- await ctx.activation.setVariable('LAST_CONFIG_REFRESH', Date.now());
921
-
922
- ctx.log.info('Retailer config cached', {
923
- retailerId: retailer.id,
924
- retailerName: retailer.name
925
- });
926
-
927
- return {
928
- cached: true,
929
- retailer: {
930
- id: retailer.id,
931
- name: retailer.name
932
- }
933
- };
934
- }
935
- );
936
- ```
937
-
938
- ### Complete ActivationImpl Reference
939
-
940
- ```typescript
941
- interface ActivationImpl {
942
- // Properties
943
- get id(): string; // Activation ID
944
- get user(): EndUser; // User info
945
- get environment(): ProjectEnvironment | undefined; // ✅ NEW in v0.4.x
946
- get connections(): Array<Connection> | undefined; // ✅ NEW in v0.4.x
947
- get dynamicVariables(): DynamicVariables | undefined; // ✅ NEW in v0.4.x
948
-
949
- // Methods
950
- getVariable<T = unknown>(name: string): T | undefined;
951
- setVariable(name: string, value: unknown): Promise<void>;
952
- }
953
- ```
954
-
955
- ---
956
-
957
- ## Troubleshooting Connection Issues
958
-
959
- ### Common Issues & Solutions
960
-
961
- | Issue | Symptoms | Solution |
962
- | ------------------------ | ------------------------------------ | ---------------------------------------------------------- |
963
- | **Connection not found** | `Error: Connection 'xyz' not found` | Verify connection name matches UI exactly (case-sensitive) |
964
- | **Token expired** | `401 Unauthorized` | Versori should auto-refresh; check token URL configuration |
965
- | **Invalid credentials** | `403 Forbidden` | Verify Client ID/Secret in Fluent dashboard |
966
- | **Missing retailerId** | `retailerId is required for job creation` | Use `client.setRetailerId('1')` or pass in method call. See [retailerId Configuration Guide](../../../../00-START-HERE/retailerid-configuration.md) |
967
- | **CORS errors** | `CORS policy blocked` | Enable CORS in webhook configuration |
968
- | **Rate limiting** | `429 Too Many Requests` | Implement retry with backoff, check Fluent API limits |
969
-
970
- ### Debug Connection Configuration
971
-
972
- ```typescript
973
- export const debugConnection = http(
974
- 'debug-connection',
975
- {
976
- connection: 'fluent_commerce',
977
- },
978
- async ctx => {
979
- const conn = ctx.activation?.connection;
980
-
981
- // Log all connection details (except secrets)
982
- ctx.log('debug', 'Connection configuration', {
983
- hasConnection: !!conn,
984
- url: conn?.url,
985
- headerKeys: conn?.headers ? Object.keys(conn.headers) : [],
986
- paramKeys: conn?.params ? Object.keys(conn.params) : [],
987
- retailerId: conn?.params?.retailerId,
988
- });
989
-
990
- // Test basic connectivity
991
- try {
992
- const response = await ctx.fetch(conn?.url || 'https://api.fluentcommerce.com', {
993
- method: 'HEAD',
994
- });
995
-
996
- return {
997
- connectionStatus: 'reachable',
998
- statusCode: response.status,
999
- headers: Object.fromEntries(response.headers.entries()),
1000
- };
1001
- } catch (error) {
1002
- return {
1003
- connectionStatus: 'unreachable',
1004
- error: error instanceof Error ? error.message : String(error),
1005
- };
1006
- }
1007
- }
1008
- );
1009
- ```
1010
-
1011
- ### Validate OAuth2 Token
1012
-
1013
- ```typescript
1014
- export const validateToken = http(
1015
- 'validate-token',
1016
- {
1017
- connection: 'fluent_commerce',
1018
- },
1019
- async ctx => {
1020
- const conn = ctx.activation?.connection;
1021
-
1022
- // Extract token from headers (Versori auto-includes)
1023
- const authHeader = conn?.headers?.['Authorization'];
1024
-
1025
- if (!authHeader) {
1026
- return { error: 'No authorization header found' };
1027
- }
1028
-
1029
- // Parse token (Bearer <token>)
1030
- const token = authHeader.replace('Bearer ', '');
1031
-
1032
- // Decode JWT (if applicable)
1033
- try {
1034
- const parts = token.split('.');
1035
- if (parts.length === 3) {
1036
- const payload = JSON.parse(atob(parts[1]));
1037
-
1038
- return {
1039
- tokenValid: true,
1040
- expiresAt: payload.exp ? new Date(payload.exp * 1000).toISOString() : 'unknown',
1041
- issuedAt: payload.iat ? new Date(payload.iat * 1000).toISOString() : 'unknown',
1042
- scopes: payload.scope || [],
1043
- };
1044
- }
1045
- } catch (error) {
1046
- return {
1047
- tokenValid: false,
1048
- error: 'Invalid JWT format',
1049
- };
1050
- }
1051
-
1052
- return { tokenValid: true, tokenLength: token.length };
1053
- }
1054
- );
1055
- ```
1056
-
1057
- ---
1058
-
1059
- ## Advanced Connection Patterns
1060
-
1061
- ### Pattern 1: Connection Fallback
1062
-
1063
- ```typescript
1064
- export const withFallback = http(
1065
- 'connection-fallback',
1066
- {
1067
- connection: 'fluent_commerce_primary',
1068
- },
1069
- async ctx => {
1070
- try {
1071
- // Try primary connection
1072
- const client = await createClient(ctx);
1073
- return await client.graphql({ query: '...' });
1074
- } catch (primaryError) {
1075
- ctx.log('warn', 'Primary connection failed, trying fallback');
1076
-
1077
- try {
1078
- // Fallback to secondary connection
1079
- const fallbackClient = await createClient({
1080
- connection: ctx.connections?.fluent_commerce_secondary,
1081
- log: ctx.log,
1082
- });
1083
-
1084
- return await fallbackClient.graphql({ query: '...' });
1085
- } catch (fallbackError) {
1086
- throw new Error('All connections failed');
1087
- }
1088
- }
1089
- }
1090
- );
1091
- ```
1092
-
1093
- ### Pattern 2: Dynamic Connection Selection
1094
-
1095
- ```typescript
1096
- export const dynamicConnection = http('dynamic-connection', async ctx => {
1097
- // Select connection based on request parameter
1098
- const environment = ctx.query?.env || 'production';
1099
-
1100
- const connectionName =
1101
- environment === 'staging' ? 'fluent_commerce_staging' : 'fluent_commerce_prod';
1102
-
1103
- ctx.log('info', 'Selected connection', { connectionName, environment });
1104
-
1105
- // Note: This pattern requires accessing ctx.connections
1106
- const client = await createClient({
1107
- connection: ctx.connections?.[connectionName],
1108
- log: ctx.log,
1109
- });
1110
-
1111
- return await client.graphql({ query: '...' });
1112
- });
1113
- ```
1114
-
1115
- ---
1116
-
1117
- ## Key Takeaways
1118
-
1119
- - 🎯 **OAuth2 connections** are managed by Versori - automatic token refresh
1120
- - 🎯 **Connection name** in code must match UI exactly (case-sensitive)
1121
- - 🎯 **Never hardcode** credentials - use connections or environment variables
1122
- - 🎯 **Multi-connection scenarios** use primary connection + ctx.connections
1123
- - 🎯 **Validate connections** before deployment with test workflows
1124
- - 🎯 **Security best practices**: rotate credentials, use secrets, audit access
1125
- - 🎯 **Troubleshooting**: check name match, token expiration, credential validity
1126
-
1127
- ---
1128
-
1129
- ## Practice Exercise
1130
-
1131
- Create a workflow that:
1132
-
1133
- 1. Uses OAuth2 connection to Fluent Commerce
1134
- 2. Validates connection on startup
1135
- 3. Falls back to secondary connection on failure
1136
- 4. Logs all connection attempts for audit
1137
- 5. Returns connection health status
1138
-
1139
- **Hints**:
1140
-
1141
- - Use `http()` with primary connection
1142
- - Implement try/catch for fallback
1143
- - Use `ctx.log()` for audit trail
1144
- - Test token validity before GraphQL calls
1145
-
1146
- **Solution** available in [Module 8: Best Practices](./platforms-versori-08-best-practices.md#practice-solutions)
1147
-
1148
- ---
1149
-
1150
- ## Next Steps
1151
-
1152
- Now that you understand connection management, let's explore state management with KV storage.
1153
-
1154
- Continue to [Module 6: KV Storage →](./platforms-versori-06-kv-storage.md) to learn about distributed state, file tracking, and caching patterns.
1155
-
1156
- ---
1157
-
1158
- ## Related Documentation
1159
-
1160
- - [Module 3: Authentication](./platforms-versori-03-authentication.md) - OAuth2 basics
1161
- - [Module 4: Workflows](./platforms-versori-04-workflows.md) - Using connections in workflows
1162
- - [Module 6: KV Storage](./platforms-versori-06-kv-storage.md) - State management
1163
- - [Module 8: Best Practices](./platforms-versori-08-best-practices.md) - Security hardening
1164
-
1165
- ---
1166
-
1167
- [← Previous: Module 4](./platforms-versori-04-workflows.md) | [Back to Guide](../platforms-versori-readme.md) | [Next: Module 6: KV Storage →](./platforms-versori-06-kv-storage.md)
1
+ # Module 5: Connection Management & Security
2
+
3
+ [← Back to Versori Platform Guide](../platforms-versori-readme.md)
4
+
5
+ **Module 5 of 8** | **Level**: Intermediate | **Time**: 20 minutes
6
+
7
+ ---
8
+
9
+ ## Learning Objectives
10
+
11
+ By the end of this module, you will:
12
+
13
+ - ✅ Understand different connection types in Versori
14
+ - ✅ Configure OAuth2 connections for Fluent Commerce
15
+ - ✅ Manage API key connections for S3 and other services
16
+ - ✅ Validate connections before deployment
17
+ - ✅ Implement connection security best practices
18
+ - ✅ Handle multi-connection scenarios
19
+ - ✅ Troubleshoot connection issues
20
+
21
+ ---
22
+
23
+ ## Connection Types Overview
24
+
25
+ Versori supports multiple connection types for different authentication methods:
26
+
27
+ | Connection Type | Use Case | Examples | Auth Method |
28
+ | --------------- | ---------------------------------------- | ------------------------------ | ---------------------------------- |
29
+ | **OAuth2** | API authentication with token management | Fluent Commerce, Salesforce | Client credentials, password grant |
30
+ | **API Key** | Simple token-based auth | AWS S3, third-party APIs | Static API key |
31
+ | **Basic Auth** | Username/password auth | Older APIs, internal services | HTTP Basic |
32
+ | **Custom** | Proprietary auth methods | Custom headers, signatures | Custom implementation |
33
+
34
+ ---
35
+
36
+ ## OAuth2 Connections
37
+
38
+ ### Fluent Commerce OAuth2 Configuration
39
+
40
+ The most common connection type for Fluent Commerce integrations.
41
+
42
+ #### Step-by-Step Configuration
43
+
44
+ 1. **Navigate to Versori Dashboard**
45
+ - Go to **Connections** tab
46
+ - Click **"Add Connection"**
47
+
48
+ 2. **Basic Information**
49
+
50
+ ```
51
+ Name: fluent_commerce
52
+ Description: Fluent Commerce Production API
53
+ Type: OAuth2
54
+ ```
55
+
56
+ 3. **OAuth2 Settings**
57
+
58
+ ```
59
+ Grant Type: client_credentials
60
+ Auth URL: https://api.fluentcommerce.com/oauth/token
61
+ Token URL: https://api.fluentcommerce.com/oauth/token
62
+ Scope: (leave empty for Fluent)
63
+ ```
64
+
65
+ 4. **Client Credentials**
66
+
67
+ ```
68
+ Client ID: [Your Fluent OAuth2 Client ID]
69
+ Client Secret: [Your Fluent OAuth2 Client Secret]
70
+ ```
71
+
72
+ 5. **Additional Configuration**
73
+
74
+ ```
75
+ Base URL: https://api.fluentcommerce.com
76
+ Custom Headers: {"Content-Type": "application/json"}
77
+ Custom Parameters: {"retailerId": "1"}
78
+ ```
79
+
80
+ 6. **Test Connection**
81
+ - Click **"Test Connection"**
82
+ - Verify successful token retrieval
83
+ - Check token expiration settings
84
+
85
+ ### Accessing OAuth2 Connection in Code
86
+
87
+ ```typescript
88
+ import { http } from '@versori/run';
89
+ import { createClient } from '@fluentcommerce/fc-connect-sdk';
90
+
91
+ export const useConnection = http(
92
+ 'use-connection',
93
+ {
94
+ connection: 'fluent_commerce', // Must match connection name in UI
95
+ },
96
+ async ctx => {
97
+ // Auto-configured client from connection
98
+ const client = await createClient(ctx);
99
+
100
+ // Access connection metadata
101
+ const connectionInfo = ctx.activation?.connection;
102
+ ctx.log('info', 'Connection details', {
103
+ url: connectionInfo?.url,
104
+ hasHeaders: !!connectionInfo?.headers,
105
+ retailerId: connectionInfo?.params?.retailerId,
106
+ });
107
+
108
+ // Use client normally
109
+ const result = await client.graphql({
110
+ query: `query { products(first: 10) { edges { node { id ref } } } }`,
111
+ });
112
+
113
+ return result.data;
114
+ }
115
+ );
116
+ ```
117
+
118
+ ### OAuth2 Token Management
119
+
120
+ Versori automatically handles:
121
+
122
+ - **Token acquisition** on first request
123
+ - **Token caching** for subsequent requests
124
+ - **Token refresh** when expired
125
+ - **Error handling** on token failures
126
+
127
+ **You don't need to manage tokens manually!**
128
+
129
+ ---
130
+
131
+ ## API Key Connections
132
+
133
+ For services that use simple API key authentication (e.g., AWS S3, third-party APIs).
134
+
135
+ ### AWS S3 Connection Example
136
+
137
+ 1. **Create Connection**
138
+
139
+ ```
140
+ Name: aws_s3
141
+ Description: AWS S3 for inventory files
142
+ Type: API Key
143
+ ```
144
+
145
+ 2. **Configuration**
146
+
147
+ ```
148
+ Authentication: Configure on the connection (no inline headers)
149
+ Additional Headers:
150
+ - x-secret-key: [Your AWS Secret Key]
151
+ - x-region: us-east-1
152
+ ```
153
+
154
+ 3. **Access in Code**
155
+
156
+ ```typescript
157
+ export const readFromS3 = http(
158
+ 'read-s3',
159
+ {
160
+ connection: 'aws_s3',
161
+ },
162
+ async ctx => {
163
+ const s3Client = new S3Client({
164
+ credentials: {
165
+ accessKeyId: ctx.activation?.connection?.headers?.['x-api-key'],
166
+ secretAccessKey: ctx.activation?.connection?.headers?.['x-secret-key'],
167
+ },
168
+ region: ctx.activation?.connection?.headers?.['x-region'],
169
+ });
170
+
171
+ // Use S3 client...
172
+ }
173
+ );
174
+ ```
175
+
176
+ ### Third-Party API Key Example
177
+
178
+ ```typescript
179
+ export const callThirdParty = http(
180
+ 'third-party-api',
181
+ {
182
+ connection: 'third_party_service',
183
+ },
184
+ async ctx => {
185
+ // API key is automatically included in headers
186
+ const response = await ctx.fetch('https://api.thirdparty.com/data', {
187
+ method: 'GET',
188
+ // Headers from connection are automatically included
189
+ });
190
+
191
+ const data = await response.json();
192
+ return data;
193
+ }
194
+ );
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Multi-Connection Scenarios
200
+
201
+ Many integrations require multiple connections (e.g., Fluent + S3).
202
+
203
+ ### Pattern 1: Primary Connection + SDK Client
204
+
205
+ ```typescript
206
+ import { http } from '@versori/run';
207
+ import { createClient, S3DataSource } from '@fluentcommerce/fc-connect-sdk';
208
+
209
+ /**
210
+ * Fetch from S3, send to Fluent
211
+ *
212
+ * Uses: fluent_commerce (primary connection) + S3 credentials from env vars
213
+ */
214
+ export const s3ToFluent = http(
215
+ 's3-to-fluent',
216
+ {
217
+ connection: 'fluent_commerce', // Primary connection
218
+ },
219
+ async ctx => {
220
+ // Fluent client from primary connection
221
+ const client = await createClient(ctx);
222
+
223
+ // S3 client from environment variables
224
+ const s3 = new S3DataSource({
225
+ region: ctx.vars?.AWS_REGION || 'us-east-1',
226
+ credentials: {
227
+ accessKeyId: ctx.vars?.AWS_ACCESS_KEY_ID,
228
+ secretAccessKey: ctx.vars?.AWS_SECRET_ACCESS_KEY,
229
+ },
230
+ });
231
+
232
+ // Fetch from S3
233
+ const csvData = await s3.readFile('inventory-bucket', 'inventory.csv');
234
+
235
+ // Parse and send to Fluent
236
+ const records = parseCSV(csvData);
237
+ const job = await client.createJob({ name: 'S3 Import' });
238
+ await client.sendBatch(job.id, {
239
+ action: 'UPSERT',
240
+ entityType: 'INVENTORY',
241
+ entities: records,
242
+ });
243
+
244
+ return { success: true, recordCount: records.length };
245
+ }
246
+ );
247
+ ```
248
+
249
+ ### Pattern 2: Multiple Connections via ctx.connections
250
+
251
+ ```typescript
252
+ export const multiConnection = http(
253
+ 'multi-connection',
254
+ {
255
+ connection: 'fluent_commerce',
256
+ },
257
+ async ctx => {
258
+ // Primary connection (Fluent)
259
+ const fluentClient = await createClient(ctx);
260
+
261
+ // Access other connections
262
+ const s3Connection = ctx.connections?.aws_s3;
263
+ const sfccConnection = ctx.connections?.sfcc_api;
264
+
265
+ // Use multiple services
266
+ const fluentData = await fluentClient.graphql({ query: '...' });
267
+ const s3Data = await fetchFromS3WithConnection(s3Connection);
268
+ const sfccData = await fetchFromSFCCWithConnection(sfccConnection);
269
+
270
+ return {
271
+ fluent: fluentData,
272
+ s3: s3Data,
273
+ sfcc: sfccData,
274
+ };
275
+ }
276
+ );
277
+ ```
278
+
279
+ ---
280
+
281
+ ## Connection Validation
282
+
283
+ ### Pre-Deployment Validation
284
+
285
+ Before deploying, validate all connections:
286
+
287
+ ```typescript
288
+ import { fn } from '@versori/run';
289
+
290
+ /**
291
+ * Validate all required connections
292
+ *
293
+ * Run manually before deployment
294
+ */
295
+ export const validateConnections = fn('validate-connections', async ctx => {
296
+ const requiredConnections = ['fluent_commerce', 'aws_s3', 'sfcc_api'];
297
+
298
+ const results = {};
299
+
300
+ for (const connName of requiredConnections) {
301
+ const conn = ctx.connections?.[connName];
302
+
303
+ if (!conn) {
304
+ results[connName] = {
305
+ status: 'missing',
306
+ error: 'Connection not configured',
307
+ };
308
+ continue;
309
+ }
310
+
311
+ // Basic validation
312
+ results[connName] = {
313
+ status: 'configured',
314
+ hasUrl: !!conn.url,
315
+ hasHeaders: !!conn.headers,
316
+ hasParams: !!conn.params,
317
+ };
318
+ }
319
+
320
+ ctx.log('info', 'Connection validation complete', results);
321
+
322
+ return results;
323
+ });
324
+ ```
325
+
326
+ ### Runtime Connection Testing
327
+
328
+ ```typescript
329
+ import { http } from '@versori/run';
330
+ import { createClient } from '@fluentcommerce/fc-connect-sdk';
331
+
332
+ /**
333
+ * Test Fluent Commerce connection
334
+ *
335
+ * GET https://{workspace}.versori.run/test-connection
336
+ */
337
+ export const testConnection = http(
338
+ 'test-connection',
339
+ {
340
+ connection: 'fluent_commerce',
341
+ },
342
+ async ctx => {
343
+ try {
344
+ const client = await createClient(ctx);
345
+
346
+ // Simple query to test connection
347
+ const result = await client.graphql({
348
+ query: `query { __typename }`,
349
+ });
350
+
351
+ if (result.errors?.length) {
352
+ return {
353
+ success: false,
354
+ error: 'GraphQL error',
355
+ details: result.errors[0].message,
356
+ };
357
+ }
358
+
359
+ ctx.log('info', 'Connection test successful');
360
+
361
+ return {
362
+ success: true,
363
+ message: 'Connection working',
364
+ timestamp: new Date().toISOString(),
365
+ };
366
+ } catch (error) {
367
+ ctx.log('error', 'Connection test failed', {
368
+ error: error instanceof Error ? error.message : String(error),
369
+ });
370
+
371
+ return {
372
+ success: false,
373
+ error: error instanceof Error ? error.message : 'Connection failed',
374
+ };
375
+ }
376
+ }
377
+ );
378
+ ```
379
+
380
+ ---
381
+
382
+ ## Security Best Practices
383
+
384
+ ### 1. Never Hardcode Credentials
385
+
386
+ ```typescript
387
+ // ❌ WRONG - Hardcoded credentials
388
+ export const bad = http(
389
+ 'bad',
390
+ {
391
+ connection: 'fluent',
392
+ },
393
+ async ctx => {
394
+ const clientId = 'my-client-id'; // NEVER do this!
395
+ const clientSecret = 'my-secret'; // NEVER do this!
396
+ }
397
+ );
398
+
399
+ // ✅ CORRECT - Use connection or environment variables
400
+ export const good = http(
401
+ 'good',
402
+ {
403
+ connection: 'fluent_commerce',
404
+ },
405
+ async ctx => {
406
+ const client = await createClient(ctx); // Credentials from connection
407
+ }
408
+ );
409
+ ```
410
+
411
+ ### 2. Use Connector Variables for Secrets
412
+
413
+ Configure sensitive values in Versori UI:
414
+
415
+ **Versori Dashboard → Connector → Variables**:
416
+
417
+ ```
418
+ Name: FLUENT_WEBHOOK_PUBLIC_KEY
419
+ Value: -----BEGIN PUBLIC KEY-----...
420
+ Type: Secret
421
+ ```
422
+
423
+ **Access in code**:
424
+
425
+ ```typescript
426
+ export const useSecrets = webhook('use-secrets', async ctx => {
427
+ // Access secret variable
428
+ const publicKey = ctx.vars?.FLUENT_WEBHOOK_PUBLIC_KEY;
429
+
430
+ if (!publicKey) {
431
+ return { error: 'Missing public key configuration' };
432
+ }
433
+
434
+ // Use securely
435
+ const validator = new WebhookValidationService({ publicKey });
436
+ // ...
437
+ });
438
+ ```
439
+
440
+ ### 3. Environment-Specific Connections
441
+
442
+ Maintain separate connections for each environment:
443
+
444
+ ```
445
+ Development:
446
+ - fluent_commerce_dev
447
+ - aws_s3_dev
448
+
449
+ Staging:
450
+ - fluent_commerce_staging
451
+ - aws_s3_staging
452
+
453
+ Production:
454
+ - fluent_commerce_prod
455
+ - aws_s3_prod
456
+ ```
457
+
458
+ **Code pattern**:
459
+
460
+ ```typescript
461
+ export const envAwareWorkflow = http(
462
+ 'env-aware',
463
+ {
464
+ connection:
465
+ process.env.NODE_ENV === 'production' ? 'fluent_commerce_prod' : 'fluent_commerce_dev',
466
+ },
467
+ async ctx => {
468
+ const client = await createClient(ctx);
469
+ // ...
470
+ }
471
+ );
472
+ ```
473
+
474
+ ### 4. Rotate Credentials Regularly
475
+
476
+ - **OAuth2 Client Secrets**: Rotate every 90 days
477
+ - **API Keys**: Rotate every 180 days
478
+ - **Webhook Public Keys**: Rotate on security events
479
+
480
+ **Update process**:
481
+
482
+ 1. Generate new credentials in source system
483
+ 2. Update connection in Versori UI
484
+ 3. Test connection
485
+ 4. Deactivate old credentials after confirmation
486
+
487
+ ### 5. Audit Connection Access
488
+
489
+ ```typescript
490
+ export const auditedWorkflow = http(
491
+ 'audited',
492
+ {
493
+ connection: 'fluent_commerce',
494
+ },
495
+ async ctx => {
496
+ // Log connection usage
497
+ ctx.log('info', 'Connection accessed', {
498
+ workflow: 'audited',
499
+ connection: 'fluent_commerce',
500
+ timestamp: Date.now(),
501
+ executionId: ctx.executionId,
502
+ user: ctx.activation?.user || 'system',
503
+ });
504
+
505
+ const client = await createClient(ctx);
506
+ // ... rest of workflow
507
+ }
508
+ );
509
+ ```
510
+
511
+ ---
512
+
513
+ ## Accessing All Connections (v0.4.x+)
514
+
515
+ ### NEW: activation.connections Array
516
+
517
+ As of @versori/run v0.4.x, you can access **all configured connections** for the current activation via `ctx.activation.connections`.
518
+
519
+ #### Connection Structure
520
+
521
+ ```typescript
522
+ type Connection = {
523
+ id: string; // Unique connection ID
524
+ name: string; // Connection name (matches UI)
525
+ templateId: string; // Connection template/type ID
526
+ dynamic: boolean; // Whether connection is dynamic
527
+ baseUrl: string; // Base URL for the connection
528
+ createdAt: string; // ISO timestamp
529
+ updatedAt: string; // ISO timestamp
530
+ credentials: ConnectionCredential[]; // Credential details
531
+ }
532
+ ```
533
+
534
+ #### Listing All Available Connections
535
+
536
+ ```typescript
537
+ import { fn } from '@versori/run';
538
+
539
+ /**
540
+ * List all connections for current activation
541
+ */
542
+ export const listConnections = fn('list-connections', ctx => {
543
+ const connections = ctx.activation.connections;
544
+
545
+ if (!connections || connections.length === 0) {
546
+ return { message: 'No connections configured', count: 0 };
547
+ }
548
+
549
+ ctx.log.info('Available connections', {
550
+ count: connections.length,
551
+ names: connections.map(c => c.name)
552
+ });
553
+
554
+ return {
555
+ count: connections.length,
556
+ connections: connections.map(c => ({
557
+ name: c.name,
558
+ id: c.id,
559
+ baseUrl: c.baseUrl,
560
+ dynamic: c.dynamic,
561
+ createdAt: c.createdAt
562
+ }))
563
+ };
564
+ });
565
+ ```
566
+
567
+ #### Finding Specific Connection
568
+
569
+ ```typescript
570
+ import { fn } from '@versori/run';
571
+
572
+ /**
573
+ * Check if Fluent Commerce connection exists
574
+ */
575
+ export const checkFluentConnection = fn('check-fluent-connection', ctx => {
576
+ const connections = ctx.activation.connections;
577
+ const fluentConn = connections?.find(c => c.name === 'fluent_commerce');
578
+
579
+ if (!fluentConn) {
580
+ throw new Error('Fluent Commerce connection not configured');
581
+ }
582
+
583
+ ctx.log.info('Fluent connection found', {
584
+ id: fluentConn.id,
585
+ baseUrl: fluentConn.baseUrl,
586
+ dynamic: fluentConn.dynamic
587
+ });
588
+
589
+ return {
590
+ found: true,
591
+ connectionId: fluentConn.id,
592
+ baseUrl: fluentConn.baseUrl
593
+ };
594
+ });
595
+ ```
596
+
597
+ ### Multi-Tenant Pattern with activation.connections
598
+
599
+ **Use Case**: One connector serves multiple customers, each with their own Fluent instance.
600
+
601
+ ```typescript
602
+ import { webhook, fn, http } from '@versori/run';
603
+ import { createClient } from '@fluentcommerce/fc-connect-sdk';
604
+
605
+ /**
606
+ * Multi-tenant order creation
607
+ *
608
+ * POST https://{workspace}.versori.run/create-order
609
+ * Body: { customerId: "customer-a", orderData: {...} }
610
+ */
611
+ export const multiTenantOrderCreate = webhook('multi-tenant-order-create', {
612
+ response: { mode: 'sync' },
613
+ })
614
+ // Step 1: Route to correct Fluent connection (fn)
615
+ .then(fn('route-connection', ctx => {
616
+ const { customerId, orderData } = ctx.data;
617
+
618
+ if (!customerId) {
619
+ throw new Error('customerId is required');
620
+ }
621
+
622
+ // Access all connections
623
+ const connections = ctx.activation.connections;
624
+
625
+ if (!connections || connections.length === 0) {
626
+ throw new Error('No connections configured for this activation');
627
+ }
628
+
629
+ // Find customer-specific connection
630
+ // Convention: connections named fluent_customer-a, fluent_customer-b, etc.
631
+ const connectionName = `fluent_${customerId.toLowerCase()}`;
632
+ const connection = connections.find(c => c.name === connectionName);
633
+
634
+ if (!connection) {
635
+ throw new Error(`No Fluent connection found for customer: ${customerId}`);
636
+ }
637
+
638
+ ctx.log.info('Routed to customer connection', {
639
+ customerId,
640
+ connectionName: connection.name,
641
+ connectionId: connection.id,
642
+ baseUrl: connection.baseUrl
643
+ });
644
+
645
+ return {
646
+ connectionName: connection.name,
647
+ customerId,
648
+ orderData
649
+ };
650
+ }))
651
+
652
+ // Step 2: Create order in customer's Fluent instance (http)
653
+ .then(http('create-order', (ctx) => {
654
+ // Return dynamic connection based on routing
655
+ return { connection: ctx.data.connectionName };
656
+ }, async ctx => {
657
+ const { customerId, orderData } = ctx.data;
658
+
659
+ // Create client with customer-specific connection
660
+ const client = await createClient(ctx);
661
+
662
+ // Create order
663
+ const result = await client.graphql({
664
+ query: `
665
+ mutation CreateOrder($input: CreateOrderInput!) {
666
+ createOrder(input: $input) {
667
+ id
668
+ ref
669
+ status
670
+ }
671
+ }
672
+ `,
673
+ variables: { input: orderData }
674
+ });
675
+
676
+ if (result.errors?.length) {
677
+ throw new Error(`Order creation failed: ${result.errors[0].message}`);
678
+ }
679
+
680
+ ctx.log.info('Order created', {
681
+ customerId,
682
+ orderId: result.data.createOrder.id
683
+ });
684
+
685
+ return {
686
+ success: true,
687
+ customerId,
688
+ orderId: result.data.createOrder.id,
689
+ orderRef: result.data.createOrder.ref
690
+ };
691
+ }))
692
+
693
+ .catch(({ data }) => ({
694
+ success: false,
695
+ error: data instanceof Error ? data.message : String(data),
696
+ status: 500
697
+ }));
698
+ ```
699
+
700
+ ### Iterating Through Multiple Connections
701
+
702
+ **Use Case**: Health check across all Fluent connections.
703
+
704
+ ```typescript
705
+ import { fn, http } from '@versori/run';
706
+ import { createClient } from '@fluentcommerce/fc-connect-sdk';
707
+
708
+ /**
709
+ * Test all Fluent connections
710
+ *
711
+ * GET https://{workspace}.versori.run/test-all-connections
712
+ */
713
+ export const testAllConnections = fn('test-all-fluent', async ctx => {
714
+ const connections = ctx.activation.connections;
715
+
716
+ // Filter to only Fluent connections (by name convention)
717
+ const fluentConnections = connections?.filter(c =>
718
+ c.name.startsWith('fluent_')
719
+ ) || [];
720
+
721
+ if (fluentConnections.length === 0) {
722
+ return { message: 'No Fluent connections found', count: 0 };
723
+ }
724
+
725
+ ctx.log.info('Testing Fluent connections', {
726
+ count: fluentConnections.length
727
+ });
728
+
729
+ const results = [];
730
+
731
+ // Test each connection
732
+ for (const conn of fluentConnections) {
733
+ try {
734
+ // Note: To actually test, we'd need to use http() with the connection
735
+ // This example shows discovery only
736
+ results.push({
737
+ name: conn.name,
738
+ id: conn.id,
739
+ baseUrl: conn.baseUrl,
740
+ status: 'configured',
741
+ available: true
742
+ });
743
+ } catch (error) {
744
+ results.push({
745
+ name: conn.name,
746
+ id: conn.id,
747
+ status: 'error',
748
+ available: false,
749
+ error: error instanceof Error ? error.message : String(error)
750
+ });
751
+ }
752
+ }
753
+
754
+ return {
755
+ totalConnections: fluentConnections.length,
756
+ results
757
+ };
758
+ });
759
+ ```
760
+
761
+ ### Validation Pattern: Required Connections
762
+
763
+ ```typescript
764
+ import { fn } from '@versori/run';
765
+
766
+ /**
767
+ * Validate required connections exist
768
+ *
769
+ * Recommended to run at connector startup
770
+ */
771
+ export const validateRequiredConnections = fn('validate-required', ctx => {
772
+ const required = ['fluent_commerce', 'aws_s3', 'sftp_warehouse'];
773
+ const connections = ctx.activation.connections || [];
774
+ const connectionNames = new Set(connections.map(c => c.name));
775
+
776
+ const missing = required.filter(name => !connectionNames.has(name));
777
+
778
+ if (missing.length > 0) {
779
+ throw new Error(`Missing required connections: ${missing.join(', ')}`);
780
+ }
781
+
782
+ ctx.log.info('All required connections configured', {
783
+ required: required.length,
784
+ configured: connections.length
785
+ });
786
+
787
+ return {
788
+ valid: true,
789
+ requiredConnections: required,
790
+ totalConnections: connections.length
791
+ };
792
+ });
793
+ ```
794
+
795
+ ---
796
+
797
+ ## Activation Environment & Dynamic Variables (v0.4.x+)
798
+
799
+ ### activation.environment
800
+
801
+ Access the current activation's environment information:
802
+
803
+ ```typescript
804
+ import { fn } from '@versori/run';
805
+
806
+ /**
807
+ * Check environment and apply environment-specific logic
808
+ */
809
+ export const envAwareWorkflow = fn('env-aware', ctx => {
810
+ const env = ctx.activation.environment;
811
+
812
+ if (!env) {
813
+ ctx.log.warn('No environment information available');
814
+ return { environment: 'unknown' };
815
+ }
816
+
817
+ ctx.log.info('Environment details', {
818
+ id: env.id,
819
+ name: env.name,
820
+ type: env.type // e.g., 'development', 'staging', 'production'
821
+ });
822
+
823
+ // Conditional logic based on environment
824
+ if (env.name === 'production') {
825
+ // Use production-specific settings
826
+ return {
827
+ environment: 'production',
828
+ batchSize: 1000,
829
+ retryAttempts: 5,
830
+ timeout: 60000
831
+ };
832
+ } else if (env.name === 'staging') {
833
+ return {
834
+ environment: 'staging',
835
+ batchSize: 100,
836
+ retryAttempts: 3,
837
+ timeout: 30000
838
+ };
839
+ } else {
840
+ return {
841
+ environment: 'development',
842
+ batchSize: 10,
843
+ retryAttempts: 1,
844
+ timeout: 10000
845
+ };
846
+ }
847
+ });
848
+ ```
849
+
850
+ ### activation.dynamicVariables
851
+
852
+ Access dynamic variables set at the activation level:
853
+
854
+ ```typescript
855
+ import { fn } from '@versori/run';
856
+
857
+ /**
858
+ * Access activation-level dynamic variables
859
+ */
860
+ export const useDynamicVars = fn('use-dynamic-vars', ctx => {
861
+ // Get variables using getVariable
862
+ const apiKey = ctx.activation.getVariable<string>('API_KEY');
863
+ const retailerId = ctx.activation.getVariable<number>('RETAILER_ID');
864
+ const region = ctx.activation.getVariable<string>('AWS_REGION');
865
+
866
+ ctx.log.info('Dynamic variables', {
867
+ hasApiKey: !!apiKey,
868
+ retailerId,
869
+ region
870
+ });
871
+
872
+ // Use variables in your workflow
873
+ return {
874
+ retailerId,
875
+ region,
876
+ configured: !!apiKey && !!retailerId
877
+ };
878
+ });
879
+ ```
880
+
881
+ ### Setting Variables Programmatically
882
+
883
+ ```typescript
884
+ import { http } from '@versori/run';
885
+ import { createClient } from '@fluentcommerce/fc-connect-sdk';
886
+
887
+ /**
888
+ * Cache frequently-used data in activation variables
889
+ */
890
+ export const cacheRetailerConfig = http(
891
+ 'cache-retailer-config',
892
+ { connection: 'fluent_commerce' },
893
+ async ctx => {
894
+ const client = await createClient(ctx);
895
+
896
+ // Query Fluent for retailer configuration
897
+ const result = await client.graphql({
898
+ query: `
899
+ query GetRetailer($id: Int!) {
900
+ retailer(id: $id) {
901
+ id
902
+ name
903
+ tradingName
904
+ supportEmail
905
+ primaryLocation {
906
+ ref
907
+ }
908
+ }
909
+ }
910
+ `,
911
+ variables: { id: 1 }
912
+ });
913
+
914
+ const retailer = result.data.retailer;
915
+
916
+ // Cache in activation variables for future workflows
917
+ await ctx.activation.setVariable('CACHED_RETAILER_ID', retailer.id);
918
+ await ctx.activation.setVariable('CACHED_RETAILER_NAME', retailer.name);
919
+ await ctx.activation.setVariable('CACHED_PRIMARY_LOCATION', retailer.primaryLocation.ref);
920
+ await ctx.activation.setVariable('LAST_CONFIG_REFRESH', Date.now());
921
+
922
+ ctx.log.info('Retailer config cached', {
923
+ retailerId: retailer.id,
924
+ retailerName: retailer.name
925
+ });
926
+
927
+ return {
928
+ cached: true,
929
+ retailer: {
930
+ id: retailer.id,
931
+ name: retailer.name
932
+ }
933
+ };
934
+ }
935
+ );
936
+ ```
937
+
938
+ ### Complete ActivationImpl Reference
939
+
940
+ ```typescript
941
+ interface ActivationImpl {
942
+ // Properties
943
+ get id(): string; // Activation ID
944
+ get user(): EndUser; // User info
945
+ get environment(): ProjectEnvironment | undefined; // ✅ NEW in v0.4.x
946
+ get connections(): Array<Connection> | undefined; // ✅ NEW in v0.4.x
947
+ get dynamicVariables(): DynamicVariables | undefined; // ✅ NEW in v0.4.x
948
+
949
+ // Methods
950
+ getVariable<T = unknown>(name: string): T | undefined;
951
+ setVariable(name: string, value: unknown): Promise<void>;
952
+ }
953
+ ```
954
+
955
+ ---
956
+
957
+ ## Troubleshooting Connection Issues
958
+
959
+ ### Common Issues & Solutions
960
+
961
+ | Issue | Symptoms | Solution |
962
+ | ------------------------ | ------------------------------------ | ---------------------------------------------------------- |
963
+ | **Connection not found** | `Error: Connection 'xyz' not found` | Verify connection name matches UI exactly (case-sensitive) |
964
+ | **Token expired** | `401 Unauthorized` | Versori should auto-refresh; check token URL configuration |
965
+ | **Invalid credentials** | `403 Forbidden` | Verify Client ID/Secret in Fluent dashboard |
966
+ | **Missing retailerId** | `retailerId is required for job creation` | Use `client.setRetailerId('1')` or pass in method call. See [retailerId Configuration Guide](../../../../00-START-HERE/retailerid-configuration.md) |
967
+ | **CORS errors** | `CORS policy blocked` | Enable CORS in webhook configuration |
968
+ | **Rate limiting** | `429 Too Many Requests` | Implement retry with backoff, check Fluent API limits |
969
+
970
+ ### Debug Connection Configuration
971
+
972
+ ```typescript
973
+ export const debugConnection = http(
974
+ 'debug-connection',
975
+ {
976
+ connection: 'fluent_commerce',
977
+ },
978
+ async ctx => {
979
+ const conn = ctx.activation?.connection;
980
+
981
+ // Log all connection details (except secrets)
982
+ ctx.log('debug', 'Connection configuration', {
983
+ hasConnection: !!conn,
984
+ url: conn?.url,
985
+ headerKeys: conn?.headers ? Object.keys(conn.headers) : [],
986
+ paramKeys: conn?.params ? Object.keys(conn.params) : [],
987
+ retailerId: conn?.params?.retailerId,
988
+ });
989
+
990
+ // Test basic connectivity
991
+ try {
992
+ const response = await ctx.fetch(conn?.url || 'https://api.fluentcommerce.com', {
993
+ method: 'HEAD',
994
+ });
995
+
996
+ return {
997
+ connectionStatus: 'reachable',
998
+ statusCode: response.status,
999
+ headers: Object.fromEntries(response.headers.entries()),
1000
+ };
1001
+ } catch (error) {
1002
+ return {
1003
+ connectionStatus: 'unreachable',
1004
+ error: error instanceof Error ? error.message : String(error),
1005
+ };
1006
+ }
1007
+ }
1008
+ );
1009
+ ```
1010
+
1011
+ ### Validate OAuth2 Token
1012
+
1013
+ ```typescript
1014
+ export const validateToken = http(
1015
+ 'validate-token',
1016
+ {
1017
+ connection: 'fluent_commerce',
1018
+ },
1019
+ async ctx => {
1020
+ const conn = ctx.activation?.connection;
1021
+
1022
+ // Extract token from headers (Versori auto-includes)
1023
+ const authHeader = conn?.headers?.['Authorization'];
1024
+
1025
+ if (!authHeader) {
1026
+ return { error: 'No authorization header found' };
1027
+ }
1028
+
1029
+ // Parse token (Bearer <token>)
1030
+ const token = authHeader.replace('Bearer ', '');
1031
+
1032
+ // Decode JWT (if applicable)
1033
+ try {
1034
+ const parts = token.split('.');
1035
+ if (parts.length === 3) {
1036
+ const payload = JSON.parse(atob(parts[1]));
1037
+
1038
+ return {
1039
+ tokenValid: true,
1040
+ expiresAt: payload.exp ? new Date(payload.exp * 1000).toISOString() : 'unknown',
1041
+ issuedAt: payload.iat ? new Date(payload.iat * 1000).toISOString() : 'unknown',
1042
+ scopes: payload.scope || [],
1043
+ };
1044
+ }
1045
+ } catch (error) {
1046
+ return {
1047
+ tokenValid: false,
1048
+ error: 'Invalid JWT format',
1049
+ };
1050
+ }
1051
+
1052
+ return { tokenValid: true, tokenLength: token.length };
1053
+ }
1054
+ );
1055
+ ```
1056
+
1057
+ ---
1058
+
1059
+ ## Advanced Connection Patterns
1060
+
1061
+ ### Pattern 1: Connection Fallback
1062
+
1063
+ ```typescript
1064
+ export const withFallback = http(
1065
+ 'connection-fallback',
1066
+ {
1067
+ connection: 'fluent_commerce_primary',
1068
+ },
1069
+ async ctx => {
1070
+ try {
1071
+ // Try primary connection
1072
+ const client = await createClient(ctx);
1073
+ return await client.graphql({ query: '...' });
1074
+ } catch (primaryError) {
1075
+ ctx.log('warn', 'Primary connection failed, trying fallback');
1076
+
1077
+ try {
1078
+ // Fallback to secondary connection
1079
+ const fallbackClient = await createClient({
1080
+ connection: ctx.connections?.fluent_commerce_secondary,
1081
+ log: ctx.log,
1082
+ });
1083
+
1084
+ return await fallbackClient.graphql({ query: '...' });
1085
+ } catch (fallbackError) {
1086
+ throw new Error('All connections failed');
1087
+ }
1088
+ }
1089
+ }
1090
+ );
1091
+ ```
1092
+
1093
+ ### Pattern 2: Dynamic Connection Selection
1094
+
1095
+ ```typescript
1096
+ export const dynamicConnection = http('dynamic-connection', async ctx => {
1097
+ // Select connection based on request parameter
1098
+ const environment = ctx.query?.env || 'production';
1099
+
1100
+ const connectionName =
1101
+ environment === 'staging' ? 'fluent_commerce_staging' : 'fluent_commerce_prod';
1102
+
1103
+ ctx.log('info', 'Selected connection', { connectionName, environment });
1104
+
1105
+ // Note: This pattern requires accessing ctx.connections
1106
+ const client = await createClient({
1107
+ connection: ctx.connections?.[connectionName],
1108
+ log: ctx.log,
1109
+ });
1110
+
1111
+ return await client.graphql({ query: '...' });
1112
+ });
1113
+ ```
1114
+
1115
+ ---
1116
+
1117
+ ## Key Takeaways
1118
+
1119
+ - 🎯 **OAuth2 connections** are managed by Versori - automatic token refresh
1120
+ - 🎯 **Connection name** in code must match UI exactly (case-sensitive)
1121
+ - 🎯 **Never hardcode** credentials - use connections or environment variables
1122
+ - 🎯 **Multi-connection scenarios** use primary connection + ctx.connections
1123
+ - 🎯 **Validate connections** before deployment with test workflows
1124
+ - 🎯 **Security best practices**: rotate credentials, use secrets, audit access
1125
+ - 🎯 **Troubleshooting**: check name match, token expiration, credential validity
1126
+
1127
+ ---
1128
+
1129
+ ## Practice Exercise
1130
+
1131
+ Create a workflow that:
1132
+
1133
+ 1. Uses OAuth2 connection to Fluent Commerce
1134
+ 2. Validates connection on startup
1135
+ 3. Falls back to secondary connection on failure
1136
+ 4. Logs all connection attempts for audit
1137
+ 5. Returns connection health status
1138
+
1139
+ **Hints**:
1140
+
1141
+ - Use `http()` with primary connection
1142
+ - Implement try/catch for fallback
1143
+ - Use `ctx.log()` for audit trail
1144
+ - Test token validity before GraphQL calls
1145
+
1146
+ **Solution** available in [Module 8: Best Practices](./platforms-versori-08-best-practices.md#practice-solutions)
1147
+
1148
+ ---
1149
+
1150
+ ## Next Steps
1151
+
1152
+ Now that you understand connection management, let's explore state management with KV storage.
1153
+
1154
+ Continue to [Module 6: KV Storage →](./platforms-versori-06-kv-storage.md) to learn about distributed state, file tracking, and caching patterns.
1155
+
1156
+ ---
1157
+
1158
+ ## Related Documentation
1159
+
1160
+ - [Module 3: Authentication](./platforms-versori-03-authentication.md) - OAuth2 basics
1161
+ - [Module 4: Workflows](./platforms-versori-04-workflows.md) - Using connections in workflows
1162
+ - [Module 6: KV Storage](./platforms-versori-06-kv-storage.md) - State management
1163
+ - [Module 8: Best Practices](./platforms-versori-08-best-practices.md) - Security hardening
1164
+
1165
+ ---
1166
+
1167
+ [← Previous: Module 4](./platforms-versori-04-workflows.md) | [Back to Guide](../platforms-versori-readme.md) | [Next: Module 6: KV Storage →](./platforms-versori-06-kv-storage.md)