@fluentcommerce/fc-connect-sdk 0.1.53 → 0.1.55

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