@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.
- package/CHANGELOG.md +30 -2
- package/README.md +39 -0
- package/dist/cjs/auth/index.d.ts +3 -0
- package/dist/cjs/auth/index.js +13 -0
- package/dist/cjs/auth/profile-loader.d.ts +18 -0
- package/dist/cjs/auth/profile-loader.js +208 -0
- package/dist/cjs/client-factory.d.ts +4 -0
- package/dist/cjs/client-factory.js +10 -0
- package/dist/cjs/clients/fluent-client.js +13 -6
- package/dist/cjs/index.d.ts +3 -1
- package/dist/cjs/index.js +8 -2
- package/dist/cjs/utils/pagination-helpers.js +38 -2
- package/dist/cjs/versori/fluent-versori-client.js +11 -5
- package/dist/esm/auth/index.d.ts +3 -0
- package/dist/esm/auth/index.js +2 -0
- package/dist/esm/auth/profile-loader.d.ts +18 -0
- package/dist/esm/auth/profile-loader.js +169 -0
- package/dist/esm/client-factory.d.ts +4 -0
- package/dist/esm/client-factory.js +9 -0
- package/dist/esm/clients/fluent-client.js +13 -6
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/utils/pagination-helpers.js +38 -2
- package/dist/esm/versori/fluent-versori-client.js +11 -5
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/tsconfig.types.tsbuildinfo +1 -1
- package/dist/types/auth/index.d.ts +3 -0
- package/dist/types/auth/profile-loader.d.ts +18 -0
- package/dist/types/client-factory.d.ts +4 -0
- package/dist/types/index.d.ts +3 -1
- package/docs/00-START-HERE/EXPORT-VALIDATION.md +158 -158
- package/docs/00-START-HERE/cli-analyze-source-structure-guide.md +655 -655
- package/docs/00-START-HERE/cli-documentation-index.md +202 -202
- package/docs/00-START-HERE/cli-quick-reference.md +252 -252
- package/docs/00-START-HERE/decision-tree.md +552 -552
- package/docs/00-START-HERE/getting-started.md +1070 -1070
- package/docs/00-START-HERE/mapper-quick-decision-guide.md +235 -235
- package/docs/00-START-HERE/readme.md +237 -237
- package/docs/00-START-HERE/retailerid-configuration.md +404 -404
- package/docs/00-START-HERE/sdk-philosophy.md +794 -794
- package/docs/00-START-HERE/troubleshooting-quick-reference.md +1086 -1086
- package/docs/01-TEMPLATES/faq.md +686 -686
- package/docs/01-TEMPLATES/patterns/pattern-templates-guide.md +68 -68
- package/docs/01-TEMPLATES/patterns/patterns-csv-schema-validation-and-rejection-report.md +233 -233
- package/docs/01-TEMPLATES/patterns/patterns-custom-resolvers.md +407 -407
- package/docs/01-TEMPLATES/patterns/patterns-error-handling-retry.md +511 -511
- package/docs/01-TEMPLATES/patterns/patterns-field-mapping-universal.md +701 -701
- package/docs/01-TEMPLATES/patterns/patterns-large-file-splitting.md +1430 -1430
- package/docs/01-TEMPLATES/patterns/patterns-master-data-etl.md +2399 -2399
- package/docs/01-TEMPLATES/patterns/patterns-pagination-streaming.md +447 -447
- package/docs/01-TEMPLATES/patterns/patterns-state-duplicate-prevention.md +385 -385
- package/docs/01-TEMPLATES/readme.md +957 -957
- package/docs/01-TEMPLATES/standalone/standalone-asn-inbound-processing.md +1209 -1209
- package/docs/01-TEMPLATES/standalone/standalone-graphql-query-export.md +1140 -1140
- package/docs/01-TEMPLATES/standalone/standalone-graphql-to-parquet-partitioned-s3.md +432 -432
- package/docs/01-TEMPLATES/standalone/standalone-multi-channel-inventory-sync.md +1185 -1185
- package/docs/01-TEMPLATES/standalone/standalone-multi-source-aggregation.md +1462 -1462
- package/docs/01-TEMPLATES/standalone/standalone-s3-csv-batch-api.md +1390 -1390
- package/docs/01-TEMPLATES/standalone/standalone-s3-csv-inventory-to-batch.md +330 -330
- package/docs/01-TEMPLATES/standalone/standalone-scripts-guide.md +87 -87
- package/docs/01-TEMPLATES/standalone/standalone-sftp-xml-graphql.md +1444 -1444
- package/docs/01-TEMPLATES/standalone/standalone-webhook-payload-processing.md +688 -688
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-dropship-order-routing.md +193 -193
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-graphql-parquet-extraction.md +518 -518
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-inter-location-transfers.md +2162 -2162
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-pre-order-allocation.md +2226 -2226
- package/docs/01-TEMPLATES/versori/business-examples/business-scenarios-guide.md +87 -87
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-connection-validation-pattern.md +656 -656
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-dual-workflow-connector.md +835 -835
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-guide.md +108 -108
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-kv-state-management.md +1533 -1533
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-xml-response-patterns.md +1160 -1160
- package/docs/01-TEMPLATES/versori/versori-platform-guide.md +201 -201
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-asn-purchase-order.md +1906 -1906
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-dropship-routing.md +1074 -1074
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-flash-sale-reserve.md +1395 -1395
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-generic-xml-order.md +888 -888
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-payment-gateway-integration.md +2478 -2478
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-rma-returns-comprehensive.md +2240 -2240
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-xml-order-ingestion.md +2029 -2029
- package/docs/01-TEMPLATES/versori/webhooks/webhook-templates-guide.md +140 -140
- package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/inventory-mapping.json +20 -20
- package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/products_2025-01-22.csv +11 -11
- package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/sample-data-guide.md +34 -34
- package/docs/01-TEMPLATES/versori/workflows/_examples/workflow-examples-guide.md +36 -36
- package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-modes-guide.md +1038 -1038
- package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-workflows-guide.md +138 -138
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/graphql-extraction-guide.md +63 -63
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-csv.md +2062 -2062
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-xml.md +2294 -2294
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-s3-csv.md +2461 -2461
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-sftp-xml.md +2529 -2529
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-csv.md +2464 -2464
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-json.md +1959 -1959
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-s3-csv.md +1953 -1953
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-sftp-xml.md +2541 -2541
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-s3-json.md +2384 -2384
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-sftp-xml.md +2445 -2445
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-csv.md +2355 -2355
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-json.md +2042 -2042
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-sftp-xml.md +2726 -2726
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/batch-api-guide.md +206 -206
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-cycle-count-reconciliation.md +2030 -2030
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-multi-channel-inventory-sync.md +1882 -1882
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-csv-inventory-batch.md +2827 -2827
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-json-inventory-batch.md +1952 -1952
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-xml-inventory-batch.md +3289 -3289
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-csv-inventory-batch.md +3064 -3064
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-json-inventory-batch.md +3238 -3238
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-xml-inventory-batch.md +2977 -2977
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/event-api-guide.md +321 -321
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-json-order-cancel-event.md +959 -959
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-xml-order-cancel-event.md +1170 -1170
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-csv-product-event.md +2312 -2312
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-json-product-event.md +2999 -2999
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-parquet-product-event.md +2836 -2836
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-xml-product-event.md +2395 -2395
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-csv-product-event.md +2295 -2295
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-json-product-event.md +2602 -2602
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-parquet-product-event.md +2589 -2589
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-xml-product-event.md +3578 -3578
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/graphql-mutations-guide.md +93 -93
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-json-order-update-graphql.md +1260 -1260
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-xml-order-update-graphql.md +1472 -1472
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-control-graphql.md +2417 -2417
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-location-graphql.md +2811 -2811
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-price-graphql.md +2619 -2619
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-json-location-graphql.md +2807 -2807
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-xml-location-graphql.md +2373 -2373
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-control-graphql.md +2740 -2740
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-location-graphql.md +2760 -2760
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-json-location-graphql.md +1710 -1710
- package/docs/01-TEMPLATES/versori/workflows/ingestion/ingestion-workflows-guide.md +136 -136
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/rubix-webhooks-guide.md +520 -520
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-inline.md +1418 -1418
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-universal-mapper.md +1785 -1785
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-order-attribute-update.md +824 -824
- package/docs/01-TEMPLATES/versori/workflows/workflows-overview-guide.md +646 -646
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-batch-archival.md +724 -724
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-job-tracker.md +627 -627
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-partial-batch-recovery.md +561 -561
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-quick-reference.md +367 -367
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-readme.md +407 -407
- package/docs/02-CORE-GUIDES/advanced-services/readme.md +49 -49
- package/docs/02-CORE-GUIDES/api-reference/api-reference-quick-reference.md +548 -548
- package/docs/02-CORE-GUIDES/api-reference/event-api-input-output-reference.md +702 -1171
- package/docs/02-CORE-GUIDES/api-reference/examples/client-initialization.ts +286 -286
- package/docs/02-CORE-GUIDES/api-reference/graphql-error-classification.md +337 -337
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-01-client-api.md +399 -482
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-03-authentication.md +199 -199
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-04-graphql-mapping.md +925 -925
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-05-services.md +1198 -1198
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-06-data-sources.md +1083 -1083
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-07-parsers.md +1097 -1097
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-pagination.md +513 -513
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-types.md +545 -597
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-error-handling.md +527 -527
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-webhook-validation.md +514 -514
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-extraction.md +557 -557
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-utilities.md +412 -412
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-cli-tools.md +423 -423
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-error-handling.md +716 -716
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-analyze-source-structure.md +518 -518
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-partial-responses.md +212 -212
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-testing.md +300 -300
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-13-resolver-builder.md +322 -322
- package/docs/02-CORE-GUIDES/api-reference/readme.md +279 -279
- package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-quick-reference.md +351 -351
- package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-readme.md +277 -277
- package/docs/02-CORE-GUIDES/auto-pagination/examples/auto-pagination-readme.md +178 -178
- package/docs/02-CORE-GUIDES/auto-pagination/examples/common-patterns.ts +351 -351
- package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-products.ts +384 -384
- package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-virtual-positions.ts +308 -308
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-01-foundations.md +470 -470
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-02-quick-start.md +713 -713
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-03-configuration.md +754 -754
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-04-advanced-patterns.md +732 -732
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-05-sdk-integration.md +847 -847
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-06-troubleshooting.md +359 -359
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-07-api-reference.md +462 -462
- package/docs/02-CORE-GUIDES/auto-pagination/readme.md +54 -54
- package/docs/02-CORE-GUIDES/data-sources/data-sources-file-operations-error-handling.md +1487 -1487
- package/docs/02-CORE-GUIDES/data-sources/data-sources-quick-reference.md +836 -836
- package/docs/02-CORE-GUIDES/data-sources/data-sources-readme.md +276 -276
- package/docs/02-CORE-GUIDES/data-sources/data-sources-sftp-credential-access-security.md +553 -553
- package/docs/02-CORE-GUIDES/data-sources/examples/common-patterns.ts +409 -409
- package/docs/02-CORE-GUIDES/data-sources/examples/data-sources-readme.md +178 -178
- package/docs/02-CORE-GUIDES/data-sources/examples/s3-operations.ts +308 -308
- package/docs/02-CORE-GUIDES/data-sources/examples/sftp-operations.ts +371 -371
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-01-foundations.md +735 -735
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-02-s3-operations.md +1302 -1302
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-03-sftp-operations.md +1379 -1379
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-04-file-patterns.md +941 -941
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-05-advanced-topics.md +813 -813
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-06-integration-patterns.md +486 -486
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-07-troubleshooting.md +387 -387
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-08-api-reference.md +417 -417
- package/docs/02-CORE-GUIDES/data-sources/readme.md +77 -77
- package/docs/02-CORE-GUIDES/error-handling-guide.md +936 -936
- package/docs/02-CORE-GUIDES/extraction/examples/02-core-guides-extraction-readme.md +116 -116
- package/docs/02-CORE-GUIDES/extraction/examples/common-patterns.ts +428 -428
- package/docs/02-CORE-GUIDES/extraction/examples/extract-inventory-basic.ts +187 -187
- package/docs/02-CORE-GUIDES/extraction/extraction-quick-reference.md +596 -596
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-01-foundations.md +514 -514
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-02-basic-extraction.md +823 -823
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-03-parquet-processing.md +507 -507
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-04-data-enrichment.md +546 -546
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-05-transformation.md +494 -494
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-export-formats.md +458 -458
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-performance.md +138 -138
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-api-reference.md +148 -148
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-optimization.md +692 -692
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-08-extraction-orchestrator.md +1008 -1008
- package/docs/02-CORE-GUIDES/extraction/readme.md +151 -151
- package/docs/02-CORE-GUIDES/ingestion/examples/_simple-kv-store.ts +40 -40
- package/docs/02-CORE-GUIDES/ingestion/examples/error-recovery.ts +728 -728
- package/docs/02-CORE-GUIDES/ingestion/examples/event-driven.ts +501 -501
- package/docs/02-CORE-GUIDES/ingestion/examples/local-file-ingestion.ts +88 -88
- package/docs/02-CORE-GUIDES/ingestion/examples/parquet-ingestion.ts +117 -117
- package/docs/02-CORE-GUIDES/ingestion/examples/performance-optimized.ts +647 -647
- package/docs/02-CORE-GUIDES/ingestion/examples/s3-csv-ingestion.ts +169 -169
- package/docs/02-CORE-GUIDES/ingestion/examples/sftp-csv-ingestion.ts +134 -134
- package/docs/02-CORE-GUIDES/ingestion/ingestion-quick-reference.md +546 -546
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-01-introduction.md +626 -626
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-02-quick-start.md +658 -658
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-03-data-sources.md +1052 -1052
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-04-field-mapping.md +763 -763
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-05-advanced-parsers.md +676 -676
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-06-batch-api.md +1295 -1295
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-api-reference.md +138 -138
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-state-management.md +1037 -1037
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-08-performance-optimization.md +1349 -1349
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-09-best-practices.md +1893 -1893
- package/docs/02-CORE-GUIDES/ingestion/readme.md +160 -160
- package/docs/02-CORE-GUIDES/logging-guide.md +585 -585
- package/docs/02-CORE-GUIDES/mapping/error-handling-patterns.md +401 -401
- package/docs/02-CORE-GUIDES/mapping/examples/02-core-guides-mapping-readme.md +128 -128
- package/docs/02-CORE-GUIDES/mapping/examples/common-patterns.ts +273 -273
- package/docs/02-CORE-GUIDES/mapping/examples/csv-location-ingestion.json +36 -36
- package/docs/02-CORE-GUIDES/mapping/examples/csv-mapping.ts +242 -242
- package/docs/02-CORE-GUIDES/mapping/examples/graphql-to-parquet-extraction.json +36 -36
- package/docs/02-CORE-GUIDES/mapping/examples/json-mapping.ts +213 -213
- package/docs/02-CORE-GUIDES/mapping/examples/json-product-to-mutation.json +48 -48
- package/docs/02-CORE-GUIDES/mapping/examples/xml-mapping.ts +291 -291
- package/docs/02-CORE-GUIDES/mapping/examples/xml-order-to-mutation.json +45 -45
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-quick-reference.md +463 -463
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-readme.md +227 -227
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-01-introduction.md +222 -222
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-02-quick-start.md +351 -351
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-03-schema-validation.md +569 -569
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-04-mapping-patterns.md +471 -471
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-05-configuration-reference.md +611 -611
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-advanced-xpath.md +148 -148
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-path-syntax.md +464 -464
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-api-reference.md +94 -94
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-array-handling.md +307 -307
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-08-custom-resolvers.md +544 -544
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-09-advanced-patterns.md +427 -427
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-10-hooks-and-variables.md +336 -336
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-11-error-handling.md +488 -488
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-12-arguments-vs-nodes.md +383 -383
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-13-best-practices.md +477 -477
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/readme.md +62 -62
- package/docs/02-CORE-GUIDES/mapping/mapping-format-decision-tree.md +480 -480
- package/docs/02-CORE-GUIDES/mapping/mapping-graphql-alias-batching-guide.md +820 -820
- package/docs/02-CORE-GUIDES/mapping/mapping-javascript-objects.md +2369 -2369
- package/docs/02-CORE-GUIDES/mapping/mapping-mapper-comparison-guide.md +682 -682
- package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-07-api-reference.md +1327 -1327
- package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-08-error-handling.md +1142 -1142
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-04-use-cases.md +891 -891
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-helpers-resolvers.md +1126 -1126
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-sdk-resolvers.md +199 -199
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-07-api-reference.md +1319 -1319
- package/docs/02-CORE-GUIDES/mapping/readme.md +178 -178
- package/docs/02-CORE-GUIDES/mapping/resolver-registration.md +410 -410
- package/docs/02-CORE-GUIDES/mapping/resolvers/examples/common-patterns.ts +226 -226
- package/docs/02-CORE-GUIDES/mapping/resolvers/examples/custom-resolvers.ts +227 -227
- package/docs/02-CORE-GUIDES/mapping/resolvers/examples/sdk-resolvers-usage.ts +203 -203
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-readme.md +274 -274
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-api-reference.md +679 -679
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-cookbook.md +826 -826
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-guide.md +1330 -1330
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-helpers-reference.md +1437 -1437
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-parameters-reference.md +553 -553
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-troubleshooting.md +854 -854
- package/docs/02-CORE-GUIDES/mapping/resolvers/readme.md +75 -75
- package/docs/02-CORE-GUIDES/parsers/examples/02-core-guides-parsers-readme.md +161 -161
- package/docs/02-CORE-GUIDES/parsers/examples/csv-parser-examples.ts +110 -110
- package/docs/02-CORE-GUIDES/parsers/examples/json-parser-examples.ts +33 -33
- package/docs/02-CORE-GUIDES/parsers/examples/parquet-parser-examples.ts +47 -47
- package/docs/02-CORE-GUIDES/parsers/examples/xml-parser-examples.ts +38 -38
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-01-foundations.md +355 -355
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-02-csv-parser.md +772 -772
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-03-json-parser.md +789 -789
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-04-xml-parser.md +857 -857
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-05-parquet-parser.md +603 -603
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-integration-patterns.md +702 -702
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-streaming.md +121 -121
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-api-reference.md +89 -89
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-troubleshooting.md +727 -727
- package/docs/02-CORE-GUIDES/parsers/parsers-quick-reference.md +482 -482
- package/docs/02-CORE-GUIDES/parsers/parsers-readme.md +258 -258
- package/docs/02-CORE-GUIDES/parsers/readme.md +65 -65
- package/docs/02-CORE-GUIDES/readme.md +194 -194
- package/docs/02-CORE-GUIDES/webhook-validation/examples/basic-validation.ts +108 -108
- package/docs/02-CORE-GUIDES/webhook-validation/examples/common-patterns.ts +316 -316
- package/docs/02-CORE-GUIDES/webhook-validation/examples/webhook-validation-readme.md +61 -61
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-01-foundations.md +440 -440
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-02-quick-start.md +525 -525
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-03-versori-integration.md +741 -741
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-04-platform-integration.md +629 -629
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-05-configuration.md +535 -535
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-error-handling.md +611 -611
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-troubleshooting.md +124 -124
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-07-api-reference.md +511 -511
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-08-rubix-webhooks.md +590 -590
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-09-rubix-event-vs-http-call.md +432 -432
- package/docs/02-CORE-GUIDES/webhook-validation/readme.md +239 -239
- package/docs/02-CORE-GUIDES/webhook-validation/webhook-validation-quick-reference.md +392 -392
- package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-quick-reference.md +498 -498
- package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-readme.md +313 -313
- package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/common-patterns.ts +612 -612
- package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/connector-scenarios-readme.md +253 -253
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-01-foundations.md +452 -452
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-02-simple-scenarios.md +681 -681
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-03-intermediate-scenarios.md +637 -637
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-04-advanced-scenarios.md +650 -650
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-05-bidirectional-sync.md +233 -233
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-06-production-patterns.md +442 -442
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-07-reference.md +445 -445
- package/docs/03-PATTERN-GUIDES/connector-scenarios/readme.md +31 -31
- package/docs/03-PATTERN-GUIDES/enterprise-integration-patterns.md +1528 -1528
- package/docs/03-PATTERN-GUIDES/error-handling/comprehensive-error-handling-guide.md +1437 -1437
- package/docs/03-PATTERN-GUIDES/error-handling/error-handling-quick-reference.md +390 -390
- package/docs/03-PATTERN-GUIDES/error-handling/examples/common-patterns.ts +438 -438
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-01-foundations.md +362 -362
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-02-error-types.md +850 -850
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-03-utf8-handling.md +456 -456
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-04-error-scenarios.md +658 -658
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-05-calling-patterns.md +671 -671
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-06-retry-strategies.md +1034 -1034
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-07-monitoring.md +653 -653
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-08-api-reference.md +847 -847
- package/docs/03-PATTERN-GUIDES/error-handling/readme.md +36 -36
- package/docs/03-PATTERN-GUIDES/examples/__tests__/readme.md +40 -40
- package/docs/03-PATTERN-GUIDES/examples/__tests__/resolver-examples.test.js +282 -282
- package/docs/03-PATTERN-GUIDES/examples/test-data/03-pattern-guides-readme.md +110 -110
- package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-inventory.json +123 -123
- package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-order.json +171 -171
- package/docs/03-PATTERN-GUIDES/examples/test-data/readme.md +28 -28
- package/docs/03-PATTERN-GUIDES/extraction/extraction-readme.md +15 -15
- package/docs/03-PATTERN-GUIDES/extraction/readme.md +25 -25
- package/docs/03-PATTERN-GUIDES/file-operations/examples/common-patterns.ts +407 -407
- package/docs/03-PATTERN-GUIDES/file-operations/examples/file-operations-readme.md +142 -142
- package/docs/03-PATTERN-GUIDES/file-operations/file-operations-quick-reference.md +462 -462
- package/docs/03-PATTERN-GUIDES/file-operations/file-operations-readme.md +379 -379
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-01-foundations.md +430 -430
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-02-quick-start.md +484 -484
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-03-s3-operations.md +507 -507
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-04-sftp-operations.md +963 -963
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-05-streaming-performance.md +503 -503
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-archive-patterns.md +386 -386
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-error-handling.md +117 -117
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-api-reference.md +78 -78
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-testing-troubleshooting.md +567 -567
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-08-api-reference.md +1055 -1055
- package/docs/03-PATTERN-GUIDES/file-operations/readme.md +32 -32
- package/docs/03-PATTERN-GUIDES/ingestion/ingestion-readme.md +15 -15
- package/docs/03-PATTERN-GUIDES/ingestion/readme.md +25 -25
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/batch-processing.ts +130 -130
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/common-patterns.ts +360 -360
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/delta-sync.ts +130 -130
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/integration-patterns-readme.md +100 -100
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/real-time-webhook.ts +398 -398
- package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-quick-reference.md +962 -962
- package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-readme.md +134 -134
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-01-real-time-processing.md +991 -991
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-02-batch-processing.md +1547 -1547
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-03-delta-sync.md +1108 -1108
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-04-webhook-patterns.md +1181 -1181
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-05-error-handling.md +1061 -1061
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-advanced-integration-services.md +1547 -1547
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-performance.md +109 -109
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-07-api-reference.md +34 -34
- package/docs/03-PATTERN-GUIDES/integration-patterns/readme.md +30 -30
- package/docs/03-PATTERN-GUIDES/logging-minimal-mode.md +128 -128
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/common-patterns.ts +380 -380
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/multiple-connections-readme.md +139 -139
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/parallel-root-connections.ts +149 -149
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/real-world-scenarios.ts +405 -405
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-01-foundations.md +378 -378
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-02-quick-start.md +566 -566
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-03-targeting-connections.md +659 -659
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-04-parallel-queries.md +656 -656
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-05-best-practices.md +624 -624
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-api-reference.md +824 -824
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-versori.md +119 -119
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-07-api-reference.md +87 -87
- package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-quick-reference.md +353 -353
- package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-readme.md +270 -270
- package/docs/03-PATTERN-GUIDES/multiple-connections/readme.md +30 -30
- package/docs/03-PATTERN-GUIDES/pagination/pagination-readme.md +14 -14
- package/docs/03-PATTERN-GUIDES/pagination/readme.md +24 -24
- package/docs/03-PATTERN-GUIDES/parquet/examples/common-patterns.ts +180 -180
- package/docs/03-PATTERN-GUIDES/parquet/examples/read-parquet.ts +48 -48
- package/docs/03-PATTERN-GUIDES/parquet/examples/write-parquet.ts +65 -65
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-01-introduction.md +393 -393
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-02-quick-start.md +572 -572
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-03-reading-parquet.md +525 -525
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-04-writing-parquet.md +554 -554
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-05-graphql-extraction.md +405 -405
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-performance.md +104 -104
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-s3-integration.md +511 -511
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-api-reference.md +90 -90
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-performance-optimization.md +525 -525
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-08-best-practices.md +712 -712
- package/docs/03-PATTERN-GUIDES/parquet/parquet-quick-reference.md +683 -683
- package/docs/03-PATTERN-GUIDES/parquet/parquet-readme.md +248 -248
- package/docs/03-PATTERN-GUIDES/parquet/readme.md +32 -32
- package/docs/03-PATTERN-GUIDES/parsers/parsers-readme.md +12 -12
- package/docs/03-PATTERN-GUIDES/parsers/readme.md +24 -24
- package/docs/03-PATTERN-GUIDES/readme.md +159 -159
- package/docs/03-PATTERN-GUIDES/webhooks/readme.md +24 -24
- package/docs/03-PATTERN-GUIDES/webhooks/webhooks-readme.md +8 -8
- package/docs/04-REFERENCE/architecture/architecture-01-overview.md +427 -427
- package/docs/04-REFERENCE/architecture/architecture-02-client-architecture.md +424 -424
- package/docs/04-REFERENCE/architecture/architecture-03-data-flow.md +690 -690
- package/docs/04-REFERENCE/architecture/architecture-04-service-layer.md +834 -834
- package/docs/04-REFERENCE/architecture/architecture-05-integration-architecture.md +655 -655
- package/docs/04-REFERENCE/architecture/architecture-06-state-management.md +653 -653
- package/docs/04-REFERENCE/architecture/architecture-adding-new-data-sources.md +686 -686
- package/docs/04-REFERENCE/architecture/readme.md +279 -279
- package/docs/04-REFERENCE/platforms/deno/readme.md +117 -117
- package/docs/04-REFERENCE/platforms/nodejs/readme.md +146 -146
- package/docs/04-REFERENCE/platforms/readme.md +135 -135
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-01-introduction.md +398 -398
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-02-quick-start.md +560 -560
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-03-authentication.md +757 -757
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-04-workflows.md +2476 -2476
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-05-connections.md +1167 -1167
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-kv-storage.md +990 -990
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-state-management.md +121 -121
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-api-reference.md +68 -68
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-deployment.md +731 -731
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-08-best-practices.md +1111 -1111
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-09-signature-reference.md +766 -766
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-readme.md +299 -299
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-s3-sftp-configuration-guide.md +1425 -1425
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-api-key-security.md +816 -816
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-connection-security.md +681 -681
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-workflow-task-types.md +708 -708
- package/docs/04-REFERENCE/platforms/versori/readme.md +108 -108
- package/docs/04-REFERENCE/readme.md +148 -148
- package/docs/04-REFERENCE/resolver-signature/examples/advanced-resolvers.ts +482 -482
- package/docs/04-REFERENCE/resolver-signature/examples/async-resolvers.ts +496 -496
- package/docs/04-REFERENCE/resolver-signature/examples/basic-resolvers.ts +343 -343
- package/docs/04-REFERENCE/resolver-signature/examples/resolver-signature-readme.md +188 -188
- package/docs/04-REFERENCE/resolver-signature/examples/testing-resolvers.ts +463 -463
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-01-foundations.md +286 -286
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-02-parameter-reference.md +643 -643
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-03-basic-examples.md +521 -521
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-04-advanced-patterns.md +739 -739
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-05-sdk-resolvers.md +531 -531
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-migration-guide.md +650 -650
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-testing.md +125 -125
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-07-api-reference.md +794 -794
- package/docs/04-REFERENCE/resolver-signature/readme.md +64 -64
- package/docs/04-REFERENCE/resolver-signature/resolver-signature-quick-reference.md +270 -270
- package/docs/04-REFERENCE/resolver-signature/resolver-signature-readme.md +351 -351
- package/docs/04-REFERENCE/schema/fluent-commerce-schema.json +764 -764
- package/docs/04-REFERENCE/schema/readme.md +141 -141
- package/docs/04-REFERENCE/testing/examples/04-reference-testing-readme.md +158 -158
- package/docs/04-REFERENCE/testing/examples/fluent-testing.ts +62 -62
- package/docs/04-REFERENCE/testing/examples/health-check.ts +155 -155
- package/docs/04-REFERENCE/testing/examples/integration-test.ts +119 -119
- package/docs/04-REFERENCE/testing/examples/performance-test.ts +183 -183
- package/docs/04-REFERENCE/testing/examples/s3-testing.ts +127 -127
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-01-foundations.md +267 -267
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-02-s3-testing.md +599 -599
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-03-fluent-testing.md +589 -589
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-04-integration-testing.md +699 -699
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-05-debugging.md +478 -478
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-cicd-integration.md +463 -463
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-preflight-validation.md +131 -131
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-best-practices.md +499 -499
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-coverage-ci.md +165 -165
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-08-api-reference.md +634 -634
- package/docs/04-REFERENCE/testing/readme.md +86 -86
- package/docs/04-REFERENCE/testing/testing-quick-reference.md +667 -667
- package/docs/04-REFERENCE/testing/testing-readme.md +286 -286
- package/docs/04-REFERENCE/troubleshooting/readme.md +144 -144
- package/docs/04-REFERENCE/troubleshooting/troubleshooting-deno-sftp-compatibility.md +392 -392
- package/docs/template-loading-matrix.md +242 -242
- package/package.json +5 -3
|
@@ -1,757 +1,757 @@
|
|
|
1
|
-
# Module 3: Authentication & Connections
|
|
2
|
-
|
|
3
|
-
[← Back to Versori Platform Guide](../platforms-versori-readme.md)
|
|
4
|
-
|
|
5
|
-
**Module 3 of 8** | **Level**: Beginner | **Time**: 35 minutes
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Learning Objectives
|
|
10
|
-
|
|
11
|
-
By the end of this module, you will:
|
|
12
|
-
- ✅ Understand OAuth2 authentication in Versori
|
|
13
|
-
- ✅ Configure Fluent Commerce connections in Versori UI
|
|
14
|
-
- ✅ Use `createClient()` with Versori context
|
|
15
|
-
- ✅ Understand FluentVersoriClient vs FluentClient
|
|
16
|
-
- ✅ Access connection credentials and metadata
|
|
17
|
-
- ✅ Handle authentication errors
|
|
18
|
-
- ✅ Implement security best practices
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## OAuth2 in Versori Platform
|
|
23
|
-
|
|
24
|
-
Versori manages OAuth2 credentials securely through **Connections**. Your code never handles raw credentials.
|
|
25
|
-
|
|
26
|
-
### Key Benefits
|
|
27
|
-
|
|
28
|
-
- **No credential management** in code - Versori handles token storage and refresh
|
|
29
|
-
- **Automatic token refresh** when expired - transparent to your code
|
|
30
|
-
- **Secure storage** in Versori platform - encrypted at rest
|
|
31
|
-
- **Environment-specific** configs (dev/staging/prod) - separate credentials per environment
|
|
32
|
-
- **Audit logging** of API calls - full traceability
|
|
33
|
-
- **Connection reuse** across workflows - configure once, use everywhere
|
|
34
|
-
|
|
35
|
-
### How Authentication Works
|
|
36
|
-
|
|
37
|
-
```
|
|
38
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
39
|
-
│ Versori Platform │
|
|
40
|
-
│ │
|
|
41
|
-
│ ┌──────────────┐ ┌──────────────┐ │
|
|
42
|
-
│ │ Workflow │──ctx.fetch()──→ │ Connection │ │
|
|
43
|
-
│ │ │ │ (OAuth2) │ │
|
|
44
|
-
│ └──────────────┘ └──────┬───────┘ │
|
|
45
|
-
│ │ │
|
|
46
|
-
└───────────────────────────────────────────┼─────────────────┘
|
|
47
|
-
│
|
|
48
|
-
│ Managed Auth
|
|
49
|
-
↓
|
|
50
|
-
┌──────────────────────────┐
|
|
51
|
-
│ Fluent Commerce API │
|
|
52
|
-
│ (api.fluentcommerce.com)│
|
|
53
|
-
└──────────────────────────┘
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
**Key Points**:
|
|
57
|
-
1. Workflows use `ctx.fetch()` - Versori injects authentication automatically
|
|
58
|
-
2. Connection stores OAuth2 credentials - client ID, client secret
|
|
59
|
-
3. Platform handles token lifecycle - fetch, refresh, retry on 401
|
|
60
|
-
4. Your code never sees raw credentials - only uses authenticated fetch
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## Configuring Fluent Commerce Connection
|
|
65
|
-
|
|
66
|
-
### Step 1: Access Connections in Versori UI
|
|
67
|
-
|
|
68
|
-
1. Log in to Versori dashboard
|
|
69
|
-
2. Navigate to **Connections** tab (left sidebar)
|
|
70
|
-
3. Click **"Add Connection"** button
|
|
71
|
-
|
|
72
|
-
### Step 2: Connection Configuration
|
|
73
|
-
|
|
74
|
-
**Basic Details**:
|
|
75
|
-
```
|
|
76
|
-
Name: fluent_commerce
|
|
77
|
-
Description: Fluent Commerce Production API
|
|
78
|
-
Type: Custom OAuth2
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
**OAuth2 Settings**:
|
|
82
|
-
```
|
|
83
|
-
Auth URL: https://api.fluentcommerce.com/oauth/token
|
|
84
|
-
Token URL: https://api.fluentcommerce.com/oauth/token
|
|
85
|
-
Grant Type: client_credentials
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
**Client Credentials**:
|
|
89
|
-
```
|
|
90
|
-
Client ID: [Your Fluent OAuth2 Client ID]
|
|
91
|
-
Client Secret: [Your Fluent OAuth2 Client Secret]
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
**API Configuration**:
|
|
95
|
-
```
|
|
96
|
-
Base URL: https://api.fluentcommerce.com
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
**Custom Parameters** (JSON) - **Optional:**
|
|
100
|
-
```json
|
|
101
|
-
{
|
|
102
|
-
"retailerId": "1"
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
**Note:** `retailerId` is only needed if you're using Job API or Event API. For GraphQL queries only, you can omit it. If your Versori version doesn't support Custom Parameters, use `client.setRetailerId('1')` after creating the client.
|
|
107
|
-
|
|
108
|
-
**See complete retailerId guide below or:** [Complete retailerId Configuration Guide](../../../../00-START-HERE/retailerid-configuration.md)
|
|
109
|
-
|
|
110
|
-
### Step 3: Test Connection
|
|
111
|
-
|
|
112
|
-
Click **"Test Connection"** to verify:
|
|
113
|
-
- OAuth2 token can be fetched
|
|
114
|
-
- Base URL is accessible
|
|
115
|
-
- Credentials are correct
|
|
116
|
-
|
|
117
|
-
---
|
|
118
|
-
|
|
119
|
-
## Using createClient() with Versori
|
|
120
|
-
|
|
121
|
-
### Basic Usage
|
|
122
|
-
|
|
123
|
-
```typescript
|
|
124
|
-
import { http } from '@versori/run';
|
|
125
|
-
import { createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
126
|
-
|
|
127
|
-
export const workflow = http('name', {
|
|
128
|
-
connection: 'fluent_commerce'
|
|
129
|
-
}, async (ctx) => {
|
|
130
|
-
// Create client from Versori context
|
|
131
|
-
const client = await createClient(ctx);
|
|
132
|
-
|
|
133
|
-
// Use client - authentication is automatic
|
|
134
|
-
const result = await client.graphql({
|
|
135
|
-
query: `query { products(first: 10) { edges { node { id ref } } } }`
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
return result.data;
|
|
139
|
-
});
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### What `createClient()` Does
|
|
143
|
-
|
|
144
|
-
```typescript
|
|
145
|
-
// Internally, createClient() detects Versori context:
|
|
146
|
-
export async function createClient(ctx: HttpContext): Promise<FluentVersoriClient> {
|
|
147
|
-
// 1. Detects runtime (Versori vs Node.js/Deno)
|
|
148
|
-
// 2. Creates appropriate client type
|
|
149
|
-
// 3. Extracts retailerId from connection variables or URL
|
|
150
|
-
// 4. Returns configured client
|
|
151
|
-
|
|
152
|
-
return FluentVersoriClient.fromContext(ctx);
|
|
153
|
-
}
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
**Key Detection Logic**:
|
|
157
|
-
- Checks for `ctx.fetch` (Versori-specific)
|
|
158
|
-
- Checks for `ctx.log` (Versori logging)
|
|
159
|
-
- Checks for `ctx.baseUrl` (connection base URL)
|
|
160
|
-
- Falls back to standalone mode if not Versori
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## FluentVersoriClient vs FluentClient
|
|
165
|
-
|
|
166
|
-
### Architecture Comparison
|
|
167
|
-
|
|
168
|
-
| Feature | FluentVersoriClient | FluentClient |
|
|
169
|
-
|---------|---------------------|--------------|
|
|
170
|
-
| **Runtime** | Versori platform only | Node.js, Deno, standalone |
|
|
171
|
-
| **Authentication** | Platform-managed (ctx.fetch) | Manual OAuth2 (clientId/secret) |
|
|
172
|
-
| **Token Management** | Automatic (Versori) | Manual (AuthService) |
|
|
173
|
-
| **Base URL** | From connection config | Passed in constructor |
|
|
174
|
-
| **Fetch Implementation** | `ctx.fetch()` (Versori) | `fetch()` (standard) |
|
|
175
|
-
| **Logging** | `ctx.log` (platform) | Custom logger or console |
|
|
176
|
-
| **KV Storage** | `ctx.openKv()` available | External KV required |
|
|
177
|
-
|
|
178
|
-
### When to Use Each
|
|
179
|
-
|
|
180
|
-
**Use FluentVersoriClient** (via `createClient(ctx)`):
|
|
181
|
-
- ✅ Running on Versori platform (webhooks, scheduled, HTTP workflows)
|
|
182
|
-
- ✅ Want automatic authentication
|
|
183
|
-
- ✅ Need Versori KV storage integration
|
|
184
|
-
- ✅ Platform logging required
|
|
185
|
-
|
|
186
|
-
**Use FluentClient** (standalone):
|
|
187
|
-
- ✅ Running Node.js scripts locally
|
|
188
|
-
- ✅ Running in Deno
|
|
189
|
-
- ✅ Custom environments (Lambda, Docker, etc.)
|
|
190
|
-
- ✅ Testing with mock credentials
|
|
191
|
-
|
|
192
|
-
### Code Example: Both Approaches
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
// ✅ Versori Platform (FluentVersoriClient via createClient)
|
|
196
|
-
import { http } from '@versori/run';
|
|
197
|
-
import { createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
198
|
-
|
|
199
|
-
export const versoriWorkflow = http('versori', {
|
|
200
|
-
connection: 'fluent_commerce'
|
|
201
|
-
}, async (ctx) => {
|
|
202
|
-
const client = await createClient(ctx); // Auto-detects Versori
|
|
203
|
-
return await client.graphql({ query: '...' });
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
// ✅ Standalone Node.js (FluentClient directly)
|
|
207
|
-
import { FluentClient } from '@fluentcommerce/fc-connect-sdk';
|
|
208
|
-
|
|
209
|
-
const client = new FluentClient({
|
|
210
|
-
baseUrl: 'https://api.fluentcommerce.com',
|
|
211
|
-
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
212
|
-
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
213
|
-
username: process.env.FLUENT_USERNAME,
|
|
214
|
-
password: process.env.FLUENT_PASSWORD,
|
|
215
|
-
retailerId: '1'
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
const result = await client.graphql({ query: '...' });
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
---
|
|
222
|
-
|
|
223
|
-
## Accessing Connection Credentials
|
|
224
|
-
|
|
225
|
-
### Connection Variables
|
|
226
|
-
|
|
227
|
-
Versori connections can store custom variables accessible in workflows:
|
|
228
|
-
|
|
229
|
-
```typescript
|
|
230
|
-
import { http } from '@versori/run';
|
|
231
|
-
|
|
232
|
-
export const accessConnectionVars = http('access-vars', {
|
|
233
|
-
connection: 'fluent_commerce'
|
|
234
|
-
}, async (ctx) => {
|
|
235
|
-
// Access connection variables
|
|
236
|
-
const connectionVars = ctx.connectionVariables || {};
|
|
237
|
-
|
|
238
|
-
const retailerId = connectionVars.retailerId || '1';
|
|
239
|
-
const environment = connectionVars.environment || 'production';
|
|
240
|
-
|
|
241
|
-
ctx.log('info', 'Connection variables', {
|
|
242
|
-
retailerId,
|
|
243
|
-
environment
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
return { retailerId, environment };
|
|
247
|
-
});
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
### Base URL Access
|
|
251
|
-
|
|
252
|
-
```typescript
|
|
253
|
-
export const accessBaseUrl = http('access-url', {
|
|
254
|
-
connection: 'fluent_commerce'
|
|
255
|
-
}, async (ctx) => {
|
|
256
|
-
// Base URL may be a Promise
|
|
257
|
-
const baseUrl = await ctx.baseUrl;
|
|
258
|
-
|
|
259
|
-
ctx.log('info', 'Connection base URL', { baseUrl });
|
|
260
|
-
|
|
261
|
-
return { baseUrl };
|
|
262
|
-
});
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
### Retailer ID Extraction
|
|
266
|
-
|
|
267
|
-
The SDK automatically extracts retailer ID from:
|
|
268
|
-
|
|
269
|
-
1. **Connection variables** (highest priority):
|
|
270
|
-
```json
|
|
271
|
-
{ "retailerId": "1" }
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
2. **URL path** (fallback):
|
|
275
|
-
```
|
|
276
|
-
https://api.fluentcommerce.com/graphql/1
|
|
277
|
-
↑
|
|
278
|
-
retailerId
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
3. **Manual override**:
|
|
282
|
-
```typescript
|
|
283
|
-
const client = await createClient(ctx);
|
|
284
|
-
client.setRetailerId('2'); // Override if needed
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
---
|
|
288
|
-
|
|
289
|
-
## retailerId Configuration (v0.1.30+)
|
|
290
|
-
|
|
291
|
-
Starting with v0.1.30, `retailerId` is **optional** for GraphQL queries but **required** for Job and Event APIs.
|
|
292
|
-
|
|
293
|
-
### When retailerId is Required
|
|
294
|
-
|
|
295
|
-
| API Type | retailerId Required? | Validation |
|
|
296
|
-
|----------|---------------------|------------|
|
|
297
|
-
| GraphQL Queries (`client.graphql()`) | ❌ Optional | Not validated |
|
|
298
|
-
| GraphQL Mutations (`client.graphql()`) | ❌ Optional | Not validated |
|
|
299
|
-
| Job API (`createJob()`, `getJob()`) | ✅ Required | Fail-fast at method call |
|
|
300
|
-
| Event API (`sendEvent()`) | ✅ Required | Fail-fast at method call |
|
|
301
|
-
| Batch API (`sendBatch()`) | ✅ Required | Fail-fast at method call |
|
|
302
|
-
|
|
303
|
-
### Configuration Patterns
|
|
304
|
-
|
|
305
|
-
**Option 1: Set at Client Creation (Recommended)**
|
|
306
|
-
```typescript
|
|
307
|
-
import { createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
308
|
-
|
|
309
|
-
export const inventorySync = http('POST', '/sync', async (ctx) => {
|
|
310
|
-
// retailerId set once at client creation
|
|
311
|
-
const client = await createClient({
|
|
312
|
-
context: ctx,
|
|
313
|
-
retailerId: ctx.connectionVariables?.RETAILER_ID,
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
// Works for all APIs
|
|
317
|
-
await client.createJob({ name: 'inventory-sync' });
|
|
318
|
-
await client.graphql({ query: '...' });
|
|
319
|
-
|
|
320
|
-
return { success: true };
|
|
321
|
-
});
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
**Option 2: Set Dynamically (Multi-Tenant)**
|
|
325
|
-
```typescript
|
|
326
|
-
export const multiTenantSync = http('POST', '/sync/:retailerId', async (ctx) => {
|
|
327
|
-
const client = await createClient({ context: ctx });
|
|
328
|
-
|
|
329
|
-
// Set retailerId from URL parameter
|
|
330
|
-
const retailerId = ctx.params?.retailerId;
|
|
331
|
-
client.setRetailerId(retailerId);
|
|
332
|
-
|
|
333
|
-
await client.createJob({ name: 'inventory-sync' });
|
|
334
|
-
|
|
335
|
-
return { success: true };
|
|
336
|
-
});
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
**Option 3: No retailerId (GraphQL Only)**
|
|
340
|
-
```typescript
|
|
341
|
-
export const queryProducts = http('POST', '/query', async (ctx) => {
|
|
342
|
-
// No retailerId needed for GraphQL queries
|
|
343
|
-
const client = await createClient({ context: ctx });
|
|
344
|
-
|
|
345
|
-
const result = await client.graphql({
|
|
346
|
-
query: `query { products { edges { node { id ref } } } }`
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
return result.data;
|
|
350
|
-
});
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
### Error Handling
|
|
354
|
-
|
|
355
|
-
```typescript
|
|
356
|
-
export const withRetailerIdValidation = http('POST', '/sync', {
|
|
357
|
-
connection: 'fluent_commerce'
|
|
358
|
-
}, async (ctx) => {
|
|
359
|
-
try {
|
|
360
|
-
const client = await createClient({ context: ctx });
|
|
361
|
-
|
|
362
|
-
// Try to call Job API
|
|
363
|
-
const job = await client.createJob({ name: 'inventory-sync' });
|
|
364
|
-
|
|
365
|
-
return { success: true, jobId: job.id };
|
|
366
|
-
|
|
367
|
-
} catch (error) {
|
|
368
|
-
if (error instanceof Error && error.message.includes('retailerId is required')) {
|
|
369
|
-
// Handle missing retailerId
|
|
370
|
-
ctx.log('error', 'retailerId not configured', {
|
|
371
|
-
error: error.message
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
return {
|
|
375
|
-
success: false,
|
|
376
|
-
error: 'retailerId configuration missing',
|
|
377
|
-
details: 'Configure retailerId in connection variables or use client.setRetailerId()'
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
throw error; // Re-throw other errors
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
**See Also:** [Complete retailerId Configuration Guide](../../../../00-START-HERE/retailerid-configuration.md) for all patterns and use cases.
|
|
387
|
-
|
|
388
|
-
---
|
|
389
|
-
|
|
390
|
-
## Authentication Error Handling
|
|
391
|
-
|
|
392
|
-
### Common Authentication Errors
|
|
393
|
-
|
|
394
|
-
```typescript
|
|
395
|
-
import { http } from '@versori/run';
|
|
396
|
-
import { createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
397
|
-
|
|
398
|
-
export const errorHandling = http('error-handling', {
|
|
399
|
-
connection: 'fluent_commerce'
|
|
400
|
-
}, async (ctx) => {
|
|
401
|
-
try {
|
|
402
|
-
const client = await createClient(ctx);
|
|
403
|
-
|
|
404
|
-
const result = await client.graphql({
|
|
405
|
-
query: `query { products(first: 10) { edges { node { id } } } }`
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
return { success: true, data: result.data };
|
|
409
|
-
|
|
410
|
-
} catch (error) {
|
|
411
|
-
// Log error details
|
|
412
|
-
ctx.log('error', 'GraphQL request failed', {
|
|
413
|
-
error: error instanceof Error ? error.message : String(error),
|
|
414
|
-
name: error instanceof Error ? error.name : 'Unknown'
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
// Check error type
|
|
418
|
-
if (error instanceof Error) {
|
|
419
|
-
// Authentication errors
|
|
420
|
-
if (error.message.includes('401') || error.message.includes('Unauthorized')) {
|
|
421
|
-
return {
|
|
422
|
-
success: false,
|
|
423
|
-
error: 'Authentication failed - check connection credentials',
|
|
424
|
-
retryable: false
|
|
425
|
-
};
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
// Token refresh errors
|
|
429
|
-
if (error.message.includes('token') || error.message.includes('expired')) {
|
|
430
|
-
return {
|
|
431
|
-
success: false,
|
|
432
|
-
error: 'Token expired - Versori will retry automatically',
|
|
433
|
-
retryable: true
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// Network errors
|
|
438
|
-
if (error.message.includes('ECONNREFUSED') || error.message.includes('timeout')) {
|
|
439
|
-
return {
|
|
440
|
-
success: false,
|
|
441
|
-
error: 'Network error - Fluent API unreachable',
|
|
442
|
-
retryable: true
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// Generic error response
|
|
448
|
-
return {
|
|
449
|
-
success: false,
|
|
450
|
-
error: 'Request failed',
|
|
451
|
-
details: error instanceof Error ? error.message : String(error)
|
|
452
|
-
};
|
|
453
|
-
}
|
|
454
|
-
});
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
### Error Response Patterns
|
|
458
|
-
|
|
459
|
-
| HTTP Status | Meaning | Versori Behavior | Your Action |
|
|
460
|
-
|-------------|---------|------------------|-------------|
|
|
461
|
-
| **401** | Unauthorized | Refreshes token, retries | Log error if retry fails |
|
|
462
|
-
| **403** | Forbidden | No retry | Check retailerId, permissions |
|
|
463
|
-
| **429** | Rate limited | Retries with backoff | Reduce request rate |
|
|
464
|
-
| **500** | Server error | May retry | Log for investigation |
|
|
465
|
-
| **503** | Service unavailable | Retries | Wait for service recovery |
|
|
466
|
-
|
|
467
|
-
---
|
|
468
|
-
|
|
469
|
-
## Token Management (Versori)
|
|
470
|
-
|
|
471
|
-
### Automatic Token Refresh
|
|
472
|
-
|
|
473
|
-
Versori handles token lifecycle automatically:
|
|
474
|
-
|
|
475
|
-
```typescript
|
|
476
|
-
// You write this:
|
|
477
|
-
const result = await client.graphql({ query: '...' });
|
|
478
|
-
|
|
479
|
-
// Versori does this behind the scenes:
|
|
480
|
-
// 1. Check if token exists and is valid
|
|
481
|
-
// 2. If expired, fetch new token from OAuth2 endpoint
|
|
482
|
-
// 3. Retry original request with fresh token
|
|
483
|
-
// 4. Return result to your code
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
**No manual token management needed!**
|
|
487
|
-
|
|
488
|
-
### Token Debugging
|
|
489
|
-
|
|
490
|
-
If authentication fails, check Versori logs:
|
|
491
|
-
|
|
492
|
-
```typescript
|
|
493
|
-
export const debugAuth = http('debug-auth', {
|
|
494
|
-
connection: 'fluent_commerce'
|
|
495
|
-
}, async (ctx) => {
|
|
496
|
-
ctx.log('info', 'Connection details', {
|
|
497
|
-
hasBaseUrl: !!ctx.baseUrl,
|
|
498
|
-
hasFetch: typeof ctx.fetch === 'function',
|
|
499
|
-
hasLog: typeof ctx.log === 'function',
|
|
500
|
-
connectionVars: ctx.connectionVariables || {}
|
|
501
|
-
});
|
|
502
|
-
|
|
503
|
-
// Test authentication
|
|
504
|
-
try {
|
|
505
|
-
const client = await createClient(ctx);
|
|
506
|
-
|
|
507
|
-
// Simple query to test auth
|
|
508
|
-
await client.graphql({
|
|
509
|
-
query: `query { __typename }`
|
|
510
|
-
});
|
|
511
|
-
|
|
512
|
-
ctx.log('info', 'Authentication successful');
|
|
513
|
-
return { authOk: true };
|
|
514
|
-
|
|
515
|
-
} catch (error) {
|
|
516
|
-
ctx.log('error', 'Authentication failed', {
|
|
517
|
-
error: error instanceof Error ? error.message : String(error)
|
|
518
|
-
});
|
|
519
|
-
return { authOk: false, error: String(error) };
|
|
520
|
-
}
|
|
521
|
-
});
|
|
522
|
-
```
|
|
523
|
-
|
|
524
|
-
---
|
|
525
|
-
|
|
526
|
-
## Security Best Practices
|
|
527
|
-
|
|
528
|
-
### 1. Never Log Credentials
|
|
529
|
-
|
|
530
|
-
```typescript
|
|
531
|
-
// ❌ WRONG - Logs sensitive data
|
|
532
|
-
ctx.log('info', 'Client config', {
|
|
533
|
-
clientId: connectionVars.clientId,
|
|
534
|
-
clientSecret: connectionVars.clientSecret // DON'T DO THIS
|
|
535
|
-
});
|
|
536
|
-
|
|
537
|
-
// ✅ CORRECT - Log safely
|
|
538
|
-
ctx.log('info', 'Client config', {
|
|
539
|
-
hasClientId: !!connectionVars.clientId,
|
|
540
|
-
hasClientSecret: !!connectionVars.clientSecret
|
|
541
|
-
});
|
|
542
|
-
```
|
|
543
|
-
|
|
544
|
-
### 2. Use Environment-Specific Connections
|
|
545
|
-
|
|
546
|
-
```
|
|
547
|
-
Connections:
|
|
548
|
-
- fluent_commerce_dev (dev environment)
|
|
549
|
-
- fluent_commerce_staging (staging environment)
|
|
550
|
-
- fluent_commerce_prod (production environment)
|
|
551
|
-
```
|
|
552
|
-
|
|
553
|
-
```typescript
|
|
554
|
-
// Select connection based on environment
|
|
555
|
-
const connectionName = process.env.ENV === 'production'
|
|
556
|
-
? 'fluent_commerce_prod'
|
|
557
|
-
: 'fluent_commerce_dev';
|
|
558
|
-
|
|
559
|
-
export const workflow = http('workflow', {
|
|
560
|
-
connection: connectionName
|
|
561
|
-
}, async (ctx) => {
|
|
562
|
-
// ...
|
|
563
|
-
});
|
|
564
|
-
```
|
|
565
|
-
|
|
566
|
-
### 3. Validate RetailerID
|
|
567
|
-
|
|
568
|
-
```typescript
|
|
569
|
-
export const validateRetailer = http('validate', {
|
|
570
|
-
connection: 'fluent_commerce'
|
|
571
|
-
}, async (ctx) => {
|
|
572
|
-
const client = await createClient(ctx);
|
|
573
|
-
const retailerId = client.getRetailerId();
|
|
574
|
-
|
|
575
|
-
// Validate retailer ID
|
|
576
|
-
if (!retailerId || retailerId === '') {
|
|
577
|
-
ctx.log('error', 'Retailer ID not configured');
|
|
578
|
-
throw new Error('Retailer ID missing - check connection configuration');
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// Validate format (numeric)
|
|
582
|
-
if (!/^\d+$/.test(retailerId)) {
|
|
583
|
-
ctx.log('error', 'Invalid retailer ID format', { retailerId });
|
|
584
|
-
throw new Error('Retailer ID must be numeric');
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
return { retailerId, valid: true };
|
|
588
|
-
});
|
|
589
|
-
```
|
|
590
|
-
|
|
591
|
-
### 4. Implement Request Timeouts
|
|
592
|
-
|
|
593
|
-
```typescript
|
|
594
|
-
export const withTimeout = http('with-timeout', {
|
|
595
|
-
connection: 'fluent_commerce'
|
|
596
|
-
}, async (ctx) => {
|
|
597
|
-
const client = await createClient(ctx);
|
|
598
|
-
|
|
599
|
-
// Implement timeout for long-running queries
|
|
600
|
-
const timeoutMs = 30000; // 30 seconds
|
|
601
|
-
|
|
602
|
-
const result = await Promise.race([
|
|
603
|
-
client.graphql({ query: '...' }),
|
|
604
|
-
new Promise((_, reject) =>
|
|
605
|
-
setTimeout(() => reject(new Error('Request timeout')), timeoutMs)
|
|
606
|
-
)
|
|
607
|
-
]);
|
|
608
|
-
|
|
609
|
-
return result;
|
|
610
|
-
});
|
|
611
|
-
```
|
|
612
|
-
|
|
613
|
-
---
|
|
614
|
-
|
|
615
|
-
## Advanced Connection Patterns
|
|
616
|
-
|
|
617
|
-
### Multi-Retailer Workflows
|
|
618
|
-
|
|
619
|
-
```typescript
|
|
620
|
-
import { http } from '@versori/run';
|
|
621
|
-
import { createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
622
|
-
|
|
623
|
-
export const multiRetailer = http('multi-retailer', {
|
|
624
|
-
connection: 'fluent_commerce'
|
|
625
|
-
}, async (ctx) => {
|
|
626
|
-
const retailers = ['1', '2', '3'];
|
|
627
|
-
const results = [];
|
|
628
|
-
|
|
629
|
-
for (const retailerId of retailers) {
|
|
630
|
-
const client = await createClient(ctx);
|
|
631
|
-
client.setRetailerId(retailerId);
|
|
632
|
-
|
|
633
|
-
try {
|
|
634
|
-
const result = await client.graphql({
|
|
635
|
-
query: `query { products(first: 10) { edges { node { id ref } } } }`
|
|
636
|
-
});
|
|
637
|
-
|
|
638
|
-
results.push({
|
|
639
|
-
retailerId,
|
|
640
|
-
success: true,
|
|
641
|
-
productCount: result.data.products.edges.length
|
|
642
|
-
});
|
|
643
|
-
|
|
644
|
-
} catch (error) {
|
|
645
|
-
ctx.log('error', 'Query failed for retailer', {
|
|
646
|
-
retailerId,
|
|
647
|
-
error: error instanceof Error ? error.message : String(error)
|
|
648
|
-
});
|
|
649
|
-
|
|
650
|
-
results.push({
|
|
651
|
-
retailerId,
|
|
652
|
-
success: false,
|
|
653
|
-
error: String(error)
|
|
654
|
-
});
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
return { results };
|
|
659
|
-
});
|
|
660
|
-
```
|
|
661
|
-
|
|
662
|
-
### Connection Health Check
|
|
663
|
-
|
|
664
|
-
```typescript
|
|
665
|
-
export const healthCheck = http('health-check', {
|
|
666
|
-
connection: 'fluent_commerce'
|
|
667
|
-
}, async (ctx) => {
|
|
668
|
-
const startTime = Date.now();
|
|
669
|
-
|
|
670
|
-
try {
|
|
671
|
-
const client = await createClient(ctx);
|
|
672
|
-
|
|
673
|
-
// Test basic connectivity
|
|
674
|
-
await client.graphql({
|
|
675
|
-
query: `query { __typename }`
|
|
676
|
-
});
|
|
677
|
-
|
|
678
|
-
const duration = Date.now() - startTime;
|
|
679
|
-
|
|
680
|
-
ctx.log('info', 'Health check passed', { durationMs: duration });
|
|
681
|
-
|
|
682
|
-
return {
|
|
683
|
-
healthy: true,
|
|
684
|
-
durationMs: duration,
|
|
685
|
-
timestamp: new Date().toISOString()
|
|
686
|
-
};
|
|
687
|
-
|
|
688
|
-
} catch (error) {
|
|
689
|
-
const duration = Date.now() - startTime;
|
|
690
|
-
|
|
691
|
-
ctx.log('error', 'Health check failed', {
|
|
692
|
-
durationMs: duration,
|
|
693
|
-
error: error instanceof Error ? error.message : String(error)
|
|
694
|
-
});
|
|
695
|
-
|
|
696
|
-
return {
|
|
697
|
-
healthy: false,
|
|
698
|
-
durationMs: duration,
|
|
699
|
-
error: String(error),
|
|
700
|
-
timestamp: new Date().toISOString()
|
|
701
|
-
};
|
|
702
|
-
}
|
|
703
|
-
});
|
|
704
|
-
```
|
|
705
|
-
|
|
706
|
-
---
|
|
707
|
-
|
|
708
|
-
## Key Takeaways
|
|
709
|
-
|
|
710
|
-
- 🎯 **Versori manages OAuth2** - Your code never handles credentials
|
|
711
|
-
- 🎯 **createClient(ctx)** - Universal factory auto-detects Versori context
|
|
712
|
-
- 🎯 **FluentVersoriClient** - Platform-optimized client using ctx.fetch
|
|
713
|
-
- 🎯 **FluentClient** - Standalone client for Node.js/Deno with manual OAuth2
|
|
714
|
-
- 🎯 **Connection variables** - Store retailerId and custom config
|
|
715
|
-
- 🎯 **Automatic token refresh** - Versori handles token lifecycle
|
|
716
|
-
- 🎯 **Error handling** - Log errors, check status codes, implement retries
|
|
717
|
-
- 🎯 **Security** - Never log credentials, use environment-specific connections
|
|
718
|
-
|
|
719
|
-
---
|
|
720
|
-
|
|
721
|
-
## Practice Exercise
|
|
722
|
-
|
|
723
|
-
Create a workflow that:
|
|
724
|
-
1. Uses `createClient()` to create authenticated client
|
|
725
|
-
2. Validates retailer ID is configured
|
|
726
|
-
3. Implements proper error handling for auth failures
|
|
727
|
-
4. Logs connection health metrics
|
|
728
|
-
5. Handles multiple retries on transient errors
|
|
729
|
-
|
|
730
|
-
**Hints**:
|
|
731
|
-
- Use `try/catch` for error handling
|
|
732
|
-
- Check `client.getRetailerId()` for validation
|
|
733
|
-
- Use `ctx.log()` for observability
|
|
734
|
-
- Implement exponential backoff for retries
|
|
735
|
-
|
|
736
|
-
**Solution** available in [Module 8: Best Practices](./platforms-versori-08-best-practices.md#practice-solutions)
|
|
737
|
-
|
|
738
|
-
---
|
|
739
|
-
|
|
740
|
-
## Next Steps
|
|
741
|
-
|
|
742
|
-
Now that you understand authentication and connections, let's explore different workflow types.
|
|
743
|
-
|
|
744
|
-
Continue to [Module 4: Workflows →](./platforms-versori-04-workflows.md) to learn about HTTP, webhooks, and scheduled workflows.
|
|
745
|
-
|
|
746
|
-
---
|
|
747
|
-
|
|
748
|
-
## Related Documentation
|
|
749
|
-
|
|
750
|
-
- [Module 2: Quick Start](./platforms-versori-02-quick-start.md) - Your first workflow
|
|
751
|
-
- [Module 4: Workflows](./platforms-versori-04-workflows.md) - Workflow types
|
|
752
|
-
- [Module 5: Connections](./platforms-versori-05-connections.md) - Advanced connection patterns
|
|
753
|
-
- [API Reference](../../../../02-CORE-GUIDES/api-reference/api-reference-readme.md) - Complete SDK API
|
|
754
|
-
|
|
755
|
-
---
|
|
756
|
-
|
|
757
|
-
[← Previous: Module 2](./platforms-versori-02-quick-start.md) | [Back to Guide](../platforms-versori-readme.md) | [Next: Module 4: Workflows →](./platforms-versori-04-workflows.md)
|
|
1
|
+
# Module 3: Authentication & Connections
|
|
2
|
+
|
|
3
|
+
[← Back to Versori Platform Guide](../platforms-versori-readme.md)
|
|
4
|
+
|
|
5
|
+
**Module 3 of 8** | **Level**: Beginner | **Time**: 35 minutes
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Learning Objectives
|
|
10
|
+
|
|
11
|
+
By the end of this module, you will:
|
|
12
|
+
- ✅ Understand OAuth2 authentication in Versori
|
|
13
|
+
- ✅ Configure Fluent Commerce connections in Versori UI
|
|
14
|
+
- ✅ Use `createClient()` with Versori context
|
|
15
|
+
- ✅ Understand FluentVersoriClient vs FluentClient
|
|
16
|
+
- ✅ Access connection credentials and metadata
|
|
17
|
+
- ✅ Handle authentication errors
|
|
18
|
+
- ✅ Implement security best practices
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## OAuth2 in Versori Platform
|
|
23
|
+
|
|
24
|
+
Versori manages OAuth2 credentials securely through **Connections**. Your code never handles raw credentials.
|
|
25
|
+
|
|
26
|
+
### Key Benefits
|
|
27
|
+
|
|
28
|
+
- **No credential management** in code - Versori handles token storage and refresh
|
|
29
|
+
- **Automatic token refresh** when expired - transparent to your code
|
|
30
|
+
- **Secure storage** in Versori platform - encrypted at rest
|
|
31
|
+
- **Environment-specific** configs (dev/staging/prod) - separate credentials per environment
|
|
32
|
+
- **Audit logging** of API calls - full traceability
|
|
33
|
+
- **Connection reuse** across workflows - configure once, use everywhere
|
|
34
|
+
|
|
35
|
+
### How Authentication Works
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
39
|
+
│ Versori Platform │
|
|
40
|
+
│ │
|
|
41
|
+
│ ┌──────────────┐ ┌──────────────┐ │
|
|
42
|
+
│ │ Workflow │──ctx.fetch()──→ │ Connection │ │
|
|
43
|
+
│ │ │ │ (OAuth2) │ │
|
|
44
|
+
│ └──────────────┘ └──────┬───────┘ │
|
|
45
|
+
│ │ │
|
|
46
|
+
└───────────────────────────────────────────┼─────────────────┘
|
|
47
|
+
│
|
|
48
|
+
│ Managed Auth
|
|
49
|
+
↓
|
|
50
|
+
┌──────────────────────────┐
|
|
51
|
+
│ Fluent Commerce API │
|
|
52
|
+
│ (api.fluentcommerce.com)│
|
|
53
|
+
└──────────────────────────┘
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Key Points**:
|
|
57
|
+
1. Workflows use `ctx.fetch()` - Versori injects authentication automatically
|
|
58
|
+
2. Connection stores OAuth2 credentials - client ID, client secret
|
|
59
|
+
3. Platform handles token lifecycle - fetch, refresh, retry on 401
|
|
60
|
+
4. Your code never sees raw credentials - only uses authenticated fetch
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Configuring Fluent Commerce Connection
|
|
65
|
+
|
|
66
|
+
### Step 1: Access Connections in Versori UI
|
|
67
|
+
|
|
68
|
+
1. Log in to Versori dashboard
|
|
69
|
+
2. Navigate to **Connections** tab (left sidebar)
|
|
70
|
+
3. Click **"Add Connection"** button
|
|
71
|
+
|
|
72
|
+
### Step 2: Connection Configuration
|
|
73
|
+
|
|
74
|
+
**Basic Details**:
|
|
75
|
+
```
|
|
76
|
+
Name: fluent_commerce
|
|
77
|
+
Description: Fluent Commerce Production API
|
|
78
|
+
Type: Custom OAuth2
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**OAuth2 Settings**:
|
|
82
|
+
```
|
|
83
|
+
Auth URL: https://api.fluentcommerce.com/oauth/token
|
|
84
|
+
Token URL: https://api.fluentcommerce.com/oauth/token
|
|
85
|
+
Grant Type: client_credentials
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Client Credentials**:
|
|
89
|
+
```
|
|
90
|
+
Client ID: [Your Fluent OAuth2 Client ID]
|
|
91
|
+
Client Secret: [Your Fluent OAuth2 Client Secret]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**API Configuration**:
|
|
95
|
+
```
|
|
96
|
+
Base URL: https://api.fluentcommerce.com
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Custom Parameters** (JSON) - **Optional:**
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"retailerId": "1"
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Note:** `retailerId` is only needed if you're using Job API or Event API. For GraphQL queries only, you can omit it. If your Versori version doesn't support Custom Parameters, use `client.setRetailerId('1')` after creating the client.
|
|
107
|
+
|
|
108
|
+
**See complete retailerId guide below or:** [Complete retailerId Configuration Guide](../../../../00-START-HERE/retailerid-configuration.md)
|
|
109
|
+
|
|
110
|
+
### Step 3: Test Connection
|
|
111
|
+
|
|
112
|
+
Click **"Test Connection"** to verify:
|
|
113
|
+
- OAuth2 token can be fetched
|
|
114
|
+
- Base URL is accessible
|
|
115
|
+
- Credentials are correct
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Using createClient() with Versori
|
|
120
|
+
|
|
121
|
+
### Basic Usage
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import { http } from '@versori/run';
|
|
125
|
+
import { createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
126
|
+
|
|
127
|
+
export const workflow = http('name', {
|
|
128
|
+
connection: 'fluent_commerce'
|
|
129
|
+
}, async (ctx) => {
|
|
130
|
+
// Create client from Versori context
|
|
131
|
+
const client = await createClient(ctx);
|
|
132
|
+
|
|
133
|
+
// Use client - authentication is automatic
|
|
134
|
+
const result = await client.graphql({
|
|
135
|
+
query: `query { products(first: 10) { edges { node { id ref } } } }`
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return result.data;
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### What `createClient()` Does
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// Internally, createClient() detects Versori context:
|
|
146
|
+
export async function createClient(ctx: HttpContext): Promise<FluentVersoriClient> {
|
|
147
|
+
// 1. Detects runtime (Versori vs Node.js/Deno)
|
|
148
|
+
// 2. Creates appropriate client type
|
|
149
|
+
// 3. Extracts retailerId from connection variables or URL
|
|
150
|
+
// 4. Returns configured client
|
|
151
|
+
|
|
152
|
+
return FluentVersoriClient.fromContext(ctx);
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Key Detection Logic**:
|
|
157
|
+
- Checks for `ctx.fetch` (Versori-specific)
|
|
158
|
+
- Checks for `ctx.log` (Versori logging)
|
|
159
|
+
- Checks for `ctx.baseUrl` (connection base URL)
|
|
160
|
+
- Falls back to standalone mode if not Versori
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## FluentVersoriClient vs FluentClient
|
|
165
|
+
|
|
166
|
+
### Architecture Comparison
|
|
167
|
+
|
|
168
|
+
| Feature | FluentVersoriClient | FluentClient |
|
|
169
|
+
|---------|---------------------|--------------|
|
|
170
|
+
| **Runtime** | Versori platform only | Node.js, Deno, standalone |
|
|
171
|
+
| **Authentication** | Platform-managed (ctx.fetch) | Manual OAuth2 (clientId/secret) |
|
|
172
|
+
| **Token Management** | Automatic (Versori) | Manual (AuthService) |
|
|
173
|
+
| **Base URL** | From connection config | Passed in constructor |
|
|
174
|
+
| **Fetch Implementation** | `ctx.fetch()` (Versori) | `fetch()` (standard) |
|
|
175
|
+
| **Logging** | `ctx.log` (platform) | Custom logger or console |
|
|
176
|
+
| **KV Storage** | `ctx.openKv()` available | External KV required |
|
|
177
|
+
|
|
178
|
+
### When to Use Each
|
|
179
|
+
|
|
180
|
+
**Use FluentVersoriClient** (via `createClient(ctx)`):
|
|
181
|
+
- ✅ Running on Versori platform (webhooks, scheduled, HTTP workflows)
|
|
182
|
+
- ✅ Want automatic authentication
|
|
183
|
+
- ✅ Need Versori KV storage integration
|
|
184
|
+
- ✅ Platform logging required
|
|
185
|
+
|
|
186
|
+
**Use FluentClient** (standalone):
|
|
187
|
+
- ✅ Running Node.js scripts locally
|
|
188
|
+
- ✅ Running in Deno
|
|
189
|
+
- ✅ Custom environments (Lambda, Docker, etc.)
|
|
190
|
+
- ✅ Testing with mock credentials
|
|
191
|
+
|
|
192
|
+
### Code Example: Both Approaches
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
// ✅ Versori Platform (FluentVersoriClient via createClient)
|
|
196
|
+
import { http } from '@versori/run';
|
|
197
|
+
import { createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
198
|
+
|
|
199
|
+
export const versoriWorkflow = http('versori', {
|
|
200
|
+
connection: 'fluent_commerce'
|
|
201
|
+
}, async (ctx) => {
|
|
202
|
+
const client = await createClient(ctx); // Auto-detects Versori
|
|
203
|
+
return await client.graphql({ query: '...' });
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// ✅ Standalone Node.js (FluentClient directly)
|
|
207
|
+
import { FluentClient } from '@fluentcommerce/fc-connect-sdk';
|
|
208
|
+
|
|
209
|
+
const client = new FluentClient({
|
|
210
|
+
baseUrl: 'https://api.fluentcommerce.com',
|
|
211
|
+
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
212
|
+
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
213
|
+
username: process.env.FLUENT_USERNAME,
|
|
214
|
+
password: process.env.FLUENT_PASSWORD,
|
|
215
|
+
retailerId: '1'
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
const result = await client.graphql({ query: '...' });
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Accessing Connection Credentials
|
|
224
|
+
|
|
225
|
+
### Connection Variables
|
|
226
|
+
|
|
227
|
+
Versori connections can store custom variables accessible in workflows:
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
import { http } from '@versori/run';
|
|
231
|
+
|
|
232
|
+
export const accessConnectionVars = http('access-vars', {
|
|
233
|
+
connection: 'fluent_commerce'
|
|
234
|
+
}, async (ctx) => {
|
|
235
|
+
// Access connection variables
|
|
236
|
+
const connectionVars = ctx.connectionVariables || {};
|
|
237
|
+
|
|
238
|
+
const retailerId = connectionVars.retailerId || '1';
|
|
239
|
+
const environment = connectionVars.environment || 'production';
|
|
240
|
+
|
|
241
|
+
ctx.log('info', 'Connection variables', {
|
|
242
|
+
retailerId,
|
|
243
|
+
environment
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
return { retailerId, environment };
|
|
247
|
+
});
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Base URL Access
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
export const accessBaseUrl = http('access-url', {
|
|
254
|
+
connection: 'fluent_commerce'
|
|
255
|
+
}, async (ctx) => {
|
|
256
|
+
// Base URL may be a Promise
|
|
257
|
+
const baseUrl = await ctx.baseUrl;
|
|
258
|
+
|
|
259
|
+
ctx.log('info', 'Connection base URL', { baseUrl });
|
|
260
|
+
|
|
261
|
+
return { baseUrl };
|
|
262
|
+
});
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Retailer ID Extraction
|
|
266
|
+
|
|
267
|
+
The SDK automatically extracts retailer ID from:
|
|
268
|
+
|
|
269
|
+
1. **Connection variables** (highest priority):
|
|
270
|
+
```json
|
|
271
|
+
{ "retailerId": "1" }
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
2. **URL path** (fallback):
|
|
275
|
+
```
|
|
276
|
+
https://api.fluentcommerce.com/graphql/1
|
|
277
|
+
↑
|
|
278
|
+
retailerId
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
3. **Manual override**:
|
|
282
|
+
```typescript
|
|
283
|
+
const client = await createClient(ctx);
|
|
284
|
+
client.setRetailerId('2'); // Override if needed
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## retailerId Configuration (v0.1.30+)
|
|
290
|
+
|
|
291
|
+
Starting with v0.1.30, `retailerId` is **optional** for GraphQL queries but **required** for Job and Event APIs.
|
|
292
|
+
|
|
293
|
+
### When retailerId is Required
|
|
294
|
+
|
|
295
|
+
| API Type | retailerId Required? | Validation |
|
|
296
|
+
|----------|---------------------|------------|
|
|
297
|
+
| GraphQL Queries (`client.graphql()`) | ❌ Optional | Not validated |
|
|
298
|
+
| GraphQL Mutations (`client.graphql()`) | ❌ Optional | Not validated |
|
|
299
|
+
| Job API (`createJob()`, `getJob()`) | ✅ Required | Fail-fast at method call |
|
|
300
|
+
| Event API (`sendEvent()`) | ✅ Required | Fail-fast at method call |
|
|
301
|
+
| Batch API (`sendBatch()`) | ✅ Required | Fail-fast at method call |
|
|
302
|
+
|
|
303
|
+
### Configuration Patterns
|
|
304
|
+
|
|
305
|
+
**Option 1: Set at Client Creation (Recommended)**
|
|
306
|
+
```typescript
|
|
307
|
+
import { createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
308
|
+
|
|
309
|
+
export const inventorySync = http('POST', '/sync', async (ctx) => {
|
|
310
|
+
// retailerId set once at client creation
|
|
311
|
+
const client = await createClient({
|
|
312
|
+
context: ctx,
|
|
313
|
+
retailerId: ctx.connectionVariables?.RETAILER_ID,
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// Works for all APIs
|
|
317
|
+
await client.createJob({ name: 'inventory-sync' });
|
|
318
|
+
await client.graphql({ query: '...' });
|
|
319
|
+
|
|
320
|
+
return { success: true };
|
|
321
|
+
});
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
**Option 2: Set Dynamically (Multi-Tenant)**
|
|
325
|
+
```typescript
|
|
326
|
+
export const multiTenantSync = http('POST', '/sync/:retailerId', async (ctx) => {
|
|
327
|
+
const client = await createClient({ context: ctx });
|
|
328
|
+
|
|
329
|
+
// Set retailerId from URL parameter
|
|
330
|
+
const retailerId = ctx.params?.retailerId;
|
|
331
|
+
client.setRetailerId(retailerId);
|
|
332
|
+
|
|
333
|
+
await client.createJob({ name: 'inventory-sync' });
|
|
334
|
+
|
|
335
|
+
return { success: true };
|
|
336
|
+
});
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
**Option 3: No retailerId (GraphQL Only)**
|
|
340
|
+
```typescript
|
|
341
|
+
export const queryProducts = http('POST', '/query', async (ctx) => {
|
|
342
|
+
// No retailerId needed for GraphQL queries
|
|
343
|
+
const client = await createClient({ context: ctx });
|
|
344
|
+
|
|
345
|
+
const result = await client.graphql({
|
|
346
|
+
query: `query { products { edges { node { id ref } } } }`
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
return result.data;
|
|
350
|
+
});
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Error Handling
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
export const withRetailerIdValidation = http('POST', '/sync', {
|
|
357
|
+
connection: 'fluent_commerce'
|
|
358
|
+
}, async (ctx) => {
|
|
359
|
+
try {
|
|
360
|
+
const client = await createClient({ context: ctx });
|
|
361
|
+
|
|
362
|
+
// Try to call Job API
|
|
363
|
+
const job = await client.createJob({ name: 'inventory-sync' });
|
|
364
|
+
|
|
365
|
+
return { success: true, jobId: job.id };
|
|
366
|
+
|
|
367
|
+
} catch (error) {
|
|
368
|
+
if (error instanceof Error && error.message.includes('retailerId is required')) {
|
|
369
|
+
// Handle missing retailerId
|
|
370
|
+
ctx.log('error', 'retailerId not configured', {
|
|
371
|
+
error: error.message
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
return {
|
|
375
|
+
success: false,
|
|
376
|
+
error: 'retailerId configuration missing',
|
|
377
|
+
details: 'Configure retailerId in connection variables or use client.setRetailerId()'
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
throw error; // Re-throw other errors
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
**See Also:** [Complete retailerId Configuration Guide](../../../../00-START-HERE/retailerid-configuration.md) for all patterns and use cases.
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Authentication Error Handling
|
|
391
|
+
|
|
392
|
+
### Common Authentication Errors
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
import { http } from '@versori/run';
|
|
396
|
+
import { createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
397
|
+
|
|
398
|
+
export const errorHandling = http('error-handling', {
|
|
399
|
+
connection: 'fluent_commerce'
|
|
400
|
+
}, async (ctx) => {
|
|
401
|
+
try {
|
|
402
|
+
const client = await createClient(ctx);
|
|
403
|
+
|
|
404
|
+
const result = await client.graphql({
|
|
405
|
+
query: `query { products(first: 10) { edges { node { id } } } }`
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
return { success: true, data: result.data };
|
|
409
|
+
|
|
410
|
+
} catch (error) {
|
|
411
|
+
// Log error details
|
|
412
|
+
ctx.log('error', 'GraphQL request failed', {
|
|
413
|
+
error: error instanceof Error ? error.message : String(error),
|
|
414
|
+
name: error instanceof Error ? error.name : 'Unknown'
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
// Check error type
|
|
418
|
+
if (error instanceof Error) {
|
|
419
|
+
// Authentication errors
|
|
420
|
+
if (error.message.includes('401') || error.message.includes('Unauthorized')) {
|
|
421
|
+
return {
|
|
422
|
+
success: false,
|
|
423
|
+
error: 'Authentication failed - check connection credentials',
|
|
424
|
+
retryable: false
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Token refresh errors
|
|
429
|
+
if (error.message.includes('token') || error.message.includes('expired')) {
|
|
430
|
+
return {
|
|
431
|
+
success: false,
|
|
432
|
+
error: 'Token expired - Versori will retry automatically',
|
|
433
|
+
retryable: true
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Network errors
|
|
438
|
+
if (error.message.includes('ECONNREFUSED') || error.message.includes('timeout')) {
|
|
439
|
+
return {
|
|
440
|
+
success: false,
|
|
441
|
+
error: 'Network error - Fluent API unreachable',
|
|
442
|
+
retryable: true
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Generic error response
|
|
448
|
+
return {
|
|
449
|
+
success: false,
|
|
450
|
+
error: 'Request failed',
|
|
451
|
+
details: error instanceof Error ? error.message : String(error)
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Error Response Patterns
|
|
458
|
+
|
|
459
|
+
| HTTP Status | Meaning | Versori Behavior | Your Action |
|
|
460
|
+
|-------------|---------|------------------|-------------|
|
|
461
|
+
| **401** | Unauthorized | Refreshes token, retries | Log error if retry fails |
|
|
462
|
+
| **403** | Forbidden | No retry | Check retailerId, permissions |
|
|
463
|
+
| **429** | Rate limited | Retries with backoff | Reduce request rate |
|
|
464
|
+
| **500** | Server error | May retry | Log for investigation |
|
|
465
|
+
| **503** | Service unavailable | Retries | Wait for service recovery |
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## Token Management (Versori)
|
|
470
|
+
|
|
471
|
+
### Automatic Token Refresh
|
|
472
|
+
|
|
473
|
+
Versori handles token lifecycle automatically:
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
// You write this:
|
|
477
|
+
const result = await client.graphql({ query: '...' });
|
|
478
|
+
|
|
479
|
+
// Versori does this behind the scenes:
|
|
480
|
+
// 1. Check if token exists and is valid
|
|
481
|
+
// 2. If expired, fetch new token from OAuth2 endpoint
|
|
482
|
+
// 3. Retry original request with fresh token
|
|
483
|
+
// 4. Return result to your code
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
**No manual token management needed!**
|
|
487
|
+
|
|
488
|
+
### Token Debugging
|
|
489
|
+
|
|
490
|
+
If authentication fails, check Versori logs:
|
|
491
|
+
|
|
492
|
+
```typescript
|
|
493
|
+
export const debugAuth = http('debug-auth', {
|
|
494
|
+
connection: 'fluent_commerce'
|
|
495
|
+
}, async (ctx) => {
|
|
496
|
+
ctx.log('info', 'Connection details', {
|
|
497
|
+
hasBaseUrl: !!ctx.baseUrl,
|
|
498
|
+
hasFetch: typeof ctx.fetch === 'function',
|
|
499
|
+
hasLog: typeof ctx.log === 'function',
|
|
500
|
+
connectionVars: ctx.connectionVariables || {}
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
// Test authentication
|
|
504
|
+
try {
|
|
505
|
+
const client = await createClient(ctx);
|
|
506
|
+
|
|
507
|
+
// Simple query to test auth
|
|
508
|
+
await client.graphql({
|
|
509
|
+
query: `query { __typename }`
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
ctx.log('info', 'Authentication successful');
|
|
513
|
+
return { authOk: true };
|
|
514
|
+
|
|
515
|
+
} catch (error) {
|
|
516
|
+
ctx.log('error', 'Authentication failed', {
|
|
517
|
+
error: error instanceof Error ? error.message : String(error)
|
|
518
|
+
});
|
|
519
|
+
return { authOk: false, error: String(error) };
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
## Security Best Practices
|
|
527
|
+
|
|
528
|
+
### 1. Never Log Credentials
|
|
529
|
+
|
|
530
|
+
```typescript
|
|
531
|
+
// ❌ WRONG - Logs sensitive data
|
|
532
|
+
ctx.log('info', 'Client config', {
|
|
533
|
+
clientId: connectionVars.clientId,
|
|
534
|
+
clientSecret: connectionVars.clientSecret // DON'T DO THIS
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
// ✅ CORRECT - Log safely
|
|
538
|
+
ctx.log('info', 'Client config', {
|
|
539
|
+
hasClientId: !!connectionVars.clientId,
|
|
540
|
+
hasClientSecret: !!connectionVars.clientSecret
|
|
541
|
+
});
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### 2. Use Environment-Specific Connections
|
|
545
|
+
|
|
546
|
+
```
|
|
547
|
+
Connections:
|
|
548
|
+
- fluent_commerce_dev (dev environment)
|
|
549
|
+
- fluent_commerce_staging (staging environment)
|
|
550
|
+
- fluent_commerce_prod (production environment)
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
```typescript
|
|
554
|
+
// Select connection based on environment
|
|
555
|
+
const connectionName = process.env.ENV === 'production'
|
|
556
|
+
? 'fluent_commerce_prod'
|
|
557
|
+
: 'fluent_commerce_dev';
|
|
558
|
+
|
|
559
|
+
export const workflow = http('workflow', {
|
|
560
|
+
connection: connectionName
|
|
561
|
+
}, async (ctx) => {
|
|
562
|
+
// ...
|
|
563
|
+
});
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
### 3. Validate RetailerID
|
|
567
|
+
|
|
568
|
+
```typescript
|
|
569
|
+
export const validateRetailer = http('validate', {
|
|
570
|
+
connection: 'fluent_commerce'
|
|
571
|
+
}, async (ctx) => {
|
|
572
|
+
const client = await createClient(ctx);
|
|
573
|
+
const retailerId = client.getRetailerId();
|
|
574
|
+
|
|
575
|
+
// Validate retailer ID
|
|
576
|
+
if (!retailerId || retailerId === '') {
|
|
577
|
+
ctx.log('error', 'Retailer ID not configured');
|
|
578
|
+
throw new Error('Retailer ID missing - check connection configuration');
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// Validate format (numeric)
|
|
582
|
+
if (!/^\d+$/.test(retailerId)) {
|
|
583
|
+
ctx.log('error', 'Invalid retailer ID format', { retailerId });
|
|
584
|
+
throw new Error('Retailer ID must be numeric');
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
return { retailerId, valid: true };
|
|
588
|
+
});
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
### 4. Implement Request Timeouts
|
|
592
|
+
|
|
593
|
+
```typescript
|
|
594
|
+
export const withTimeout = http('with-timeout', {
|
|
595
|
+
connection: 'fluent_commerce'
|
|
596
|
+
}, async (ctx) => {
|
|
597
|
+
const client = await createClient(ctx);
|
|
598
|
+
|
|
599
|
+
// Implement timeout for long-running queries
|
|
600
|
+
const timeoutMs = 30000; // 30 seconds
|
|
601
|
+
|
|
602
|
+
const result = await Promise.race([
|
|
603
|
+
client.graphql({ query: '...' }),
|
|
604
|
+
new Promise((_, reject) =>
|
|
605
|
+
setTimeout(() => reject(new Error('Request timeout')), timeoutMs)
|
|
606
|
+
)
|
|
607
|
+
]);
|
|
608
|
+
|
|
609
|
+
return result;
|
|
610
|
+
});
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
## Advanced Connection Patterns
|
|
616
|
+
|
|
617
|
+
### Multi-Retailer Workflows
|
|
618
|
+
|
|
619
|
+
```typescript
|
|
620
|
+
import { http } from '@versori/run';
|
|
621
|
+
import { createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
622
|
+
|
|
623
|
+
export const multiRetailer = http('multi-retailer', {
|
|
624
|
+
connection: 'fluent_commerce'
|
|
625
|
+
}, async (ctx) => {
|
|
626
|
+
const retailers = ['1', '2', '3'];
|
|
627
|
+
const results = [];
|
|
628
|
+
|
|
629
|
+
for (const retailerId of retailers) {
|
|
630
|
+
const client = await createClient(ctx);
|
|
631
|
+
client.setRetailerId(retailerId);
|
|
632
|
+
|
|
633
|
+
try {
|
|
634
|
+
const result = await client.graphql({
|
|
635
|
+
query: `query { products(first: 10) { edges { node { id ref } } } }`
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
results.push({
|
|
639
|
+
retailerId,
|
|
640
|
+
success: true,
|
|
641
|
+
productCount: result.data.products.edges.length
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
} catch (error) {
|
|
645
|
+
ctx.log('error', 'Query failed for retailer', {
|
|
646
|
+
retailerId,
|
|
647
|
+
error: error instanceof Error ? error.message : String(error)
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
results.push({
|
|
651
|
+
retailerId,
|
|
652
|
+
success: false,
|
|
653
|
+
error: String(error)
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
return { results };
|
|
659
|
+
});
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
### Connection Health Check
|
|
663
|
+
|
|
664
|
+
```typescript
|
|
665
|
+
export const healthCheck = http('health-check', {
|
|
666
|
+
connection: 'fluent_commerce'
|
|
667
|
+
}, async (ctx) => {
|
|
668
|
+
const startTime = Date.now();
|
|
669
|
+
|
|
670
|
+
try {
|
|
671
|
+
const client = await createClient(ctx);
|
|
672
|
+
|
|
673
|
+
// Test basic connectivity
|
|
674
|
+
await client.graphql({
|
|
675
|
+
query: `query { __typename }`
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
const duration = Date.now() - startTime;
|
|
679
|
+
|
|
680
|
+
ctx.log('info', 'Health check passed', { durationMs: duration });
|
|
681
|
+
|
|
682
|
+
return {
|
|
683
|
+
healthy: true,
|
|
684
|
+
durationMs: duration,
|
|
685
|
+
timestamp: new Date().toISOString()
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
} catch (error) {
|
|
689
|
+
const duration = Date.now() - startTime;
|
|
690
|
+
|
|
691
|
+
ctx.log('error', 'Health check failed', {
|
|
692
|
+
durationMs: duration,
|
|
693
|
+
error: error instanceof Error ? error.message : String(error)
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
return {
|
|
697
|
+
healthy: false,
|
|
698
|
+
durationMs: duration,
|
|
699
|
+
error: String(error),
|
|
700
|
+
timestamp: new Date().toISOString()
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
## Key Takeaways
|
|
709
|
+
|
|
710
|
+
- 🎯 **Versori manages OAuth2** - Your code never handles credentials
|
|
711
|
+
- 🎯 **createClient(ctx)** - Universal factory auto-detects Versori context
|
|
712
|
+
- 🎯 **FluentVersoriClient** - Platform-optimized client using ctx.fetch
|
|
713
|
+
- 🎯 **FluentClient** - Standalone client for Node.js/Deno with manual OAuth2
|
|
714
|
+
- 🎯 **Connection variables** - Store retailerId and custom config
|
|
715
|
+
- 🎯 **Automatic token refresh** - Versori handles token lifecycle
|
|
716
|
+
- 🎯 **Error handling** - Log errors, check status codes, implement retries
|
|
717
|
+
- 🎯 **Security** - Never log credentials, use environment-specific connections
|
|
718
|
+
|
|
719
|
+
---
|
|
720
|
+
|
|
721
|
+
## Practice Exercise
|
|
722
|
+
|
|
723
|
+
Create a workflow that:
|
|
724
|
+
1. Uses `createClient()` to create authenticated client
|
|
725
|
+
2. Validates retailer ID is configured
|
|
726
|
+
3. Implements proper error handling for auth failures
|
|
727
|
+
4. Logs connection health metrics
|
|
728
|
+
5. Handles multiple retries on transient errors
|
|
729
|
+
|
|
730
|
+
**Hints**:
|
|
731
|
+
- Use `try/catch` for error handling
|
|
732
|
+
- Check `client.getRetailerId()` for validation
|
|
733
|
+
- Use `ctx.log()` for observability
|
|
734
|
+
- Implement exponential backoff for retries
|
|
735
|
+
|
|
736
|
+
**Solution** available in [Module 8: Best Practices](./platforms-versori-08-best-practices.md#practice-solutions)
|
|
737
|
+
|
|
738
|
+
---
|
|
739
|
+
|
|
740
|
+
## Next Steps
|
|
741
|
+
|
|
742
|
+
Now that you understand authentication and connections, let's explore different workflow types.
|
|
743
|
+
|
|
744
|
+
Continue to [Module 4: Workflows →](./platforms-versori-04-workflows.md) to learn about HTTP, webhooks, and scheduled workflows.
|
|
745
|
+
|
|
746
|
+
---
|
|
747
|
+
|
|
748
|
+
## Related Documentation
|
|
749
|
+
|
|
750
|
+
- [Module 2: Quick Start](./platforms-versori-02-quick-start.md) - Your first workflow
|
|
751
|
+
- [Module 4: Workflows](./platforms-versori-04-workflows.md) - Workflow types
|
|
752
|
+
- [Module 5: Connections](./platforms-versori-05-connections.md) - Advanced connection patterns
|
|
753
|
+
- [API Reference](../../../../02-CORE-GUIDES/api-reference/api-reference-readme.md) - Complete SDK API
|
|
754
|
+
|
|
755
|
+
---
|
|
756
|
+
|
|
757
|
+
[← Previous: Module 2](./platforms-versori-02-quick-start.md) | [Back to Guide](../platforms-versori-readme.md) | [Next: Module 4: Workflows →](./platforms-versori-04-workflows.md)
|