@fluentcommerce/fc-connect-sdk 0.1.54 → 0.1.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +11 -0
- package/dist/cjs/clients/fluent-client.js +13 -6
- package/dist/cjs/utils/pagination-helpers.js +38 -2
- package/dist/cjs/versori/fluent-versori-client.js +11 -5
- package/dist/esm/clients/fluent-client.js +13 -6
- 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/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 -520
- 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
- package/docs/02-CORE-GUIDES/api-reference/cli-profile-integration.md +0 -377
|
@@ -1,525 +1,525 @@
|
|
|
1
|
-
# Module 2: Quick Start
|
|
2
|
-
|
|
3
|
-
**Level:** Beginner
|
|
4
|
-
**Estimated Time:** 15 minutes
|
|
5
|
-
|
|
6
|
-
## Overview
|
|
7
|
-
|
|
8
|
-
This module gets you started with webhook validation immediately. You'll learn the basic usage pattern, auto-detection features, and how to validate your first webhook in just a few lines of code.
|
|
9
|
-
|
|
10
|
-
## Learning Objectives
|
|
11
|
-
|
|
12
|
-
By the end of this module, you will:
|
|
13
|
-
- Implement basic webhook validation
|
|
14
|
-
- Understand the auto-detection pattern
|
|
15
|
-
- Know how to handle validation results
|
|
16
|
-
- Test webhook validation locally
|
|
17
|
-
- Build a complete working example
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## Basic Validation Pattern
|
|
22
|
-
|
|
23
|
-
### Minimal Example
|
|
24
|
-
|
|
25
|
-
```typescript
|
|
26
|
-
import {
|
|
27
|
-
WebhookValidationService,
|
|
28
|
-
createConsoleLogger
|
|
29
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
30
|
-
|
|
31
|
-
// 1. Initialize logging
|
|
32
|
-
const logger = createConsoleLogger();
|
|
33
|
-
|
|
34
|
-
// 2. Create validator
|
|
35
|
-
const validator = new WebhookValidationService({
|
|
36
|
-
strictValidation: true // Throw errors on validation failure
|
|
37
|
-
}, logger);
|
|
38
|
-
|
|
39
|
-
// 3. Validate webhook (auto-detects signature type)
|
|
40
|
-
const result = await validator.validateWebhook(
|
|
41
|
-
rawBody, // Raw request body as string
|
|
42
|
-
headers, // Request headers object
|
|
43
|
-
publicKey // Public key from Fluent Commerce
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
// 4. Check result
|
|
47
|
-
if (!result.isValid) {
|
|
48
|
-
console.error('Invalid webhook:', result.error);
|
|
49
|
-
return { statusCode: 401, body: 'Invalid signature' };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// 5. Process valid webhook
|
|
53
|
-
console.log('Valid webhook using:', result.algorithm);
|
|
54
|
-
const data = JSON.parse(rawBody);
|
|
55
|
-
// ... your business logic here
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
**That's the complete pattern.** The SDK handles algorithm detection, signature extraction, and cryptographic verification automatically.
|
|
59
|
-
|
|
60
|
-
> **Note:** `validateWebhook()` is the **ONLY** FluentClient method that does NOT require `retailerId` configuration. This is because webhook validation is performed using RSA public key cryptography and does not require API authentication.
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## Understanding the Parameters
|
|
65
|
-
|
|
66
|
-
### 1. Raw Body (Critical)
|
|
67
|
-
|
|
68
|
-
**Must be the exact string** received in the webhook request:
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
// ✅ CORRECT - Raw string body
|
|
72
|
-
const rawBody = await request.text();
|
|
73
|
-
const rawBody = req.body.toString(); // If using express.raw()
|
|
74
|
-
|
|
75
|
-
// ❌ WRONG - Parsed or modified body
|
|
76
|
-
const rawBody = JSON.stringify(req.body); // Don't stringify parsed JSON
|
|
77
|
-
const rawBody = req.body.data; // Don't use parsed fields
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
**Why this matters**: The signature is created from the exact byte sequence of the original body. Any modification (even whitespace changes) breaks validation.
|
|
81
|
-
|
|
82
|
-
### 2. Headers Object
|
|
83
|
-
|
|
84
|
-
Standard HTTP headers object with signature header:
|
|
85
|
-
|
|
86
|
-
```typescript
|
|
87
|
-
// Example headers object
|
|
88
|
-
const headers = {
|
|
89
|
-
'fluent-signature': 'iQEcBAABCAAGBQJgm...',
|
|
90
|
-
'content-type': 'application/json',
|
|
91
|
-
'user-agent': 'Fluent-Webhook/1.0'
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
// From Express.js
|
|
95
|
-
const headers = req.headers;
|
|
96
|
-
|
|
97
|
-
// From Versori (use ctx.request() to access Express request)
|
|
98
|
-
const req = ctx.request();
|
|
99
|
-
const headers = req?.headers || {};
|
|
100
|
-
|
|
101
|
-
// From fetch API
|
|
102
|
-
const headers = Object.fromEntries(request.headers.entries());
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
**Signature headers** the SDK looks for (in priority order):
|
|
106
|
-
1. `fluent-signature` (SHA512withRSA)
|
|
107
|
-
2. `flex.signature` (MD5withRSA)
|
|
108
|
-
|
|
109
|
-
### 3. Public Key
|
|
110
|
-
|
|
111
|
-
Public key from Fluent Commerce for your environment:
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
// From environment variable (recommended)
|
|
115
|
-
const publicKey = process.env.FLUENT_WEBHOOK_PUBLIC_KEY;
|
|
116
|
-
|
|
117
|
-
// From Versori variable
|
|
118
|
-
const publicKey = ctx.vars.FLUENT_WEBHOOK_PUBLIC_KEY;
|
|
119
|
-
|
|
120
|
-
// From configuration
|
|
121
|
-
const publicKey = config.fluent.webhookPublicKey;
|
|
122
|
-
|
|
123
|
-
// Hardcoded (development only - not recommended)
|
|
124
|
-
const publicKey = "-----BEGIN PUBLIC KEY-----\nMIIBIj...\n-----END PUBLIC KEY-----";
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
**Formats accepted**:
|
|
128
|
-
- Full PEM with headers: `-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----`
|
|
129
|
-
- Raw base64: `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...`
|
|
130
|
-
|
|
131
|
-
The SDK automatically adds PEM headers if missing.
|
|
132
|
-
|
|
133
|
-
---
|
|
134
|
-
|
|
135
|
-
## Auto-Detection in Action
|
|
136
|
-
|
|
137
|
-
The SDK automatically detects which signature algorithm to use:
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
// Webhook with SHA512 signature
|
|
141
|
-
const headers1 = {
|
|
142
|
-
'fluent-signature': 'abc123...',
|
|
143
|
-
'content-type': 'application/json'
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
const result1 = await validator.validateWebhook(rawBody, headers1, publicKey);
|
|
147
|
-
// result1.algorithm = 'SHA512withRSA'
|
|
148
|
-
|
|
149
|
-
// Webhook with MD5 signature (for Flex workflows)
|
|
150
|
-
const headers2 = {
|
|
151
|
-
'flex.signature': 'xyz789...',
|
|
152
|
-
'content-type': 'application/json'
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const result2 = await validator.validateWebhook(rawBody, headers2, publicKey);
|
|
156
|
-
// result2.algorithm = 'MD5withRSA'
|
|
157
|
-
|
|
158
|
-
// Webhook with no signature
|
|
159
|
-
const headers3 = {
|
|
160
|
-
'content-type': 'application/json'
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
const result3 = await validator.validateWebhook(rawBody, headers3, publicKey);
|
|
164
|
-
// result3.isValid = false
|
|
165
|
-
// result3.error = 'No signature header found'
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
**You don't need to specify the algorithm** - the SDK handles it automatically based on which header is present.
|
|
169
|
-
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
## Handling Validation Results
|
|
173
|
-
|
|
174
|
-
### Validation Result Structure
|
|
175
|
-
|
|
176
|
-
```typescript
|
|
177
|
-
interface WebhookValidationResult {
|
|
178
|
-
isValid: boolean; // true if signature verified successfully
|
|
179
|
-
algorithm: SignatureAlgorithm; // Which algorithm was used
|
|
180
|
-
error?: string; // Error message if validation failed
|
|
181
|
-
timestamp: Date; // When validation occurred
|
|
182
|
-
}
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
### Success Case
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
const result = await validator.validateWebhook(rawBody, headers, publicKey);
|
|
189
|
-
|
|
190
|
-
if (result.isValid) {
|
|
191
|
-
console.log(`Valid webhook using ${result.algorithm}`);
|
|
192
|
-
console.log(`Validated at ${result.timestamp.toISOString()}`);
|
|
193
|
-
|
|
194
|
-
// Safe to process webhook data
|
|
195
|
-
const data = JSON.parse(rawBody);
|
|
196
|
-
await processWebhookData(data);
|
|
197
|
-
|
|
198
|
-
return { statusCode: 200, body: 'Success' };
|
|
199
|
-
}
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
### Failure Case
|
|
203
|
-
|
|
204
|
-
```typescript
|
|
205
|
-
const result = await validator.validateWebhook(rawBody, headers, publicKey);
|
|
206
|
-
|
|
207
|
-
if (!result.isValid) {
|
|
208
|
-
console.error(`Validation failed: ${result.error}`);
|
|
209
|
-
console.error(`Attempted algorithm: ${result.algorithm}`);
|
|
210
|
-
|
|
211
|
-
// Log for security monitoring
|
|
212
|
-
logger.warn('Invalid webhook signature', {
|
|
213
|
-
error: result.error,
|
|
214
|
-
timestamp: result.timestamp,
|
|
215
|
-
headers: headers
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
// Return 401 Unauthorized
|
|
219
|
-
return { statusCode: 401, body: 'Invalid signature' };
|
|
220
|
-
}
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
## Complete Working Example
|
|
226
|
-
|
|
227
|
-
### Standalone Validation Script
|
|
228
|
-
|
|
229
|
-
```typescript
|
|
230
|
-
import {
|
|
231
|
-
WebhookValidationService,
|
|
232
|
-
SignatureAlgorithm,
|
|
233
|
-
createConsoleLogger
|
|
234
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
235
|
-
|
|
236
|
-
async function validateWebhook(
|
|
237
|
-
rawBody: string,
|
|
238
|
-
headers: Record<string, string>,
|
|
239
|
-
publicKey: string
|
|
240
|
-
): Promise<boolean> {
|
|
241
|
-
// Initialize logging
|
|
242
|
-
const logger = createConsoleLogger();
|
|
243
|
-
|
|
244
|
-
// Create validator with strict validation
|
|
245
|
-
const validator = new WebhookValidationService({
|
|
246
|
-
strictValidation: true
|
|
247
|
-
}, logger);
|
|
248
|
-
|
|
249
|
-
try {
|
|
250
|
-
// Validate webhook (auto-detects algorithm)
|
|
251
|
-
const result = await validator.validateWebhook(
|
|
252
|
-
rawBody,
|
|
253
|
-
headers,
|
|
254
|
-
publicKey
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
if (!result.isValid) {
|
|
258
|
-
logger.error('Webhook validation failed', {
|
|
259
|
-
error: result.error,
|
|
260
|
-
algorithm: result.algorithm,
|
|
261
|
-
timestamp: result.timestamp
|
|
262
|
-
});
|
|
263
|
-
return false;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
logger.info('Webhook validated successfully', {
|
|
267
|
-
algorithm: result.algorithm,
|
|
268
|
-
timestamp: result.timestamp
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
return true;
|
|
272
|
-
|
|
273
|
-
} catch (error) {
|
|
274
|
-
logger.error('Validation error', { error });
|
|
275
|
-
return false;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Usage
|
|
280
|
-
const isValid = await validateWebhook(
|
|
281
|
-
requestBody,
|
|
282
|
-
requestHeaders,
|
|
283
|
-
process.env.FLUENT_WEBHOOK_PUBLIC_KEY!
|
|
284
|
-
);
|
|
285
|
-
|
|
286
|
-
if (isValid) {
|
|
287
|
-
const webhookData = JSON.parse(requestBody);
|
|
288
|
-
console.log('Processing webhook:', webhookData.eventId);
|
|
289
|
-
// ... process webhook
|
|
290
|
-
} else {
|
|
291
|
-
console.error('Rejecting invalid webhook');
|
|
292
|
-
}
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
---
|
|
296
|
-
|
|
297
|
-
## Testing Validation
|
|
298
|
-
|
|
299
|
-
### Test with Sample Data
|
|
300
|
-
|
|
301
|
-
```typescript
|
|
302
|
-
import {
|
|
303
|
-
WebhookValidationService,
|
|
304
|
-
createConsoleLogger
|
|
305
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
306
|
-
|
|
307
|
-
async function testValidation() {
|
|
308
|
-
const logger = createConsoleLogger();
|
|
309
|
-
|
|
310
|
-
const validator = new WebhookValidationService({
|
|
311
|
-
strictValidation: false // Lenient for testing
|
|
312
|
-
}, logger);
|
|
313
|
-
|
|
314
|
-
// Sample webhook payload
|
|
315
|
-
const webhookBody = JSON.stringify({
|
|
316
|
-
eventId: 'evt_123',
|
|
317
|
-
entityType: 'ORDER',
|
|
318
|
-
entityId: 'order_456',
|
|
319
|
-
timestamp: new Date().toISOString(),
|
|
320
|
-
data: {
|
|
321
|
-
ref: 'ORD-123',
|
|
322
|
-
status: 'PLACED'
|
|
323
|
-
}
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
// Sample headers (get real signature from Fluent Commerce)
|
|
327
|
-
const webhookHeaders = {
|
|
328
|
-
'fluent-signature': 'YOUR_TEST_SIGNATURE_HERE',
|
|
329
|
-
'content-type': 'application/json'
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
const publicKey = process.env.FLUENT_WEBHOOK_PUBLIC_KEY!;
|
|
333
|
-
|
|
334
|
-
// Validate
|
|
335
|
-
const result = await validator.validateWebhook(
|
|
336
|
-
webhookBody,
|
|
337
|
-
webhookHeaders,
|
|
338
|
-
publicKey
|
|
339
|
-
);
|
|
340
|
-
|
|
341
|
-
console.log('Validation test result:', {
|
|
342
|
-
isValid: result.isValid,
|
|
343
|
-
algorithm: result.algorithm,
|
|
344
|
-
error: result.error,
|
|
345
|
-
timestamp: result.timestamp
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
testValidation();
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
### Local Testing Tips
|
|
353
|
-
|
|
354
|
-
1. **Get a real webhook sample** from Fluent Commerce test environment
|
|
355
|
-
2. **Capture the exact raw body** - don't modify or reformat
|
|
356
|
-
3. **Extract the signature header** - `fluent-signature` or `flex.signature`
|
|
357
|
-
4. **Use the correct public key** for the environment (sandbox/production)
|
|
358
|
-
5. **Test with both algorithms** to ensure your code handles both
|
|
359
|
-
|
|
360
|
-
---
|
|
361
|
-
|
|
362
|
-
## Common Patterns
|
|
363
|
-
|
|
364
|
-
### Pattern 1: Validate Then Parse
|
|
365
|
-
|
|
366
|
-
```typescript
|
|
367
|
-
// ✅ CORRECT - Validate before parsing
|
|
368
|
-
const result = await validator.validateWebhook(rawBody, headers, publicKey);
|
|
369
|
-
if (!result.isValid) {
|
|
370
|
-
throw new Error('Invalid signature');
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
const data = JSON.parse(rawBody); // Safe to parse now
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
### Pattern 2: Early Return on Failure
|
|
377
|
-
|
|
378
|
-
```typescript
|
|
379
|
-
// ✅ CORRECT - Fail fast pattern
|
|
380
|
-
const result = await validator.validateWebhook(rawBody, headers, publicKey);
|
|
381
|
-
if (!result.isValid) {
|
|
382
|
-
return { statusCode: 401, body: 'Unauthorized' };
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
// Continue processing valid webhook
|
|
386
|
-
const data = JSON.parse(rawBody);
|
|
387
|
-
await processWebhookData(data);
|
|
388
|
-
return { statusCode: 200, body: 'Success' };
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
### Pattern 3: Logging for Security Monitoring
|
|
392
|
-
|
|
393
|
-
```typescript
|
|
394
|
-
// ✅ CORRECT - Log validation failures for security team
|
|
395
|
-
const result = await validator.validateWebhook(rawBody, headers, publicKey);
|
|
396
|
-
|
|
397
|
-
if (!result.isValid) {
|
|
398
|
-
logger.warn('Webhook validation failed', {
|
|
399
|
-
error: result.error,
|
|
400
|
-
timestamp: result.timestamp,
|
|
401
|
-
sourceIp: request.ip, // Track source
|
|
402
|
-
algorithm: result.algorithm,
|
|
403
|
-
hasSignature: !!headers['fluent-signature'] || !!headers['flex.signature']
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
// Optionally alert security team if many failures
|
|
407
|
-
if (await tooManyFailures()) {
|
|
408
|
-
await alertSecurityTeam('Multiple webhook validation failures detected');
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
return { statusCode: 401, body: 'Unauthorized' };
|
|
412
|
-
}
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
---
|
|
416
|
-
|
|
417
|
-
## Quick Troubleshooting
|
|
418
|
-
|
|
419
|
-
### Problem: Validation Always Fails
|
|
420
|
-
|
|
421
|
-
**Check 1**: Are you using the raw body?
|
|
422
|
-
```typescript
|
|
423
|
-
// ✅ CORRECT
|
|
424
|
-
const rawBody = await request.text();
|
|
425
|
-
|
|
426
|
-
// ❌ WRONG
|
|
427
|
-
const rawBody = JSON.stringify(request.json());
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
**Check 2**: Is the public key correct?
|
|
431
|
-
```typescript
|
|
432
|
-
console.log('Public key starts with:', publicKey.substring(0, 30));
|
|
433
|
-
// Should start with "-----BEGIN PUBLIC KEY-----" or "MIIBIj"
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
**Check 3**: Is the signature header present?
|
|
437
|
-
```typescript
|
|
438
|
-
console.log('Headers:', headers);
|
|
439
|
-
console.log('Has fluent-signature:', !!headers['fluent-signature']);
|
|
440
|
-
console.log('Has flex.signature:', !!headers['flex.signature']);
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
**Check 4**: Are you using the right environment's key?
|
|
444
|
-
```typescript
|
|
445
|
-
// Production webhook needs production public key
|
|
446
|
-
// Sandbox webhook needs sandbox public key
|
|
447
|
-
console.log('Environment:', process.env.NODE_ENV);
|
|
448
|
-
console.log('Using key for:', process.env.FLUENT_ENV);
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
---
|
|
452
|
-
|
|
453
|
-
## Key Takeaways
|
|
454
|
-
|
|
455
|
-
- **Basic pattern**: Create validator → call `validateWebhook()` → check `isValid`
|
|
456
|
-
- **Auto-detection works**: SDK automatically selects SHA512 or MD5 based on headers
|
|
457
|
-
- **Use raw body**: Never parse or modify body before validation
|
|
458
|
-
- **Check isValid**: Always check result before processing webhook data
|
|
459
|
-
- **Log failures**: Track validation failures for security monitoring
|
|
460
|
-
- **Return 401**: Return unauthorized status for invalid signatures
|
|
461
|
-
|
|
462
|
-
---
|
|
463
|
-
|
|
464
|
-
## Practice Exercise
|
|
465
|
-
|
|
466
|
-
Create a simple webhook validator that:
|
|
467
|
-
1. Accepts a webhook payload and headers
|
|
468
|
-
2. Validates the signature using the SDK
|
|
469
|
-
3. Logs the validation result
|
|
470
|
-
4. Returns success/failure status
|
|
471
|
-
|
|
472
|
-
<details>
|
|
473
|
-
<summary>Solution</summary>
|
|
474
|
-
|
|
475
|
-
```typescript
|
|
476
|
-
import {
|
|
477
|
-
WebhookValidationService,
|
|
478
|
-
createConsoleLogger
|
|
479
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
480
|
-
|
|
481
|
-
async function handleWebhook(
|
|
482
|
-
rawBody: string,
|
|
483
|
-
headers: Record<string, string>
|
|
484
|
-
): Promise<{ statusCode: number; body: string }> {
|
|
485
|
-
// Setup
|
|
486
|
-
const logger = createConsoleLogger();
|
|
487
|
-
const validator = new WebhookValidationService({ strictValidation: true }, logger);
|
|
488
|
-
const publicKey = process.env.FLUENT_WEBHOOK_PUBLIC_KEY!;
|
|
489
|
-
|
|
490
|
-
// Validate
|
|
491
|
-
const result = await validator.validateWebhook(rawBody, headers, publicKey);
|
|
492
|
-
|
|
493
|
-
// Log result
|
|
494
|
-
logger.info('Validation result', {
|
|
495
|
-
isValid: result.isValid,
|
|
496
|
-
algorithm: result.algorithm,
|
|
497
|
-
error: result.error
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
// Return response
|
|
501
|
-
if (!result.isValid) {
|
|
502
|
-
return { statusCode: 401, body: 'Invalid signature' };
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
const data = JSON.parse(rawBody);
|
|
506
|
-
logger.info('Processing webhook', { eventId: data.eventId });
|
|
507
|
-
|
|
508
|
-
return { statusCode: 200, body: 'Success' };
|
|
509
|
-
}
|
|
510
|
-
```
|
|
511
|
-
</details>
|
|
512
|
-
|
|
513
|
-
---
|
|
514
|
-
|
|
515
|
-
## Next Steps
|
|
516
|
-
|
|
517
|
-
Continue to [Module 3: Versori Integration](./webhook-validation-03-versori-integration.md) to learn how to integrate webhook validation in Versori connectors.
|
|
518
|
-
|
|
519
|
-
---
|
|
520
|
-
|
|
521
|
-
## Further Reading
|
|
522
|
-
|
|
523
|
-
- [Module 4: Platform Integration](./webhook-validation-04-platform-integration.md) - Express.js and other platforms
|
|
524
|
-
- [Module 5: Configuration](./webhook-validation-05-configuration.md) - Advanced configuration options
|
|
525
|
-
- [Module 6: Error Handling](./webhook-validation-06-error-handling.md) - Comprehensive error handling patterns
|
|
1
|
+
# Module 2: Quick Start
|
|
2
|
+
|
|
3
|
+
**Level:** Beginner
|
|
4
|
+
**Estimated Time:** 15 minutes
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
This module gets you started with webhook validation immediately. You'll learn the basic usage pattern, auto-detection features, and how to validate your first webhook in just a few lines of code.
|
|
9
|
+
|
|
10
|
+
## Learning Objectives
|
|
11
|
+
|
|
12
|
+
By the end of this module, you will:
|
|
13
|
+
- Implement basic webhook validation
|
|
14
|
+
- Understand the auto-detection pattern
|
|
15
|
+
- Know how to handle validation results
|
|
16
|
+
- Test webhook validation locally
|
|
17
|
+
- Build a complete working example
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Basic Validation Pattern
|
|
22
|
+
|
|
23
|
+
### Minimal Example
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import {
|
|
27
|
+
WebhookValidationService,
|
|
28
|
+
createConsoleLogger
|
|
29
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
30
|
+
|
|
31
|
+
// 1. Initialize logging
|
|
32
|
+
const logger = createConsoleLogger();
|
|
33
|
+
|
|
34
|
+
// 2. Create validator
|
|
35
|
+
const validator = new WebhookValidationService({
|
|
36
|
+
strictValidation: true // Throw errors on validation failure
|
|
37
|
+
}, logger);
|
|
38
|
+
|
|
39
|
+
// 3. Validate webhook (auto-detects signature type)
|
|
40
|
+
const result = await validator.validateWebhook(
|
|
41
|
+
rawBody, // Raw request body as string
|
|
42
|
+
headers, // Request headers object
|
|
43
|
+
publicKey // Public key from Fluent Commerce
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// 4. Check result
|
|
47
|
+
if (!result.isValid) {
|
|
48
|
+
console.error('Invalid webhook:', result.error);
|
|
49
|
+
return { statusCode: 401, body: 'Invalid signature' };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 5. Process valid webhook
|
|
53
|
+
console.log('Valid webhook using:', result.algorithm);
|
|
54
|
+
const data = JSON.parse(rawBody);
|
|
55
|
+
// ... your business logic here
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**That's the complete pattern.** The SDK handles algorithm detection, signature extraction, and cryptographic verification automatically.
|
|
59
|
+
|
|
60
|
+
> **Note:** `validateWebhook()` is the **ONLY** FluentClient method that does NOT require `retailerId` configuration. This is because webhook validation is performed using RSA public key cryptography and does not require API authentication.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Understanding the Parameters
|
|
65
|
+
|
|
66
|
+
### 1. Raw Body (Critical)
|
|
67
|
+
|
|
68
|
+
**Must be the exact string** received in the webhook request:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// ✅ CORRECT - Raw string body
|
|
72
|
+
const rawBody = await request.text();
|
|
73
|
+
const rawBody = req.body.toString(); // If using express.raw()
|
|
74
|
+
|
|
75
|
+
// ❌ WRONG - Parsed or modified body
|
|
76
|
+
const rawBody = JSON.stringify(req.body); // Don't stringify parsed JSON
|
|
77
|
+
const rawBody = req.body.data; // Don't use parsed fields
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Why this matters**: The signature is created from the exact byte sequence of the original body. Any modification (even whitespace changes) breaks validation.
|
|
81
|
+
|
|
82
|
+
### 2. Headers Object
|
|
83
|
+
|
|
84
|
+
Standard HTTP headers object with signature header:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// Example headers object
|
|
88
|
+
const headers = {
|
|
89
|
+
'fluent-signature': 'iQEcBAABCAAGBQJgm...',
|
|
90
|
+
'content-type': 'application/json',
|
|
91
|
+
'user-agent': 'Fluent-Webhook/1.0'
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// From Express.js
|
|
95
|
+
const headers = req.headers;
|
|
96
|
+
|
|
97
|
+
// From Versori (use ctx.request() to access Express request)
|
|
98
|
+
const req = ctx.request();
|
|
99
|
+
const headers = req?.headers || {};
|
|
100
|
+
|
|
101
|
+
// From fetch API
|
|
102
|
+
const headers = Object.fromEntries(request.headers.entries());
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Signature headers** the SDK looks for (in priority order):
|
|
106
|
+
1. `fluent-signature` (SHA512withRSA)
|
|
107
|
+
2. `flex.signature` (MD5withRSA)
|
|
108
|
+
|
|
109
|
+
### 3. Public Key
|
|
110
|
+
|
|
111
|
+
Public key from Fluent Commerce for your environment:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// From environment variable (recommended)
|
|
115
|
+
const publicKey = process.env.FLUENT_WEBHOOK_PUBLIC_KEY;
|
|
116
|
+
|
|
117
|
+
// From Versori variable
|
|
118
|
+
const publicKey = ctx.vars.FLUENT_WEBHOOK_PUBLIC_KEY;
|
|
119
|
+
|
|
120
|
+
// From configuration
|
|
121
|
+
const publicKey = config.fluent.webhookPublicKey;
|
|
122
|
+
|
|
123
|
+
// Hardcoded (development only - not recommended)
|
|
124
|
+
const publicKey = "-----BEGIN PUBLIC KEY-----\nMIIBIj...\n-----END PUBLIC KEY-----";
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**Formats accepted**:
|
|
128
|
+
- Full PEM with headers: `-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----`
|
|
129
|
+
- Raw base64: `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...`
|
|
130
|
+
|
|
131
|
+
The SDK automatically adds PEM headers if missing.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Auto-Detection in Action
|
|
136
|
+
|
|
137
|
+
The SDK automatically detects which signature algorithm to use:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// Webhook with SHA512 signature
|
|
141
|
+
const headers1 = {
|
|
142
|
+
'fluent-signature': 'abc123...',
|
|
143
|
+
'content-type': 'application/json'
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const result1 = await validator.validateWebhook(rawBody, headers1, publicKey);
|
|
147
|
+
// result1.algorithm = 'SHA512withRSA'
|
|
148
|
+
|
|
149
|
+
// Webhook with MD5 signature (for Flex workflows)
|
|
150
|
+
const headers2 = {
|
|
151
|
+
'flex.signature': 'xyz789...',
|
|
152
|
+
'content-type': 'application/json'
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const result2 = await validator.validateWebhook(rawBody, headers2, publicKey);
|
|
156
|
+
// result2.algorithm = 'MD5withRSA'
|
|
157
|
+
|
|
158
|
+
// Webhook with no signature
|
|
159
|
+
const headers3 = {
|
|
160
|
+
'content-type': 'application/json'
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const result3 = await validator.validateWebhook(rawBody, headers3, publicKey);
|
|
164
|
+
// result3.isValid = false
|
|
165
|
+
// result3.error = 'No signature header found'
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**You don't need to specify the algorithm** - the SDK handles it automatically based on which header is present.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Handling Validation Results
|
|
173
|
+
|
|
174
|
+
### Validation Result Structure
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
interface WebhookValidationResult {
|
|
178
|
+
isValid: boolean; // true if signature verified successfully
|
|
179
|
+
algorithm: SignatureAlgorithm; // Which algorithm was used
|
|
180
|
+
error?: string; // Error message if validation failed
|
|
181
|
+
timestamp: Date; // When validation occurred
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Success Case
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const result = await validator.validateWebhook(rawBody, headers, publicKey);
|
|
189
|
+
|
|
190
|
+
if (result.isValid) {
|
|
191
|
+
console.log(`Valid webhook using ${result.algorithm}`);
|
|
192
|
+
console.log(`Validated at ${result.timestamp.toISOString()}`);
|
|
193
|
+
|
|
194
|
+
// Safe to process webhook data
|
|
195
|
+
const data = JSON.parse(rawBody);
|
|
196
|
+
await processWebhookData(data);
|
|
197
|
+
|
|
198
|
+
return { statusCode: 200, body: 'Success' };
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Failure Case
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
const result = await validator.validateWebhook(rawBody, headers, publicKey);
|
|
206
|
+
|
|
207
|
+
if (!result.isValid) {
|
|
208
|
+
console.error(`Validation failed: ${result.error}`);
|
|
209
|
+
console.error(`Attempted algorithm: ${result.algorithm}`);
|
|
210
|
+
|
|
211
|
+
// Log for security monitoring
|
|
212
|
+
logger.warn('Invalid webhook signature', {
|
|
213
|
+
error: result.error,
|
|
214
|
+
timestamp: result.timestamp,
|
|
215
|
+
headers: headers
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Return 401 Unauthorized
|
|
219
|
+
return { statusCode: 401, body: 'Invalid signature' };
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Complete Working Example
|
|
226
|
+
|
|
227
|
+
### Standalone Validation Script
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
import {
|
|
231
|
+
WebhookValidationService,
|
|
232
|
+
SignatureAlgorithm,
|
|
233
|
+
createConsoleLogger
|
|
234
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
235
|
+
|
|
236
|
+
async function validateWebhook(
|
|
237
|
+
rawBody: string,
|
|
238
|
+
headers: Record<string, string>,
|
|
239
|
+
publicKey: string
|
|
240
|
+
): Promise<boolean> {
|
|
241
|
+
// Initialize logging
|
|
242
|
+
const logger = createConsoleLogger();
|
|
243
|
+
|
|
244
|
+
// Create validator with strict validation
|
|
245
|
+
const validator = new WebhookValidationService({
|
|
246
|
+
strictValidation: true
|
|
247
|
+
}, logger);
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
// Validate webhook (auto-detects algorithm)
|
|
251
|
+
const result = await validator.validateWebhook(
|
|
252
|
+
rawBody,
|
|
253
|
+
headers,
|
|
254
|
+
publicKey
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
if (!result.isValid) {
|
|
258
|
+
logger.error('Webhook validation failed', {
|
|
259
|
+
error: result.error,
|
|
260
|
+
algorithm: result.algorithm,
|
|
261
|
+
timestamp: result.timestamp
|
|
262
|
+
});
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
logger.info('Webhook validated successfully', {
|
|
267
|
+
algorithm: result.algorithm,
|
|
268
|
+
timestamp: result.timestamp
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
return true;
|
|
272
|
+
|
|
273
|
+
} catch (error) {
|
|
274
|
+
logger.error('Validation error', { error });
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Usage
|
|
280
|
+
const isValid = await validateWebhook(
|
|
281
|
+
requestBody,
|
|
282
|
+
requestHeaders,
|
|
283
|
+
process.env.FLUENT_WEBHOOK_PUBLIC_KEY!
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
if (isValid) {
|
|
287
|
+
const webhookData = JSON.parse(requestBody);
|
|
288
|
+
console.log('Processing webhook:', webhookData.eventId);
|
|
289
|
+
// ... process webhook
|
|
290
|
+
} else {
|
|
291
|
+
console.error('Rejecting invalid webhook');
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Testing Validation
|
|
298
|
+
|
|
299
|
+
### Test with Sample Data
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
import {
|
|
303
|
+
WebhookValidationService,
|
|
304
|
+
createConsoleLogger
|
|
305
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
306
|
+
|
|
307
|
+
async function testValidation() {
|
|
308
|
+
const logger = createConsoleLogger();
|
|
309
|
+
|
|
310
|
+
const validator = new WebhookValidationService({
|
|
311
|
+
strictValidation: false // Lenient for testing
|
|
312
|
+
}, logger);
|
|
313
|
+
|
|
314
|
+
// Sample webhook payload
|
|
315
|
+
const webhookBody = JSON.stringify({
|
|
316
|
+
eventId: 'evt_123',
|
|
317
|
+
entityType: 'ORDER',
|
|
318
|
+
entityId: 'order_456',
|
|
319
|
+
timestamp: new Date().toISOString(),
|
|
320
|
+
data: {
|
|
321
|
+
ref: 'ORD-123',
|
|
322
|
+
status: 'PLACED'
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// Sample headers (get real signature from Fluent Commerce)
|
|
327
|
+
const webhookHeaders = {
|
|
328
|
+
'fluent-signature': 'YOUR_TEST_SIGNATURE_HERE',
|
|
329
|
+
'content-type': 'application/json'
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const publicKey = process.env.FLUENT_WEBHOOK_PUBLIC_KEY!;
|
|
333
|
+
|
|
334
|
+
// Validate
|
|
335
|
+
const result = await validator.validateWebhook(
|
|
336
|
+
webhookBody,
|
|
337
|
+
webhookHeaders,
|
|
338
|
+
publicKey
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
console.log('Validation test result:', {
|
|
342
|
+
isValid: result.isValid,
|
|
343
|
+
algorithm: result.algorithm,
|
|
344
|
+
error: result.error,
|
|
345
|
+
timestamp: result.timestamp
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
testValidation();
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Local Testing Tips
|
|
353
|
+
|
|
354
|
+
1. **Get a real webhook sample** from Fluent Commerce test environment
|
|
355
|
+
2. **Capture the exact raw body** - don't modify or reformat
|
|
356
|
+
3. **Extract the signature header** - `fluent-signature` or `flex.signature`
|
|
357
|
+
4. **Use the correct public key** for the environment (sandbox/production)
|
|
358
|
+
5. **Test with both algorithms** to ensure your code handles both
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## Common Patterns
|
|
363
|
+
|
|
364
|
+
### Pattern 1: Validate Then Parse
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
// ✅ CORRECT - Validate before parsing
|
|
368
|
+
const result = await validator.validateWebhook(rawBody, headers, publicKey);
|
|
369
|
+
if (!result.isValid) {
|
|
370
|
+
throw new Error('Invalid signature');
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const data = JSON.parse(rawBody); // Safe to parse now
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Pattern 2: Early Return on Failure
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
// ✅ CORRECT - Fail fast pattern
|
|
380
|
+
const result = await validator.validateWebhook(rawBody, headers, publicKey);
|
|
381
|
+
if (!result.isValid) {
|
|
382
|
+
return { statusCode: 401, body: 'Unauthorized' };
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Continue processing valid webhook
|
|
386
|
+
const data = JSON.parse(rawBody);
|
|
387
|
+
await processWebhookData(data);
|
|
388
|
+
return { statusCode: 200, body: 'Success' };
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Pattern 3: Logging for Security Monitoring
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
// ✅ CORRECT - Log validation failures for security team
|
|
395
|
+
const result = await validator.validateWebhook(rawBody, headers, publicKey);
|
|
396
|
+
|
|
397
|
+
if (!result.isValid) {
|
|
398
|
+
logger.warn('Webhook validation failed', {
|
|
399
|
+
error: result.error,
|
|
400
|
+
timestamp: result.timestamp,
|
|
401
|
+
sourceIp: request.ip, // Track source
|
|
402
|
+
algorithm: result.algorithm,
|
|
403
|
+
hasSignature: !!headers['fluent-signature'] || !!headers['flex.signature']
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
// Optionally alert security team if many failures
|
|
407
|
+
if (await tooManyFailures()) {
|
|
408
|
+
await alertSecurityTeam('Multiple webhook validation failures detected');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return { statusCode: 401, body: 'Unauthorized' };
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## Quick Troubleshooting
|
|
418
|
+
|
|
419
|
+
### Problem: Validation Always Fails
|
|
420
|
+
|
|
421
|
+
**Check 1**: Are you using the raw body?
|
|
422
|
+
```typescript
|
|
423
|
+
// ✅ CORRECT
|
|
424
|
+
const rawBody = await request.text();
|
|
425
|
+
|
|
426
|
+
// ❌ WRONG
|
|
427
|
+
const rawBody = JSON.stringify(request.json());
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**Check 2**: Is the public key correct?
|
|
431
|
+
```typescript
|
|
432
|
+
console.log('Public key starts with:', publicKey.substring(0, 30));
|
|
433
|
+
// Should start with "-----BEGIN PUBLIC KEY-----" or "MIIBIj"
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
**Check 3**: Is the signature header present?
|
|
437
|
+
```typescript
|
|
438
|
+
console.log('Headers:', headers);
|
|
439
|
+
console.log('Has fluent-signature:', !!headers['fluent-signature']);
|
|
440
|
+
console.log('Has flex.signature:', !!headers['flex.signature']);
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
**Check 4**: Are you using the right environment's key?
|
|
444
|
+
```typescript
|
|
445
|
+
// Production webhook needs production public key
|
|
446
|
+
// Sandbox webhook needs sandbox public key
|
|
447
|
+
console.log('Environment:', process.env.NODE_ENV);
|
|
448
|
+
console.log('Using key for:', process.env.FLUENT_ENV);
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## Key Takeaways
|
|
454
|
+
|
|
455
|
+
- **Basic pattern**: Create validator → call `validateWebhook()` → check `isValid`
|
|
456
|
+
- **Auto-detection works**: SDK automatically selects SHA512 or MD5 based on headers
|
|
457
|
+
- **Use raw body**: Never parse or modify body before validation
|
|
458
|
+
- **Check isValid**: Always check result before processing webhook data
|
|
459
|
+
- **Log failures**: Track validation failures for security monitoring
|
|
460
|
+
- **Return 401**: Return unauthorized status for invalid signatures
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
## Practice Exercise
|
|
465
|
+
|
|
466
|
+
Create a simple webhook validator that:
|
|
467
|
+
1. Accepts a webhook payload and headers
|
|
468
|
+
2. Validates the signature using the SDK
|
|
469
|
+
3. Logs the validation result
|
|
470
|
+
4. Returns success/failure status
|
|
471
|
+
|
|
472
|
+
<details>
|
|
473
|
+
<summary>Solution</summary>
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
import {
|
|
477
|
+
WebhookValidationService,
|
|
478
|
+
createConsoleLogger
|
|
479
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
480
|
+
|
|
481
|
+
async function handleWebhook(
|
|
482
|
+
rawBody: string,
|
|
483
|
+
headers: Record<string, string>
|
|
484
|
+
): Promise<{ statusCode: number; body: string }> {
|
|
485
|
+
// Setup
|
|
486
|
+
const logger = createConsoleLogger();
|
|
487
|
+
const validator = new WebhookValidationService({ strictValidation: true }, logger);
|
|
488
|
+
const publicKey = process.env.FLUENT_WEBHOOK_PUBLIC_KEY!;
|
|
489
|
+
|
|
490
|
+
// Validate
|
|
491
|
+
const result = await validator.validateWebhook(rawBody, headers, publicKey);
|
|
492
|
+
|
|
493
|
+
// Log result
|
|
494
|
+
logger.info('Validation result', {
|
|
495
|
+
isValid: result.isValid,
|
|
496
|
+
algorithm: result.algorithm,
|
|
497
|
+
error: result.error
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
// Return response
|
|
501
|
+
if (!result.isValid) {
|
|
502
|
+
return { statusCode: 401, body: 'Invalid signature' };
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const data = JSON.parse(rawBody);
|
|
506
|
+
logger.info('Processing webhook', { eventId: data.eventId });
|
|
507
|
+
|
|
508
|
+
return { statusCode: 200, body: 'Success' };
|
|
509
|
+
}
|
|
510
|
+
```
|
|
511
|
+
</details>
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
## Next Steps
|
|
516
|
+
|
|
517
|
+
Continue to [Module 3: Versori Integration](./webhook-validation-03-versori-integration.md) to learn how to integrate webhook validation in Versori connectors.
|
|
518
|
+
|
|
519
|
+
---
|
|
520
|
+
|
|
521
|
+
## Further Reading
|
|
522
|
+
|
|
523
|
+
- [Module 4: Platform Integration](./webhook-validation-04-platform-integration.md) - Express.js and other platforms
|
|
524
|
+
- [Module 5: Configuration](./webhook-validation-05-configuration.md) - Advanced configuration options
|
|
525
|
+
- [Module 6: Error Handling](./webhook-validation-06-error-handling.md) - Comprehensive error handling patterns
|