@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,959 +1,959 @@
|
|
|
1
|
-
---
|
|
2
|
-
template_id: tpl-ingest-payload-json-to-order-cancel-event
|
|
3
|
-
canonical_filename: template-ingestion-payload-json-order-cancel-event.md
|
|
4
|
-
sdk_version: latest
|
|
5
|
-
runtime: versori
|
|
6
|
-
direction: ingestion
|
|
7
|
-
source: payload-json
|
|
8
|
-
destination: fluent-event-api
|
|
9
|
-
entity: order
|
|
10
|
-
format: json
|
|
11
|
-
logging: versori
|
|
12
|
-
status: stable
|
|
13
|
-
features:
|
|
14
|
-
- direct-payload-processing
|
|
15
|
-
- json-parsing
|
|
16
|
-
- event-api-integration
|
|
17
|
-
- error-handling
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
# Template: Ingestion - Payload JSON to Order Cancel Event
|
|
21
|
-
|
|
22
|
-
**SDK Version:** @fluentcommerce/fc-connect-sdk@latest
|
|
23
|
-
**Last Updated:** 2025-01-24
|
|
24
|
-
**Deployment Target:** Versori Platform
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## 📋 Implementation Prompt
|
|
29
|
-
|
|
30
|
-
```
|
|
31
|
-
I need a Versori webhook ingestion that:
|
|
32
|
-
|
|
33
|
-
1) Receives JSON payload directly in webhook request body
|
|
34
|
-
2) Parses JSON to extract order reference
|
|
35
|
-
3) Builds OrderCancel event payload with retailerId, name, entityRef, entityType
|
|
36
|
-
4) Sends event to Fluent Commerce Event API (async)
|
|
37
|
-
5) Returns success/error response
|
|
38
|
-
6) Uses native Versori log from context
|
|
39
|
-
|
|
40
|
-
Use the loaded docs to fill in SDK specifics and best practices.
|
|
41
|
-
Keep the structure identical to the template; only adapt where needed.
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## 📋 Template Overview
|
|
47
|
-
|
|
48
|
-
This connector runs on the Versori platform. It receives JSON payloads directly via webhook, extracts the order reference, and sends OrderCancel events to Fluent Commerce Event API. Most operational settings (Fluent account/connection) are configured via activation variables.
|
|
49
|
-
|
|
50
|
-
### What This Template Does
|
|
51
|
-
|
|
52
|
-
```
|
|
53
|
-
┌────────────────────────────────────────────────────────────────┐
|
|
54
|
-
│ INGESTION WORKFLOW │
|
|
55
|
-
└────────────────────────────────────────────────────────────────┘
|
|
56
|
-
|
|
57
|
-
1. TRIGGER
|
|
58
|
-
└─ Webhook: HTTP POST endpoint receives JSON payload
|
|
59
|
-
|
|
60
|
-
2. RECEIVE PAYLOAD
|
|
61
|
-
├─ Extract JSON from request body (ctx.data or ctx.request)
|
|
62
|
-
├─ Validate payload structure
|
|
63
|
-
└─ Log incoming request
|
|
64
|
-
|
|
65
|
-
3. PARSE JSON
|
|
66
|
-
├─ Parse JSON payload (if raw string)
|
|
67
|
-
├─ Extract order reference field
|
|
68
|
-
└─ Validate required fields
|
|
69
|
-
|
|
70
|
-
4. BUILD EVENT
|
|
71
|
-
├─ Construct OrderCancel event payload
|
|
72
|
-
├─ Set retailerId (from config or payload)
|
|
73
|
-
├─ Set name: "OrderCancel"
|
|
74
|
-
├─ Set entityRef: order reference
|
|
75
|
-
└─ Set entityType: "ORDER"
|
|
76
|
-
|
|
77
|
-
5. SEND EVENT (Event API)
|
|
78
|
-
├─ Send event to Fluent Commerce Event API (async)
|
|
79
|
-
├─ Handle success/error responses
|
|
80
|
-
└─ Log event result
|
|
81
|
-
|
|
82
|
-
6. RETURN RESPONSE
|
|
83
|
-
├─ Return success with event details
|
|
84
|
-
└─ Return error with details if failed
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Key Features
|
|
88
|
-
|
|
89
|
-
- **Direct Payload Processing**: Receives JSON payload directly in webhook request body
|
|
90
|
-
- **JSON Parsing**: Handles both pre-parsed and raw JSON payloads
|
|
91
|
-
- **Event API Integration**: Sends OrderCancel events to Fluent Commerce
|
|
92
|
-
- **Error Handling**: Comprehensive error handling with detailed logging
|
|
93
|
-
- **Native Versori Logging**: Uses Versori log from context
|
|
94
|
-
- **Flexible Order Reference Extraction**: Supports multiple JSON field patterns
|
|
95
|
-
|
|
96
|
-
### 📦 Package Information
|
|
97
|
-
|
|
98
|
-
**SDK:** [@fluentcommerce/fc-connect-sdk](https://www.npmjs.com/package/@fluentcommerce/fc-connect-sdk) `latest`
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
npm install @fluentcommerce/fc-connect-sdk@latest
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
---
|
|
105
|
-
|
|
106
|
-
**Templates are designed for direct deployment; customize via activation variables.**
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
## 📦 SDK Imports (Verified - Versori Optimized)
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
// ✅ VERIFIED IMPORTS - These match actual SDK exports
|
|
114
|
-
import { Buffer } from 'node:buffer'; // Required for Versori/Deno runtime
|
|
115
|
-
import {
|
|
116
|
-
createClient, // Universal client factory
|
|
117
|
-
JSONParserService, // JSON parsing utility
|
|
118
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
119
|
-
|
|
120
|
-
import type { FluentClient } from '@fluentcommerce/fc-connect-sdk';
|
|
121
|
-
|
|
122
|
-
// Versori platform imports
|
|
123
|
-
import { webhook, http } from '@versori/run';
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
**Note:** All imports are from actual SDK exports - this code compiles and runs as-is.
|
|
127
|
-
|
|
128
|
-
**⚠️ CRITICAL - Buffer Import Required:**
|
|
129
|
-
|
|
130
|
-
The `Buffer` import from `node:buffer` is **required** for Versori/Deno runtime compatibility:
|
|
131
|
-
- Versori and Deno do NOT have `Buffer` as a global (unlike Node.js)
|
|
132
|
-
- Without this import, code will crash with `ReferenceError: Buffer is not defined`
|
|
133
|
-
- Always include this import in Versori templates, even if not directly used in the template code
|
|
134
|
-
- Required for SDK internal operations and any Buffer usage in your code
|
|
135
|
-
|
|
136
|
-
**✅ VERSORI PLATFORM - Use Native Logs:**
|
|
137
|
-
|
|
138
|
-
- Use `log` from context: `const { log } = ctx;`
|
|
139
|
-
- Native Versori logs are simpler and automatically integrated with platform monitoring
|
|
140
|
-
|
|
141
|
-
---
|
|
142
|
-
|
|
143
|
-
## 🔐 Fluent Commerce Connection Setup
|
|
144
|
-
|
|
145
|
-
**✅ BEST PRACTICE:** Store Fluent Commerce credentials in a Versori connection object:
|
|
146
|
-
|
|
147
|
-
**Connection Configuration:**
|
|
148
|
-
|
|
149
|
-
1. **Create Connection in Versori:**
|
|
150
|
-
- Name: `fluent_commerce`
|
|
151
|
-
- Type: HTTP Basic Auth or OAuth2
|
|
152
|
-
- Credentials: Fluent Commerce API credentials
|
|
153
|
-
|
|
154
|
-
2. **Connection Variables:**
|
|
155
|
-
- `FLUENT_BASE_URL` - Fluent Commerce API base URL (e.g., `https://api.fluentcommerce.com`)
|
|
156
|
-
- `FLUENT_RETAILER_ID` - Your retailer ID
|
|
157
|
-
- `FLUENT_CLIENT_ID` - OAuth client ID (if using OAuth2)
|
|
158
|
-
- `FLUENT_CLIENT_SECRET` - OAuth client secret (if using OAuth2)
|
|
159
|
-
|
|
160
|
-
**Benefits:**
|
|
161
|
-
- ✅ Credentials stored securely in Versori vault
|
|
162
|
-
- ✅ Connection can be reused across workflows
|
|
163
|
-
- ✅ No sensitive data in activation variables
|
|
164
|
-
- ✅ Easier credential rotation
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## 📄 Expected JSON Payload Format
|
|
169
|
-
|
|
170
|
-
The webhook accepts JSON payloads with order reference information. Multiple formats are supported:
|
|
171
|
-
|
|
172
|
-
### Format 1: Simple Order Reference
|
|
173
|
-
|
|
174
|
-
```json
|
|
175
|
-
{
|
|
176
|
-
"orderRef": "ORD-12345"
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### Format 2: Nested Order Reference
|
|
181
|
-
|
|
182
|
-
```json
|
|
183
|
-
{
|
|
184
|
-
"order": {
|
|
185
|
-
"reference": "ORD-12345"
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### Format 3: With Additional Metadata
|
|
191
|
-
|
|
192
|
-
```json
|
|
193
|
-
{
|
|
194
|
-
"orderRef": "ORD-12345",
|
|
195
|
-
"reason": "Customer requested cancellation",
|
|
196
|
-
"cancelledBy": "admin@example.com"
|
|
197
|
-
}
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
**Note:** The template extracts `orderRef` from the payload. Customize the extraction logic in the service if your payload uses different field names.
|
|
201
|
-
|
|
202
|
-
---
|
|
203
|
-
|
|
204
|
-
## Event Payload Structure
|
|
205
|
-
|
|
206
|
-
The template builds and sends this event structure:
|
|
207
|
-
|
|
208
|
-
```json
|
|
209
|
-
{
|
|
210
|
-
"retailerId": "{{retailer_id}}",
|
|
211
|
-
"name": "OrderCancel",
|
|
212
|
-
"entityRef": "{{order_ref}}",
|
|
213
|
-
"entityType": "ORDER"
|
|
214
|
-
}
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
**Fields:**
|
|
218
|
-
- `retailerId`: Retrieved from Fluent Commerce connection or activation variable
|
|
219
|
-
- `name`: Fixed as "OrderCancel"
|
|
220
|
-
- `entityRef`: Extracted from incoming JSON payload
|
|
221
|
-
- `entityType`: Fixed as "ORDER"
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
## 🔧 Complete Production Code
|
|
226
|
-
|
|
227
|
-
### Versori Workflows Structure
|
|
228
|
-
|
|
229
|
-
**Key Concept**: Versori workflows are organized by **trigger type** at the first level, then by **specific workflow** with descriptive file names.
|
|
230
|
-
|
|
231
|
-
**Trigger Types:**
|
|
232
|
-
- **`webhook()`** → HTTP-based triggers (event-driven) - Creates HTTP endpoints
|
|
233
|
-
|
|
234
|
-
**Execution Steps (chained to triggers):**
|
|
235
|
-
- **`http()`** → External API calls (chained from webhook)
|
|
236
|
-
|
|
237
|
-
### Recommended Project Structure
|
|
238
|
-
|
|
239
|
-
```
|
|
240
|
-
order-cancel-webhook/
|
|
241
|
-
├── index.ts # Entry point - exports all workflows
|
|
242
|
-
└── src/
|
|
243
|
-
├── workflows/
|
|
244
|
-
│ └── webhook/
|
|
245
|
-
│ └── order-cancel.ts # Webhook: Order cancel handler
|
|
246
|
-
│
|
|
247
|
-
├── services/
|
|
248
|
-
│ └── order-cancel.service.ts # Shared orchestration logic
|
|
249
|
-
│
|
|
250
|
-
└── types/
|
|
251
|
-
└── order-cancel.types.ts # Type definitions
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
**Benefits:**
|
|
255
|
-
- ✅ Clear structure (webhook handlers in `webhook/`)
|
|
256
|
-
- ✅ Descriptive file names (easy to browse and understand)
|
|
257
|
-
- ✅ Reusable code in `services/` (DRY principle)
|
|
258
|
-
- ✅ Centralized type definitions
|
|
259
|
-
|
|
260
|
-
---
|
|
261
|
-
|
|
262
|
-
## Workflow Files
|
|
263
|
-
|
|
264
|
-
### 1. Webhook Workflow (`src/workflows/webhook/order-cancel.ts`)
|
|
265
|
-
|
|
266
|
-
**Purpose**: Handle order cancel requests via webhook
|
|
267
|
-
**Trigger**: HTTP POST
|
|
268
|
-
**Endpoint**: `POST https://{workspace}.versori.run/order-cancel`
|
|
269
|
-
**Use Cases**: Order cancellation from external systems, manual cancellations
|
|
270
|
-
|
|
271
|
-
```typescript
|
|
272
|
-
import { webhook, http } from '@versori/run';
|
|
273
|
-
import { executeOrderCancel } from '../../services/order-cancel.service';
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Webhook: Order Cancel Handler
|
|
277
|
-
*
|
|
278
|
-
* Endpoint: POST https://{workspace}.versori.run/order-cancel
|
|
279
|
-
* Request body: { "orderRef": "ORD-12345" }
|
|
280
|
-
*
|
|
281
|
-
* Pattern: webhook().then(http()) - needs Fluent API access
|
|
282
|
-
* Uses shared service: order-cancel.service.ts
|
|
283
|
-
*
|
|
284
|
-
* SECURITY: Authentication handled via connection parameter
|
|
285
|
-
* No manual API key validation needed - Versori manages this via connection auth
|
|
286
|
-
*/
|
|
287
|
-
export const orderCancelWebhook = webhook('order-cancel', {
|
|
288
|
-
// ✅ Webhook response mode: 'sync'
|
|
289
|
-
// - HTTP response sent when handler completes
|
|
290
|
-
// - Returns event ID and success status immediately after Fluent accepts event
|
|
291
|
-
// - Alternative: 'async' mode would return immediately (before processing)
|
|
292
|
-
response: { mode: 'sync' },
|
|
293
|
-
connection: 'order-cancel-webhook', // Versori validates API key
|
|
294
|
-
}).then(
|
|
295
|
-
http('process-order-cancel', { connection: 'fluent_commerce' }, async ctx => {
|
|
296
|
-
const { log, data } = ctx;
|
|
297
|
-
|
|
298
|
-
log.info('🚀 [WEBHOOK] Order cancel request received', {
|
|
299
|
-
timestamp: new Date().toISOString(),
|
|
300
|
-
hasPayload: !!data,
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
try {
|
|
304
|
-
// Reuse shared orchestration logic
|
|
305
|
-
const result = await executeOrderCancel(ctx);
|
|
306
|
-
|
|
307
|
-
log.info('✅ [WEBHOOK] Order cancel completed successfully', {
|
|
308
|
-
orderRef: result.orderRef,
|
|
309
|
-
eventId: result.eventId,
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
return {
|
|
313
|
-
success: true,
|
|
314
|
-
orderRef: result.orderRef,
|
|
315
|
-
eventId: result.eventId,
|
|
316
|
-
message: 'Order cancel event sent successfully',
|
|
317
|
-
};
|
|
318
|
-
} catch (e: any) {
|
|
319
|
-
log.error('❌ [WEBHOOK] Order cancel failed', {
|
|
320
|
-
message: e?.message,
|
|
321
|
-
stack: e?.stack,
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
return {
|
|
325
|
-
success: false,
|
|
326
|
-
error: e?.message || 'Unknown error occurred',
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
})
|
|
330
|
-
);
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
---
|
|
334
|
-
|
|
335
|
-
### 2. Entry Point (`index.ts`)
|
|
336
|
-
|
|
337
|
-
**Purpose**: Register all workflows with Versori platform
|
|
338
|
-
|
|
339
|
-
```typescript
|
|
340
|
-
/**
|
|
341
|
-
* Entry Point - Registers all workflows with Versori platform
|
|
342
|
-
*
|
|
343
|
-
* Versori automatically discovers and registers exported workflows
|
|
344
|
-
*
|
|
345
|
-
* File Structure:
|
|
346
|
-
* - src/workflows/webhook/ → HTTP-based triggers (webhooks)
|
|
347
|
-
* - src/services/ → Shared service logic (reusable across workflows)
|
|
348
|
-
*/
|
|
349
|
-
|
|
350
|
-
// Import webhook workflows
|
|
351
|
-
import { orderCancelWebhook } from './src/workflows/webhook/order-cancel';
|
|
352
|
-
|
|
353
|
-
// Register all workflows with Versori platform
|
|
354
|
-
export {
|
|
355
|
-
// Webhooks (HTTP-based triggers)
|
|
356
|
-
orderCancelWebhook,
|
|
357
|
-
};
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
**What Gets Exposed:**
|
|
361
|
-
- ✅ `orderCancelWebhook` → `https://{workspace}.versori.run/order-cancel`
|
|
362
|
-
|
|
363
|
-
---
|
|
364
|
-
|
|
365
|
-
## 3. Type Definitions (`src/types/order-cancel.types.ts`)
|
|
366
|
-
|
|
367
|
-
```typescript
|
|
368
|
-
/**
|
|
369
|
-
* Type Definitions for Order Cancel Ingestion
|
|
370
|
-
*
|
|
371
|
-
* Centralized type definitions for order cancel workflow
|
|
372
|
-
*/
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* Order cancel request payload
|
|
376
|
-
*/
|
|
377
|
-
export interface OrderCancelPayload {
|
|
378
|
-
orderRef?: string;
|
|
379
|
-
order?: {
|
|
380
|
-
reference?: string;
|
|
381
|
-
ref?: string;
|
|
382
|
-
};
|
|
383
|
-
[key: string]: unknown; // Allow additional fields
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Order cancel event payload
|
|
388
|
-
*/
|
|
389
|
-
export interface OrderCancelEvent {
|
|
390
|
-
retailerId: string;
|
|
391
|
-
name: 'OrderCancel';
|
|
392
|
-
entityRef: string;
|
|
393
|
-
entityType: 'ORDER';
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Order cancel result
|
|
398
|
-
*/
|
|
399
|
-
export interface OrderCancelResult {
|
|
400
|
-
success: boolean;
|
|
401
|
-
orderRef: string;
|
|
402
|
-
eventId?: string;
|
|
403
|
-
error?: string;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* Versori Context Interface
|
|
408
|
-
* Represents the Versori runtime context passed to workflow functions
|
|
409
|
-
*/
|
|
410
|
-
export interface VersoriContext {
|
|
411
|
-
log: {
|
|
412
|
-
info: (message: string, data?: Record<string, unknown>) => void;
|
|
413
|
-
warn: (message: string, data?: Record<string, unknown>) => void;
|
|
414
|
-
error: (message: string, data?: Record<string, unknown>) => void;
|
|
415
|
-
debug?: (message: string, data?: Record<string, unknown>) => void;
|
|
416
|
-
};
|
|
417
|
-
data?: unknown;
|
|
418
|
-
request?: Request;
|
|
419
|
-
activation: {
|
|
420
|
-
getVariable: (name: string) => string | undefined;
|
|
421
|
-
connections?: Record<string, unknown>;
|
|
422
|
-
};
|
|
423
|
-
connections?: Record<string, unknown>;
|
|
424
|
-
}
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
---
|
|
428
|
-
|
|
429
|
-
## 4. Service: Order Cancel Processor (`src/services/order-cancel.service.ts`)
|
|
430
|
-
|
|
431
|
-
```typescript
|
|
432
|
-
/**
|
|
433
|
-
* Order Cancel Service
|
|
434
|
-
*
|
|
435
|
-
* Processes order cancel requests: extracts order reference from JSON payload,
|
|
436
|
-
* builds OrderCancel event, and sends to Fluent Commerce Event API.
|
|
437
|
-
*/
|
|
438
|
-
|
|
439
|
-
import {
|
|
440
|
-
createClient,
|
|
441
|
-
JSONParserService,
|
|
442
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
443
|
-
import type { FluentClient } from '@fluentcommerce/fc-connect-sdk';
|
|
444
|
-
import type {
|
|
445
|
-
OrderCancelPayload,
|
|
446
|
-
OrderCancelResult,
|
|
447
|
-
VersoriContext,
|
|
448
|
-
} from '../types/order-cancel.types';
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* Extract order reference from JSON payload
|
|
452
|
-
*
|
|
453
|
-
* Supports multiple payload formats:
|
|
454
|
-
* - { orderRef: "ORD-12345" }
|
|
455
|
-
* - { order: { reference: "ORD-12345" } }
|
|
456
|
-
* - { order: { ref: "ORD-12345" } }
|
|
457
|
-
*/
|
|
458
|
-
function extractOrderRef(payload: OrderCancelPayload): string | null {
|
|
459
|
-
// Try direct orderRef field
|
|
460
|
-
if (payload.orderRef && typeof payload.orderRef === 'string') {
|
|
461
|
-
return payload.orderRef;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
// Try nested order.reference
|
|
465
|
-
if (
|
|
466
|
-
payload.order &&
|
|
467
|
-
typeof payload.order === 'object' &&
|
|
468
|
-
'reference' in payload.order
|
|
469
|
-
) {
|
|
470
|
-
const ref = payload.order.reference;
|
|
471
|
-
if (typeof ref === 'string') {
|
|
472
|
-
return ref;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// Try nested order.ref
|
|
477
|
-
if (
|
|
478
|
-
payload.order &&
|
|
479
|
-
typeof payload.order === 'object' &&
|
|
480
|
-
'ref' in payload.order
|
|
481
|
-
) {
|
|
482
|
-
const ref = payload.order.ref;
|
|
483
|
-
if (typeof ref === 'string') {
|
|
484
|
-
return ref;
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
return null;
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
/**
|
|
492
|
-
* Parse webhook payload from Versori context
|
|
493
|
-
*
|
|
494
|
-
* Handles both pre-parsed JSON (ctx.data) and raw request body (ctx.request)
|
|
495
|
-
*/
|
|
496
|
-
async function parseWebhookPayload(
|
|
497
|
-
ctx: VersoriContext
|
|
498
|
-
): Promise<OrderCancelPayload | null> {
|
|
499
|
-
const { log, data, request } = ctx;
|
|
500
|
-
|
|
501
|
-
// Scenario 1: Pre-parsed JSON (Versori auto-parsed)
|
|
502
|
-
if (data && typeof data === 'object') {
|
|
503
|
-
log.info('📥 [PARSE] Using pre-parsed JSON payload', {
|
|
504
|
-
hasData: true,
|
|
505
|
-
dataKeys: Object.keys(data),
|
|
506
|
-
});
|
|
507
|
-
return data as OrderCancelPayload;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// Scenario 2: Raw request body (need to parse)
|
|
511
|
-
if (request && typeof request.text === 'function') {
|
|
512
|
-
log.info('📥 [PARSE] Extracting raw request body');
|
|
513
|
-
try {
|
|
514
|
-
const rawBody = await request.text();
|
|
515
|
-
if (!rawBody || rawBody.trim() === '') {
|
|
516
|
-
log.error('❌ [PARSE] Request body is empty');
|
|
517
|
-
return null;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
const parser = new JSONParserService(log);
|
|
521
|
-
const parsed = await parser.parse(rawBody);
|
|
522
|
-
|
|
523
|
-
log.info('📥 [PARSE] Successfully parsed JSON payload', {
|
|
524
|
-
parsedKeys: Object.keys(parsed),
|
|
525
|
-
});
|
|
526
|
-
|
|
527
|
-
return parsed as OrderCancelPayload;
|
|
528
|
-
} catch (parseError: unknown) {
|
|
529
|
-
const errorMessage =
|
|
530
|
-
parseError instanceof Error ? parseError.message : String(parseError);
|
|
531
|
-
log.error('❌ [PARSE] Failed to parse JSON payload', {
|
|
532
|
-
error: errorMessage,
|
|
533
|
-
});
|
|
534
|
-
return null;
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
log.error('❌ [PARSE] No valid payload found in context');
|
|
539
|
-
return null;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
/**
|
|
543
|
-
* Build OrderCancel event payload
|
|
544
|
-
*/
|
|
545
|
-
function buildOrderCancelEvent(
|
|
546
|
-
orderRef: string,
|
|
547
|
-
retailerId: string
|
|
548
|
-
): {
|
|
549
|
-
retailerId: string;
|
|
550
|
-
name: 'OrderCancel';
|
|
551
|
-
entityRef: string;
|
|
552
|
-
entityType: 'ORDER';
|
|
553
|
-
} {
|
|
554
|
-
return {
|
|
555
|
-
retailerId,
|
|
556
|
-
name: 'OrderCancel',
|
|
557
|
-
entityRef: orderRef,
|
|
558
|
-
entityType: 'ORDER',
|
|
559
|
-
};
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
/**
|
|
563
|
-
* Execute order cancel workflow
|
|
564
|
-
*
|
|
565
|
-
* Main orchestration function:
|
|
566
|
-
* 1. Parse webhook payload
|
|
567
|
-
* 2. Extract order reference
|
|
568
|
-
* 3. Create Fluent client
|
|
569
|
-
* 4. Build event payload
|
|
570
|
-
* 5. Send event to Fluent Commerce
|
|
571
|
-
*/
|
|
572
|
-
export async function executeOrderCancel(
|
|
573
|
-
ctx: VersoriContext
|
|
574
|
-
): Promise<OrderCancelResult> {
|
|
575
|
-
const { log, activation } = ctx;
|
|
576
|
-
|
|
577
|
-
log.info('🚀 [SERVICE] Starting order cancel processing');
|
|
578
|
-
|
|
579
|
-
// STEP 1: Parse webhook payload
|
|
580
|
-
const payload = await parseWebhookPayload(ctx);
|
|
581
|
-
if (!payload) {
|
|
582
|
-
log.error('❌ [SERVICE] Failed to parse webhook payload', {
|
|
583
|
-
hasData: !!ctx.data,
|
|
584
|
-
hasRequest: !!ctx.request,
|
|
585
|
-
});
|
|
586
|
-
throw new Error('Failed to parse webhook payload. Ensure Content-Type: application/json is set in request headers.');
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
log.info('📥 [SERVICE] Payload parsed successfully', {
|
|
590
|
-
payloadKeys: Object.keys(payload),
|
|
591
|
-
});
|
|
592
|
-
|
|
593
|
-
// STEP 2: Extract order reference
|
|
594
|
-
const orderRef = extractOrderRef(payload);
|
|
595
|
-
if (!orderRef) {
|
|
596
|
-
log.error('❌ [SERVICE] Order reference not found in payload', {
|
|
597
|
-
payloadKeys: Object.keys(payload),
|
|
598
|
-
expectedFields: ['orderRef', 'order.reference', 'order.ref'],
|
|
599
|
-
});
|
|
600
|
-
throw new Error(
|
|
601
|
-
'Order reference not found in payload. Expected field: orderRef, order.reference, or order.ref'
|
|
602
|
-
);
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
log.info('✅ [SERVICE] Order reference extracted', { orderRef });
|
|
606
|
-
|
|
607
|
-
// STEP 3: Get retailer ID from activation variable or connection
|
|
608
|
-
const retailerId =
|
|
609
|
-
activation.getVariable('FLUENT_RETAILER_ID') ||
|
|
610
|
-
(activation.connections?.fluent_commerce as any)?.retailerId;
|
|
611
|
-
|
|
612
|
-
if (!retailerId) {
|
|
613
|
-
log.error('❌ [SERVICE] Retailer ID not found', {
|
|
614
|
-
checkedVariables: ['FLUENT_RETAILER_ID'],
|
|
615
|
-
hasConnection: !!activation.connections?.fluent_commerce,
|
|
616
|
-
});
|
|
617
|
-
throw new Error(
|
|
618
|
-
'Retailer ID not found. Set FLUENT_RETAILER_ID activation variable or configure in connection.'
|
|
619
|
-
);
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
log.info('✅ [SERVICE] Retailer ID retrieved', { retailerId });
|
|
623
|
-
|
|
624
|
-
// STEP 4: Create Fluent client
|
|
625
|
-
// ✅ Pass ctx directly - createClient auto-detects Versori context
|
|
626
|
-
const client = await createClient(ctx);
|
|
627
|
-
|
|
628
|
-
log.info('✅ [SERVICE] Fluent client created');
|
|
629
|
-
|
|
630
|
-
// STEP 5: Build event payload
|
|
631
|
-
const eventPayload = buildOrderCancelEvent(orderRef, retailerId);
|
|
632
|
-
|
|
633
|
-
log.info('📤 [SERVICE] Sending OrderCancel event', {
|
|
634
|
-
orderRef,
|
|
635
|
-
retailerId,
|
|
636
|
-
});
|
|
637
|
-
|
|
638
|
-
// STEP 6: Send event to Fluent Commerce
|
|
639
|
-
// ✅ Using 'async' mode (recommended):
|
|
640
|
-
// - Fluent accepts event immediately and processes in background
|
|
641
|
-
// - Returns event ID quickly (non-blocking)
|
|
642
|
-
// - Better performance for webhook responses
|
|
643
|
-
// - Alternative: 'sync' mode waits for event processing (slower, blocking)
|
|
644
|
-
// - Sync mode success: { eventId: "...", eventStatus: "COMPLETE" }
|
|
645
|
-
// - Sync mode failure: { eventStatus: "FAILED" }
|
|
646
|
-
// - Sync mode no match: { eventId: "...", eventStatus: "NO_MATCH" }
|
|
647
|
-
const response = await client.sendEvent(eventPayload, 'async');
|
|
648
|
-
|
|
649
|
-
// Extract event ID from Fluent response
|
|
650
|
-
// Async mode response format: { id: "evt_abc123", ... }
|
|
651
|
-
// Sync mode response format (success): { eventId: "...", eventStatus: "COMPLETE" }
|
|
652
|
-
// Sync mode response format (failure): { eventStatus: "FAILED" }
|
|
653
|
-
// Sync mode response format (no match): { eventId: "...", eventStatus: "NO_MATCH" }
|
|
654
|
-
let eventId: string | undefined;
|
|
655
|
-
|
|
656
|
-
if (response && typeof response === 'object') {
|
|
657
|
-
// Extract event ID first (needed for error messages)
|
|
658
|
-
if ('id' in response) {
|
|
659
|
-
eventId = response.id as string;
|
|
660
|
-
} else if ('eventId' in response) {
|
|
661
|
-
eventId = response.eventId as string;
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
// Check for sync mode failure statuses
|
|
665
|
-
if ('eventStatus' in response) {
|
|
666
|
-
const eventStatus = response.eventStatus as string;
|
|
667
|
-
|
|
668
|
-
if (eventStatus === 'FAILED') {
|
|
669
|
-
log.error('❌ [SERVICE] OrderCancel event failed (sync mode)', {
|
|
670
|
-
orderRef,
|
|
671
|
-
eventId,
|
|
672
|
-
eventStatus,
|
|
673
|
-
response,
|
|
674
|
-
});
|
|
675
|
-
throw new Error('Order cancel event failed. Event status: FAILED');
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
if (eventStatus === 'NO_MATCH') {
|
|
679
|
-
log.error('❌ [SERVICE] OrderCancel event no match (sync mode)', {
|
|
680
|
-
orderRef,
|
|
681
|
-
eventId,
|
|
682
|
-
eventStatus,
|
|
683
|
-
response,
|
|
684
|
-
});
|
|
685
|
-
throw new Error(
|
|
686
|
-
'Order cancel event did not match any workflow. Possible causes: incorrect event name, status mismatch, or entity not found. Event status: NO_MATCH'
|
|
687
|
-
);
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
if (eventStatus === 'COMPLETE') {
|
|
691
|
-
log.info('✅ [SERVICE] OrderCancel event completed (sync mode)', {
|
|
692
|
-
orderRef,
|
|
693
|
-
eventId,
|
|
694
|
-
eventStatus,
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
log.info('✅ [SERVICE] OrderCancel event sent successfully', {
|
|
701
|
-
orderRef,
|
|
702
|
-
eventId,
|
|
703
|
-
});
|
|
704
|
-
|
|
705
|
-
return {
|
|
706
|
-
success: true,
|
|
707
|
-
orderRef,
|
|
708
|
-
eventId,
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
|
-
```
|
|
712
|
-
|
|
713
|
-
---
|
|
714
|
-
|
|
715
|
-
## 5. Configuration
|
|
716
|
-
|
|
717
|
-
### Activation Variables
|
|
718
|
-
|
|
719
|
-
Configure these variables in Versori activation settings:
|
|
720
|
-
|
|
721
|
-
```json
|
|
722
|
-
{
|
|
723
|
-
"FLUENT_RETAILER_ID": "your-retailer-id"
|
|
724
|
-
}
|
|
725
|
-
```
|
|
726
|
-
|
|
727
|
-
**Note:** If using Versori connection for Fluent Commerce, retailer ID can also be configured in the connection settings.
|
|
728
|
-
|
|
729
|
-
### Webhook Connection
|
|
730
|
-
|
|
731
|
-
Create a Versori connection for webhook authentication:
|
|
732
|
-
|
|
733
|
-
1. **Connection Name:** `order-cancel-webhook`
|
|
734
|
-
2. **Type:** API Key or Basic Auth
|
|
735
|
-
3. **Purpose:** Authenticate incoming webhook requests
|
|
736
|
-
|
|
737
|
-
**Example webhook call:**
|
|
738
|
-
|
|
739
|
-
```bash
|
|
740
|
-
curl -X POST https://{workspace}.versori.run/order-cancel \
|
|
741
|
-
-H "Content-Type: application/json" \
|
|
742
|
-
-H "X-API-Key: your-api-key" \
|
|
743
|
-
-d '{
|
|
744
|
-
"orderRef": "ORD-12345"
|
|
745
|
-
}'
|
|
746
|
-
```
|
|
747
|
-
|
|
748
|
-
---
|
|
749
|
-
|
|
750
|
-
## 6. Error Handling
|
|
751
|
-
|
|
752
|
-
The template includes comprehensive error handling:
|
|
753
|
-
|
|
754
|
-
### Payload Parsing Errors
|
|
755
|
-
|
|
756
|
-
- **Empty payload:** Returns error response
|
|
757
|
-
- **Invalid JSON:** Returns error with parse details
|
|
758
|
-
- **Missing order reference:** Returns error with expected field names
|
|
759
|
-
|
|
760
|
-
### Event Sending Errors
|
|
761
|
-
|
|
762
|
-
- **Network errors:** Logged and returned in error response
|
|
763
|
-
- **API errors:** Logged with full error details
|
|
764
|
-
- **Validation errors:** Logged with validation message
|
|
765
|
-
|
|
766
|
-
### Error Response Format
|
|
767
|
-
|
|
768
|
-
**Webhook Processing Errors:**
|
|
769
|
-
```json
|
|
770
|
-
{
|
|
771
|
-
"success": false,
|
|
772
|
-
"error": "Order reference not found in payload. Expected field: orderRef, order.reference, or order.ref"
|
|
773
|
-
}
|
|
774
|
-
```
|
|
775
|
-
|
|
776
|
-
**Event API Sync Mode Responses:**
|
|
777
|
-
|
|
778
|
-
**Success (sync mode):**
|
|
779
|
-
```json
|
|
780
|
-
{
|
|
781
|
-
"eventId": "421d1709-d0af-4d8a-b7b6-75e40c5fc038",
|
|
782
|
-
"eventStatus": "COMPLETE"
|
|
783
|
-
}
|
|
784
|
-
```
|
|
785
|
-
|
|
786
|
-
**Failure (sync mode):**
|
|
787
|
-
```json
|
|
788
|
-
{
|
|
789
|
-
"eventStatus": "FAILED"
|
|
790
|
-
}
|
|
791
|
-
```
|
|
792
|
-
|
|
793
|
-
**No Match (sync mode):**
|
|
794
|
-
Occurs when event name is incorrect, status mismatch, or entity not found:
|
|
795
|
-
```json
|
|
796
|
-
{
|
|
797
|
-
"eventId": "9782c552-033c-47c7-89ea-2b0068fbdd0a",
|
|
798
|
-
"eventStatus": "NO_MATCH"
|
|
799
|
-
}
|
|
800
|
-
```
|
|
801
|
-
|
|
802
|
-
The webhook will catch failures and return:
|
|
803
|
-
```json
|
|
804
|
-
{
|
|
805
|
-
"success": false,
|
|
806
|
-
"error": "Order cancel event failed. Event status: FAILED"
|
|
807
|
-
}
|
|
808
|
-
```
|
|
809
|
-
|
|
810
|
-
Or for NO_MATCH:
|
|
811
|
-
```json
|
|
812
|
-
{
|
|
813
|
-
"success": false,
|
|
814
|
-
"error": "Order cancel event did not match any workflow. Possible causes: incorrect event name, status mismatch, or entity not found. Event status: NO_MATCH"
|
|
815
|
-
}
|
|
816
|
-
```
|
|
817
|
-
|
|
818
|
-
---
|
|
819
|
-
|
|
820
|
-
## 7. Testing
|
|
821
|
-
|
|
822
|
-
### Test with cURL
|
|
823
|
-
|
|
824
|
-
```bash
|
|
825
|
-
# Test order cancel webhook
|
|
826
|
-
curl -X POST https://{workspace}.versori.run/order-cancel \
|
|
827
|
-
-H "Content-Type: application/json" \
|
|
828
|
-
-H "X-API-Key: your-api-key" \
|
|
829
|
-
-d '{
|
|
830
|
-
"orderRef": "ORD-12345"
|
|
831
|
-
}'
|
|
832
|
-
```
|
|
833
|
-
|
|
834
|
-
### Expected Success Response
|
|
835
|
-
|
|
836
|
-
```json
|
|
837
|
-
{
|
|
838
|
-
"success": true,
|
|
839
|
-
"orderRef": "ORD-12345",
|
|
840
|
-
"eventId": "evt_abc123",
|
|
841
|
-
"message": "Order cancel event sent successfully"
|
|
842
|
-
}
|
|
843
|
-
```
|
|
844
|
-
|
|
845
|
-
**Response Details:**
|
|
846
|
-
- `success`: `true` indicates webhook processed successfully
|
|
847
|
-
- `orderRef`: The order reference that was cancelled
|
|
848
|
-
- `eventId`: Fluent Commerce event ID (returned from Event API async endpoint)
|
|
849
|
-
- `message`: Human-readable success message
|
|
850
|
-
|
|
851
|
-
**Event API Mode: `async` (recommended)**
|
|
852
|
-
- Fluent accepts the event immediately and returns an event ID
|
|
853
|
-
- Event processing happens in the background
|
|
854
|
-
- Webhook response includes the event ID for tracking
|
|
855
|
-
- Response format: `{ id: "evt_abc123" }`
|
|
856
|
-
|
|
857
|
-
**Alternative: `sync` mode**
|
|
858
|
-
- Fluent processes the event synchronously before responding
|
|
859
|
-
- Slower response time (waits for event processing)
|
|
860
|
-
- Success response: `{ eventId: "...", eventStatus: "COMPLETE" }`
|
|
861
|
-
- Failure response: `{ eventStatus: "FAILED" }`
|
|
862
|
-
- No match response: `{ eventId: "...", eventStatus: "NO_MATCH" }` (incorrect event name, status mismatch, or entity not found)
|
|
863
|
-
- Use only if you need immediate confirmation of event processing
|
|
864
|
-
|
|
865
|
-
### Expected Error Response
|
|
866
|
-
|
|
867
|
-
```json
|
|
868
|
-
{
|
|
869
|
-
"success": false,
|
|
870
|
-
"error": "Order reference not found in payload"
|
|
871
|
-
}
|
|
872
|
-
```
|
|
873
|
-
|
|
874
|
-
---
|
|
875
|
-
|
|
876
|
-
## 8. Customization
|
|
877
|
-
|
|
878
|
-
### Custom Order Reference Field
|
|
879
|
-
|
|
880
|
-
If your payload uses a different field name, modify `extractOrderRef()` in `order-cancel.service.ts`:
|
|
881
|
-
|
|
882
|
-
```typescript
|
|
883
|
-
function extractOrderRef(payload: OrderCancelPayload): string | null {
|
|
884
|
-
// Add your custom field extraction logic
|
|
885
|
-
if (payload.customOrderId && typeof payload.customOrderId === 'string') {
|
|
886
|
-
return payload.customOrderId;
|
|
887
|
-
}
|
|
888
|
-
// ... existing logic
|
|
889
|
-
}
|
|
890
|
-
```
|
|
891
|
-
|
|
892
|
-
### Custom Event Name
|
|
893
|
-
|
|
894
|
-
To use a different event name, modify `buildOrderCancelEvent()`:
|
|
895
|
-
|
|
896
|
-
```typescript
|
|
897
|
-
function buildOrderCancelEvent(
|
|
898
|
-
orderRef: string,
|
|
899
|
-
retailerId: string
|
|
900
|
-
) {
|
|
901
|
-
return {
|
|
902
|
-
retailerId,
|
|
903
|
-
name: 'CustomOrderCancel', // Change event name
|
|
904
|
-
entityRef: orderRef,
|
|
905
|
-
entityType: 'ORDER',
|
|
906
|
-
};
|
|
907
|
-
}
|
|
908
|
-
```
|
|
909
|
-
|
|
910
|
-
### Additional Event Data
|
|
911
|
-
|
|
912
|
-
To include additional data in the event:
|
|
913
|
-
|
|
914
|
-
```typescript
|
|
915
|
-
function buildOrderCancelEvent(
|
|
916
|
-
orderRef: string,
|
|
917
|
-
retailerId: string,
|
|
918
|
-
additionalData?: Record<string, unknown>
|
|
919
|
-
) {
|
|
920
|
-
return {
|
|
921
|
-
retailerId,
|
|
922
|
-
name: 'OrderCancel',
|
|
923
|
-
entityRef: orderRef,
|
|
924
|
-
entityType: 'ORDER',
|
|
925
|
-
data: additionalData, // Add custom data
|
|
926
|
-
};
|
|
927
|
-
}
|
|
928
|
-
```
|
|
929
|
-
|
|
930
|
-
---
|
|
931
|
-
|
|
932
|
-
## Summary
|
|
933
|
-
|
|
934
|
-
✅ **DO:**
|
|
935
|
-
- Use Versori connection for Fluent Commerce credentials
|
|
936
|
-
- Handle both pre-parsed and raw JSON payloads
|
|
937
|
-
- Extract order reference with fallback patterns
|
|
938
|
-
- Log all steps for debugging
|
|
939
|
-
- Return clear error messages
|
|
940
|
-
|
|
941
|
-
❌ **DON'T:**
|
|
942
|
-
- Hardcode credentials in code
|
|
943
|
-
- Assume payload format without validation
|
|
944
|
-
- Skip error handling
|
|
945
|
-
- Use `sync` mode for Event API (use `async` for better performance and faster webhook responses)
|
|
946
|
-
|
|
947
|
-
---
|
|
948
|
-
|
|
949
|
-
## Next Steps
|
|
950
|
-
|
|
951
|
-
1. **Deploy:** Copy code to your Versori project
|
|
952
|
-
2. **Configure:** Set up Fluent Commerce connection and activation variables
|
|
953
|
-
3. **Test:** Test webhook with sample payloads
|
|
954
|
-
4. **Monitor:** Check Versori logs for event processing
|
|
955
|
-
|
|
956
|
-
For more templates, see:
|
|
957
|
-
- [XML Payload Template](./template-ingestion-payload-xml-order-cancel-event.md)
|
|
958
|
-
- [Other Event API Templates](./event-api-guide.md)
|
|
959
|
-
|
|
1
|
+
---
|
|
2
|
+
template_id: tpl-ingest-payload-json-to-order-cancel-event
|
|
3
|
+
canonical_filename: template-ingestion-payload-json-order-cancel-event.md
|
|
4
|
+
sdk_version: latest
|
|
5
|
+
runtime: versori
|
|
6
|
+
direction: ingestion
|
|
7
|
+
source: payload-json
|
|
8
|
+
destination: fluent-event-api
|
|
9
|
+
entity: order
|
|
10
|
+
format: json
|
|
11
|
+
logging: versori
|
|
12
|
+
status: stable
|
|
13
|
+
features:
|
|
14
|
+
- direct-payload-processing
|
|
15
|
+
- json-parsing
|
|
16
|
+
- event-api-integration
|
|
17
|
+
- error-handling
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Template: Ingestion - Payload JSON to Order Cancel Event
|
|
21
|
+
|
|
22
|
+
**SDK Version:** @fluentcommerce/fc-connect-sdk@latest
|
|
23
|
+
**Last Updated:** 2025-01-24
|
|
24
|
+
**Deployment Target:** Versori Platform
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 📋 Implementation Prompt
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
I need a Versori webhook ingestion that:
|
|
32
|
+
|
|
33
|
+
1) Receives JSON payload directly in webhook request body
|
|
34
|
+
2) Parses JSON to extract order reference
|
|
35
|
+
3) Builds OrderCancel event payload with retailerId, name, entityRef, entityType
|
|
36
|
+
4) Sends event to Fluent Commerce Event API (async)
|
|
37
|
+
5) Returns success/error response
|
|
38
|
+
6) Uses native Versori log from context
|
|
39
|
+
|
|
40
|
+
Use the loaded docs to fill in SDK specifics and best practices.
|
|
41
|
+
Keep the structure identical to the template; only adapt where needed.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 📋 Template Overview
|
|
47
|
+
|
|
48
|
+
This connector runs on the Versori platform. It receives JSON payloads directly via webhook, extracts the order reference, and sends OrderCancel events to Fluent Commerce Event API. Most operational settings (Fluent account/connection) are configured via activation variables.
|
|
49
|
+
|
|
50
|
+
### What This Template Does
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
┌────────────────────────────────────────────────────────────────┐
|
|
54
|
+
│ INGESTION WORKFLOW │
|
|
55
|
+
└────────────────────────────────────────────────────────────────┘
|
|
56
|
+
|
|
57
|
+
1. TRIGGER
|
|
58
|
+
└─ Webhook: HTTP POST endpoint receives JSON payload
|
|
59
|
+
|
|
60
|
+
2. RECEIVE PAYLOAD
|
|
61
|
+
├─ Extract JSON from request body (ctx.data or ctx.request)
|
|
62
|
+
├─ Validate payload structure
|
|
63
|
+
└─ Log incoming request
|
|
64
|
+
|
|
65
|
+
3. PARSE JSON
|
|
66
|
+
├─ Parse JSON payload (if raw string)
|
|
67
|
+
├─ Extract order reference field
|
|
68
|
+
└─ Validate required fields
|
|
69
|
+
|
|
70
|
+
4. BUILD EVENT
|
|
71
|
+
├─ Construct OrderCancel event payload
|
|
72
|
+
├─ Set retailerId (from config or payload)
|
|
73
|
+
├─ Set name: "OrderCancel"
|
|
74
|
+
├─ Set entityRef: order reference
|
|
75
|
+
└─ Set entityType: "ORDER"
|
|
76
|
+
|
|
77
|
+
5. SEND EVENT (Event API)
|
|
78
|
+
├─ Send event to Fluent Commerce Event API (async)
|
|
79
|
+
├─ Handle success/error responses
|
|
80
|
+
└─ Log event result
|
|
81
|
+
|
|
82
|
+
6. RETURN RESPONSE
|
|
83
|
+
├─ Return success with event details
|
|
84
|
+
└─ Return error with details if failed
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Key Features
|
|
88
|
+
|
|
89
|
+
- **Direct Payload Processing**: Receives JSON payload directly in webhook request body
|
|
90
|
+
- **JSON Parsing**: Handles both pre-parsed and raw JSON payloads
|
|
91
|
+
- **Event API Integration**: Sends OrderCancel events to Fluent Commerce
|
|
92
|
+
- **Error Handling**: Comprehensive error handling with detailed logging
|
|
93
|
+
- **Native Versori Logging**: Uses Versori log from context
|
|
94
|
+
- **Flexible Order Reference Extraction**: Supports multiple JSON field patterns
|
|
95
|
+
|
|
96
|
+
### 📦 Package Information
|
|
97
|
+
|
|
98
|
+
**SDK:** [@fluentcommerce/fc-connect-sdk](https://www.npmjs.com/package/@fluentcommerce/fc-connect-sdk) `latest`
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm install @fluentcommerce/fc-connect-sdk@latest
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
**Templates are designed for direct deployment; customize via activation variables.**
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 📦 SDK Imports (Verified - Versori Optimized)
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// ✅ VERIFIED IMPORTS - These match actual SDK exports
|
|
114
|
+
import { Buffer } from 'node:buffer'; // Required for Versori/Deno runtime
|
|
115
|
+
import {
|
|
116
|
+
createClient, // Universal client factory
|
|
117
|
+
JSONParserService, // JSON parsing utility
|
|
118
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
119
|
+
|
|
120
|
+
import type { FluentClient } from '@fluentcommerce/fc-connect-sdk';
|
|
121
|
+
|
|
122
|
+
// Versori platform imports
|
|
123
|
+
import { webhook, http } from '@versori/run';
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Note:** All imports are from actual SDK exports - this code compiles and runs as-is.
|
|
127
|
+
|
|
128
|
+
**⚠️ CRITICAL - Buffer Import Required:**
|
|
129
|
+
|
|
130
|
+
The `Buffer` import from `node:buffer` is **required** for Versori/Deno runtime compatibility:
|
|
131
|
+
- Versori and Deno do NOT have `Buffer` as a global (unlike Node.js)
|
|
132
|
+
- Without this import, code will crash with `ReferenceError: Buffer is not defined`
|
|
133
|
+
- Always include this import in Versori templates, even if not directly used in the template code
|
|
134
|
+
- Required for SDK internal operations and any Buffer usage in your code
|
|
135
|
+
|
|
136
|
+
**✅ VERSORI PLATFORM - Use Native Logs:**
|
|
137
|
+
|
|
138
|
+
- Use `log` from context: `const { log } = ctx;`
|
|
139
|
+
- Native Versori logs are simpler and automatically integrated with platform monitoring
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 🔐 Fluent Commerce Connection Setup
|
|
144
|
+
|
|
145
|
+
**✅ BEST PRACTICE:** Store Fluent Commerce credentials in a Versori connection object:
|
|
146
|
+
|
|
147
|
+
**Connection Configuration:**
|
|
148
|
+
|
|
149
|
+
1. **Create Connection in Versori:**
|
|
150
|
+
- Name: `fluent_commerce`
|
|
151
|
+
- Type: HTTP Basic Auth or OAuth2
|
|
152
|
+
- Credentials: Fluent Commerce API credentials
|
|
153
|
+
|
|
154
|
+
2. **Connection Variables:**
|
|
155
|
+
- `FLUENT_BASE_URL` - Fluent Commerce API base URL (e.g., `https://api.fluentcommerce.com`)
|
|
156
|
+
- `FLUENT_RETAILER_ID` - Your retailer ID
|
|
157
|
+
- `FLUENT_CLIENT_ID` - OAuth client ID (if using OAuth2)
|
|
158
|
+
- `FLUENT_CLIENT_SECRET` - OAuth client secret (if using OAuth2)
|
|
159
|
+
|
|
160
|
+
**Benefits:**
|
|
161
|
+
- ✅ Credentials stored securely in Versori vault
|
|
162
|
+
- ✅ Connection can be reused across workflows
|
|
163
|
+
- ✅ No sensitive data in activation variables
|
|
164
|
+
- ✅ Easier credential rotation
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 📄 Expected JSON Payload Format
|
|
169
|
+
|
|
170
|
+
The webhook accepts JSON payloads with order reference information. Multiple formats are supported:
|
|
171
|
+
|
|
172
|
+
### Format 1: Simple Order Reference
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"orderRef": "ORD-12345"
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Format 2: Nested Order Reference
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"order": {
|
|
185
|
+
"reference": "ORD-12345"
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Format 3: With Additional Metadata
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"orderRef": "ORD-12345",
|
|
195
|
+
"reason": "Customer requested cancellation",
|
|
196
|
+
"cancelledBy": "admin@example.com"
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Note:** The template extracts `orderRef` from the payload. Customize the extraction logic in the service if your payload uses different field names.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Event Payload Structure
|
|
205
|
+
|
|
206
|
+
The template builds and sends this event structure:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"retailerId": "{{retailer_id}}",
|
|
211
|
+
"name": "OrderCancel",
|
|
212
|
+
"entityRef": "{{order_ref}}",
|
|
213
|
+
"entityType": "ORDER"
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Fields:**
|
|
218
|
+
- `retailerId`: Retrieved from Fluent Commerce connection or activation variable
|
|
219
|
+
- `name`: Fixed as "OrderCancel"
|
|
220
|
+
- `entityRef`: Extracted from incoming JSON payload
|
|
221
|
+
- `entityType`: Fixed as "ORDER"
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## 🔧 Complete Production Code
|
|
226
|
+
|
|
227
|
+
### Versori Workflows Structure
|
|
228
|
+
|
|
229
|
+
**Key Concept**: Versori workflows are organized by **trigger type** at the first level, then by **specific workflow** with descriptive file names.
|
|
230
|
+
|
|
231
|
+
**Trigger Types:**
|
|
232
|
+
- **`webhook()`** → HTTP-based triggers (event-driven) - Creates HTTP endpoints
|
|
233
|
+
|
|
234
|
+
**Execution Steps (chained to triggers):**
|
|
235
|
+
- **`http()`** → External API calls (chained from webhook)
|
|
236
|
+
|
|
237
|
+
### Recommended Project Structure
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
order-cancel-webhook/
|
|
241
|
+
├── index.ts # Entry point - exports all workflows
|
|
242
|
+
└── src/
|
|
243
|
+
├── workflows/
|
|
244
|
+
│ └── webhook/
|
|
245
|
+
│ └── order-cancel.ts # Webhook: Order cancel handler
|
|
246
|
+
│
|
|
247
|
+
├── services/
|
|
248
|
+
│ └── order-cancel.service.ts # Shared orchestration logic
|
|
249
|
+
│
|
|
250
|
+
└── types/
|
|
251
|
+
└── order-cancel.types.ts # Type definitions
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Benefits:**
|
|
255
|
+
- ✅ Clear structure (webhook handlers in `webhook/`)
|
|
256
|
+
- ✅ Descriptive file names (easy to browse and understand)
|
|
257
|
+
- ✅ Reusable code in `services/` (DRY principle)
|
|
258
|
+
- ✅ Centralized type definitions
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Workflow Files
|
|
263
|
+
|
|
264
|
+
### 1. Webhook Workflow (`src/workflows/webhook/order-cancel.ts`)
|
|
265
|
+
|
|
266
|
+
**Purpose**: Handle order cancel requests via webhook
|
|
267
|
+
**Trigger**: HTTP POST
|
|
268
|
+
**Endpoint**: `POST https://{workspace}.versori.run/order-cancel`
|
|
269
|
+
**Use Cases**: Order cancellation from external systems, manual cancellations
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
import { webhook, http } from '@versori/run';
|
|
273
|
+
import { executeOrderCancel } from '../../services/order-cancel.service';
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Webhook: Order Cancel Handler
|
|
277
|
+
*
|
|
278
|
+
* Endpoint: POST https://{workspace}.versori.run/order-cancel
|
|
279
|
+
* Request body: { "orderRef": "ORD-12345" }
|
|
280
|
+
*
|
|
281
|
+
* Pattern: webhook().then(http()) - needs Fluent API access
|
|
282
|
+
* Uses shared service: order-cancel.service.ts
|
|
283
|
+
*
|
|
284
|
+
* SECURITY: Authentication handled via connection parameter
|
|
285
|
+
* No manual API key validation needed - Versori manages this via connection auth
|
|
286
|
+
*/
|
|
287
|
+
export const orderCancelWebhook = webhook('order-cancel', {
|
|
288
|
+
// ✅ Webhook response mode: 'sync'
|
|
289
|
+
// - HTTP response sent when handler completes
|
|
290
|
+
// - Returns event ID and success status immediately after Fluent accepts event
|
|
291
|
+
// - Alternative: 'async' mode would return immediately (before processing)
|
|
292
|
+
response: { mode: 'sync' },
|
|
293
|
+
connection: 'order-cancel-webhook', // Versori validates API key
|
|
294
|
+
}).then(
|
|
295
|
+
http('process-order-cancel', { connection: 'fluent_commerce' }, async ctx => {
|
|
296
|
+
const { log, data } = ctx;
|
|
297
|
+
|
|
298
|
+
log.info('🚀 [WEBHOOK] Order cancel request received', {
|
|
299
|
+
timestamp: new Date().toISOString(),
|
|
300
|
+
hasPayload: !!data,
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
try {
|
|
304
|
+
// Reuse shared orchestration logic
|
|
305
|
+
const result = await executeOrderCancel(ctx);
|
|
306
|
+
|
|
307
|
+
log.info('✅ [WEBHOOK] Order cancel completed successfully', {
|
|
308
|
+
orderRef: result.orderRef,
|
|
309
|
+
eventId: result.eventId,
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
success: true,
|
|
314
|
+
orderRef: result.orderRef,
|
|
315
|
+
eventId: result.eventId,
|
|
316
|
+
message: 'Order cancel event sent successfully',
|
|
317
|
+
};
|
|
318
|
+
} catch (e: any) {
|
|
319
|
+
log.error('❌ [WEBHOOK] Order cancel failed', {
|
|
320
|
+
message: e?.message,
|
|
321
|
+
stack: e?.stack,
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
return {
|
|
325
|
+
success: false,
|
|
326
|
+
error: e?.message || 'Unknown error occurred',
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
})
|
|
330
|
+
);
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
### 2. Entry Point (`index.ts`)
|
|
336
|
+
|
|
337
|
+
**Purpose**: Register all workflows with Versori platform
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
/**
|
|
341
|
+
* Entry Point - Registers all workflows with Versori platform
|
|
342
|
+
*
|
|
343
|
+
* Versori automatically discovers and registers exported workflows
|
|
344
|
+
*
|
|
345
|
+
* File Structure:
|
|
346
|
+
* - src/workflows/webhook/ → HTTP-based triggers (webhooks)
|
|
347
|
+
* - src/services/ → Shared service logic (reusable across workflows)
|
|
348
|
+
*/
|
|
349
|
+
|
|
350
|
+
// Import webhook workflows
|
|
351
|
+
import { orderCancelWebhook } from './src/workflows/webhook/order-cancel';
|
|
352
|
+
|
|
353
|
+
// Register all workflows with Versori platform
|
|
354
|
+
export {
|
|
355
|
+
// Webhooks (HTTP-based triggers)
|
|
356
|
+
orderCancelWebhook,
|
|
357
|
+
};
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
**What Gets Exposed:**
|
|
361
|
+
- ✅ `orderCancelWebhook` → `https://{workspace}.versori.run/order-cancel`
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## 3. Type Definitions (`src/types/order-cancel.types.ts`)
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
/**
|
|
369
|
+
* Type Definitions for Order Cancel Ingestion
|
|
370
|
+
*
|
|
371
|
+
* Centralized type definitions for order cancel workflow
|
|
372
|
+
*/
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Order cancel request payload
|
|
376
|
+
*/
|
|
377
|
+
export interface OrderCancelPayload {
|
|
378
|
+
orderRef?: string;
|
|
379
|
+
order?: {
|
|
380
|
+
reference?: string;
|
|
381
|
+
ref?: string;
|
|
382
|
+
};
|
|
383
|
+
[key: string]: unknown; // Allow additional fields
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Order cancel event payload
|
|
388
|
+
*/
|
|
389
|
+
export interface OrderCancelEvent {
|
|
390
|
+
retailerId: string;
|
|
391
|
+
name: 'OrderCancel';
|
|
392
|
+
entityRef: string;
|
|
393
|
+
entityType: 'ORDER';
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Order cancel result
|
|
398
|
+
*/
|
|
399
|
+
export interface OrderCancelResult {
|
|
400
|
+
success: boolean;
|
|
401
|
+
orderRef: string;
|
|
402
|
+
eventId?: string;
|
|
403
|
+
error?: string;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Versori Context Interface
|
|
408
|
+
* Represents the Versori runtime context passed to workflow functions
|
|
409
|
+
*/
|
|
410
|
+
export interface VersoriContext {
|
|
411
|
+
log: {
|
|
412
|
+
info: (message: string, data?: Record<string, unknown>) => void;
|
|
413
|
+
warn: (message: string, data?: Record<string, unknown>) => void;
|
|
414
|
+
error: (message: string, data?: Record<string, unknown>) => void;
|
|
415
|
+
debug?: (message: string, data?: Record<string, unknown>) => void;
|
|
416
|
+
};
|
|
417
|
+
data?: unknown;
|
|
418
|
+
request?: Request;
|
|
419
|
+
activation: {
|
|
420
|
+
getVariable: (name: string) => string | undefined;
|
|
421
|
+
connections?: Record<string, unknown>;
|
|
422
|
+
};
|
|
423
|
+
connections?: Record<string, unknown>;
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## 4. Service: Order Cancel Processor (`src/services/order-cancel.service.ts`)
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
/**
|
|
433
|
+
* Order Cancel Service
|
|
434
|
+
*
|
|
435
|
+
* Processes order cancel requests: extracts order reference from JSON payload,
|
|
436
|
+
* builds OrderCancel event, and sends to Fluent Commerce Event API.
|
|
437
|
+
*/
|
|
438
|
+
|
|
439
|
+
import {
|
|
440
|
+
createClient,
|
|
441
|
+
JSONParserService,
|
|
442
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
443
|
+
import type { FluentClient } from '@fluentcommerce/fc-connect-sdk';
|
|
444
|
+
import type {
|
|
445
|
+
OrderCancelPayload,
|
|
446
|
+
OrderCancelResult,
|
|
447
|
+
VersoriContext,
|
|
448
|
+
} from '../types/order-cancel.types';
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Extract order reference from JSON payload
|
|
452
|
+
*
|
|
453
|
+
* Supports multiple payload formats:
|
|
454
|
+
* - { orderRef: "ORD-12345" }
|
|
455
|
+
* - { order: { reference: "ORD-12345" } }
|
|
456
|
+
* - { order: { ref: "ORD-12345" } }
|
|
457
|
+
*/
|
|
458
|
+
function extractOrderRef(payload: OrderCancelPayload): string | null {
|
|
459
|
+
// Try direct orderRef field
|
|
460
|
+
if (payload.orderRef && typeof payload.orderRef === 'string') {
|
|
461
|
+
return payload.orderRef;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// Try nested order.reference
|
|
465
|
+
if (
|
|
466
|
+
payload.order &&
|
|
467
|
+
typeof payload.order === 'object' &&
|
|
468
|
+
'reference' in payload.order
|
|
469
|
+
) {
|
|
470
|
+
const ref = payload.order.reference;
|
|
471
|
+
if (typeof ref === 'string') {
|
|
472
|
+
return ref;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Try nested order.ref
|
|
477
|
+
if (
|
|
478
|
+
payload.order &&
|
|
479
|
+
typeof payload.order === 'object' &&
|
|
480
|
+
'ref' in payload.order
|
|
481
|
+
) {
|
|
482
|
+
const ref = payload.order.ref;
|
|
483
|
+
if (typeof ref === 'string') {
|
|
484
|
+
return ref;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return null;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Parse webhook payload from Versori context
|
|
493
|
+
*
|
|
494
|
+
* Handles both pre-parsed JSON (ctx.data) and raw request body (ctx.request)
|
|
495
|
+
*/
|
|
496
|
+
async function parseWebhookPayload(
|
|
497
|
+
ctx: VersoriContext
|
|
498
|
+
): Promise<OrderCancelPayload | null> {
|
|
499
|
+
const { log, data, request } = ctx;
|
|
500
|
+
|
|
501
|
+
// Scenario 1: Pre-parsed JSON (Versori auto-parsed)
|
|
502
|
+
if (data && typeof data === 'object') {
|
|
503
|
+
log.info('📥 [PARSE] Using pre-parsed JSON payload', {
|
|
504
|
+
hasData: true,
|
|
505
|
+
dataKeys: Object.keys(data),
|
|
506
|
+
});
|
|
507
|
+
return data as OrderCancelPayload;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Scenario 2: Raw request body (need to parse)
|
|
511
|
+
if (request && typeof request.text === 'function') {
|
|
512
|
+
log.info('📥 [PARSE] Extracting raw request body');
|
|
513
|
+
try {
|
|
514
|
+
const rawBody = await request.text();
|
|
515
|
+
if (!rawBody || rawBody.trim() === '') {
|
|
516
|
+
log.error('❌ [PARSE] Request body is empty');
|
|
517
|
+
return null;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
const parser = new JSONParserService(log);
|
|
521
|
+
const parsed = await parser.parse(rawBody);
|
|
522
|
+
|
|
523
|
+
log.info('📥 [PARSE] Successfully parsed JSON payload', {
|
|
524
|
+
parsedKeys: Object.keys(parsed),
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
return parsed as OrderCancelPayload;
|
|
528
|
+
} catch (parseError: unknown) {
|
|
529
|
+
const errorMessage =
|
|
530
|
+
parseError instanceof Error ? parseError.message : String(parseError);
|
|
531
|
+
log.error('❌ [PARSE] Failed to parse JSON payload', {
|
|
532
|
+
error: errorMessage,
|
|
533
|
+
});
|
|
534
|
+
return null;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
log.error('❌ [PARSE] No valid payload found in context');
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Build OrderCancel event payload
|
|
544
|
+
*/
|
|
545
|
+
function buildOrderCancelEvent(
|
|
546
|
+
orderRef: string,
|
|
547
|
+
retailerId: string
|
|
548
|
+
): {
|
|
549
|
+
retailerId: string;
|
|
550
|
+
name: 'OrderCancel';
|
|
551
|
+
entityRef: string;
|
|
552
|
+
entityType: 'ORDER';
|
|
553
|
+
} {
|
|
554
|
+
return {
|
|
555
|
+
retailerId,
|
|
556
|
+
name: 'OrderCancel',
|
|
557
|
+
entityRef: orderRef,
|
|
558
|
+
entityType: 'ORDER',
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Execute order cancel workflow
|
|
564
|
+
*
|
|
565
|
+
* Main orchestration function:
|
|
566
|
+
* 1. Parse webhook payload
|
|
567
|
+
* 2. Extract order reference
|
|
568
|
+
* 3. Create Fluent client
|
|
569
|
+
* 4. Build event payload
|
|
570
|
+
* 5. Send event to Fluent Commerce
|
|
571
|
+
*/
|
|
572
|
+
export async function executeOrderCancel(
|
|
573
|
+
ctx: VersoriContext
|
|
574
|
+
): Promise<OrderCancelResult> {
|
|
575
|
+
const { log, activation } = ctx;
|
|
576
|
+
|
|
577
|
+
log.info('🚀 [SERVICE] Starting order cancel processing');
|
|
578
|
+
|
|
579
|
+
// STEP 1: Parse webhook payload
|
|
580
|
+
const payload = await parseWebhookPayload(ctx);
|
|
581
|
+
if (!payload) {
|
|
582
|
+
log.error('❌ [SERVICE] Failed to parse webhook payload', {
|
|
583
|
+
hasData: !!ctx.data,
|
|
584
|
+
hasRequest: !!ctx.request,
|
|
585
|
+
});
|
|
586
|
+
throw new Error('Failed to parse webhook payload. Ensure Content-Type: application/json is set in request headers.');
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
log.info('📥 [SERVICE] Payload parsed successfully', {
|
|
590
|
+
payloadKeys: Object.keys(payload),
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
// STEP 2: Extract order reference
|
|
594
|
+
const orderRef = extractOrderRef(payload);
|
|
595
|
+
if (!orderRef) {
|
|
596
|
+
log.error('❌ [SERVICE] Order reference not found in payload', {
|
|
597
|
+
payloadKeys: Object.keys(payload),
|
|
598
|
+
expectedFields: ['orderRef', 'order.reference', 'order.ref'],
|
|
599
|
+
});
|
|
600
|
+
throw new Error(
|
|
601
|
+
'Order reference not found in payload. Expected field: orderRef, order.reference, or order.ref'
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
log.info('✅ [SERVICE] Order reference extracted', { orderRef });
|
|
606
|
+
|
|
607
|
+
// STEP 3: Get retailer ID from activation variable or connection
|
|
608
|
+
const retailerId =
|
|
609
|
+
activation.getVariable('FLUENT_RETAILER_ID') ||
|
|
610
|
+
(activation.connections?.fluent_commerce as any)?.retailerId;
|
|
611
|
+
|
|
612
|
+
if (!retailerId) {
|
|
613
|
+
log.error('❌ [SERVICE] Retailer ID not found', {
|
|
614
|
+
checkedVariables: ['FLUENT_RETAILER_ID'],
|
|
615
|
+
hasConnection: !!activation.connections?.fluent_commerce,
|
|
616
|
+
});
|
|
617
|
+
throw new Error(
|
|
618
|
+
'Retailer ID not found. Set FLUENT_RETAILER_ID activation variable or configure in connection.'
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
log.info('✅ [SERVICE] Retailer ID retrieved', { retailerId });
|
|
623
|
+
|
|
624
|
+
// STEP 4: Create Fluent client
|
|
625
|
+
// ✅ Pass ctx directly - createClient auto-detects Versori context
|
|
626
|
+
const client = await createClient(ctx);
|
|
627
|
+
|
|
628
|
+
log.info('✅ [SERVICE] Fluent client created');
|
|
629
|
+
|
|
630
|
+
// STEP 5: Build event payload
|
|
631
|
+
const eventPayload = buildOrderCancelEvent(orderRef, retailerId);
|
|
632
|
+
|
|
633
|
+
log.info('📤 [SERVICE] Sending OrderCancel event', {
|
|
634
|
+
orderRef,
|
|
635
|
+
retailerId,
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
// STEP 6: Send event to Fluent Commerce
|
|
639
|
+
// ✅ Using 'async' mode (recommended):
|
|
640
|
+
// - Fluent accepts event immediately and processes in background
|
|
641
|
+
// - Returns event ID quickly (non-blocking)
|
|
642
|
+
// - Better performance for webhook responses
|
|
643
|
+
// - Alternative: 'sync' mode waits for event processing (slower, blocking)
|
|
644
|
+
// - Sync mode success: { eventId: "...", eventStatus: "COMPLETE" }
|
|
645
|
+
// - Sync mode failure: { eventStatus: "FAILED" }
|
|
646
|
+
// - Sync mode no match: { eventId: "...", eventStatus: "NO_MATCH" }
|
|
647
|
+
const response = await client.sendEvent(eventPayload, 'async');
|
|
648
|
+
|
|
649
|
+
// Extract event ID from Fluent response
|
|
650
|
+
// Async mode response format: { id: "evt_abc123", ... }
|
|
651
|
+
// Sync mode response format (success): { eventId: "...", eventStatus: "COMPLETE" }
|
|
652
|
+
// Sync mode response format (failure): { eventStatus: "FAILED" }
|
|
653
|
+
// Sync mode response format (no match): { eventId: "...", eventStatus: "NO_MATCH" }
|
|
654
|
+
let eventId: string | undefined;
|
|
655
|
+
|
|
656
|
+
if (response && typeof response === 'object') {
|
|
657
|
+
// Extract event ID first (needed for error messages)
|
|
658
|
+
if ('id' in response) {
|
|
659
|
+
eventId = response.id as string;
|
|
660
|
+
} else if ('eventId' in response) {
|
|
661
|
+
eventId = response.eventId as string;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// Check for sync mode failure statuses
|
|
665
|
+
if ('eventStatus' in response) {
|
|
666
|
+
const eventStatus = response.eventStatus as string;
|
|
667
|
+
|
|
668
|
+
if (eventStatus === 'FAILED') {
|
|
669
|
+
log.error('❌ [SERVICE] OrderCancel event failed (sync mode)', {
|
|
670
|
+
orderRef,
|
|
671
|
+
eventId,
|
|
672
|
+
eventStatus,
|
|
673
|
+
response,
|
|
674
|
+
});
|
|
675
|
+
throw new Error('Order cancel event failed. Event status: FAILED');
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
if (eventStatus === 'NO_MATCH') {
|
|
679
|
+
log.error('❌ [SERVICE] OrderCancel event no match (sync mode)', {
|
|
680
|
+
orderRef,
|
|
681
|
+
eventId,
|
|
682
|
+
eventStatus,
|
|
683
|
+
response,
|
|
684
|
+
});
|
|
685
|
+
throw new Error(
|
|
686
|
+
'Order cancel event did not match any workflow. Possible causes: incorrect event name, status mismatch, or entity not found. Event status: NO_MATCH'
|
|
687
|
+
);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
if (eventStatus === 'COMPLETE') {
|
|
691
|
+
log.info('✅ [SERVICE] OrderCancel event completed (sync mode)', {
|
|
692
|
+
orderRef,
|
|
693
|
+
eventId,
|
|
694
|
+
eventStatus,
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
log.info('✅ [SERVICE] OrderCancel event sent successfully', {
|
|
701
|
+
orderRef,
|
|
702
|
+
eventId,
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
return {
|
|
706
|
+
success: true,
|
|
707
|
+
orderRef,
|
|
708
|
+
eventId,
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
715
|
+
## 5. Configuration
|
|
716
|
+
|
|
717
|
+
### Activation Variables
|
|
718
|
+
|
|
719
|
+
Configure these variables in Versori activation settings:
|
|
720
|
+
|
|
721
|
+
```json
|
|
722
|
+
{
|
|
723
|
+
"FLUENT_RETAILER_ID": "your-retailer-id"
|
|
724
|
+
}
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
**Note:** If using Versori connection for Fluent Commerce, retailer ID can also be configured in the connection settings.
|
|
728
|
+
|
|
729
|
+
### Webhook Connection
|
|
730
|
+
|
|
731
|
+
Create a Versori connection for webhook authentication:
|
|
732
|
+
|
|
733
|
+
1. **Connection Name:** `order-cancel-webhook`
|
|
734
|
+
2. **Type:** API Key or Basic Auth
|
|
735
|
+
3. **Purpose:** Authenticate incoming webhook requests
|
|
736
|
+
|
|
737
|
+
**Example webhook call:**
|
|
738
|
+
|
|
739
|
+
```bash
|
|
740
|
+
curl -X POST https://{workspace}.versori.run/order-cancel \
|
|
741
|
+
-H "Content-Type: application/json" \
|
|
742
|
+
-H "X-API-Key: your-api-key" \
|
|
743
|
+
-d '{
|
|
744
|
+
"orderRef": "ORD-12345"
|
|
745
|
+
}'
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
---
|
|
749
|
+
|
|
750
|
+
## 6. Error Handling
|
|
751
|
+
|
|
752
|
+
The template includes comprehensive error handling:
|
|
753
|
+
|
|
754
|
+
### Payload Parsing Errors
|
|
755
|
+
|
|
756
|
+
- **Empty payload:** Returns error response
|
|
757
|
+
- **Invalid JSON:** Returns error with parse details
|
|
758
|
+
- **Missing order reference:** Returns error with expected field names
|
|
759
|
+
|
|
760
|
+
### Event Sending Errors
|
|
761
|
+
|
|
762
|
+
- **Network errors:** Logged and returned in error response
|
|
763
|
+
- **API errors:** Logged with full error details
|
|
764
|
+
- **Validation errors:** Logged with validation message
|
|
765
|
+
|
|
766
|
+
### Error Response Format
|
|
767
|
+
|
|
768
|
+
**Webhook Processing Errors:**
|
|
769
|
+
```json
|
|
770
|
+
{
|
|
771
|
+
"success": false,
|
|
772
|
+
"error": "Order reference not found in payload. Expected field: orderRef, order.reference, or order.ref"
|
|
773
|
+
}
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
**Event API Sync Mode Responses:**
|
|
777
|
+
|
|
778
|
+
**Success (sync mode):**
|
|
779
|
+
```json
|
|
780
|
+
{
|
|
781
|
+
"eventId": "421d1709-d0af-4d8a-b7b6-75e40c5fc038",
|
|
782
|
+
"eventStatus": "COMPLETE"
|
|
783
|
+
}
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
**Failure (sync mode):**
|
|
787
|
+
```json
|
|
788
|
+
{
|
|
789
|
+
"eventStatus": "FAILED"
|
|
790
|
+
}
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
**No Match (sync mode):**
|
|
794
|
+
Occurs when event name is incorrect, status mismatch, or entity not found:
|
|
795
|
+
```json
|
|
796
|
+
{
|
|
797
|
+
"eventId": "9782c552-033c-47c7-89ea-2b0068fbdd0a",
|
|
798
|
+
"eventStatus": "NO_MATCH"
|
|
799
|
+
}
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
The webhook will catch failures and return:
|
|
803
|
+
```json
|
|
804
|
+
{
|
|
805
|
+
"success": false,
|
|
806
|
+
"error": "Order cancel event failed. Event status: FAILED"
|
|
807
|
+
}
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
Or for NO_MATCH:
|
|
811
|
+
```json
|
|
812
|
+
{
|
|
813
|
+
"success": false,
|
|
814
|
+
"error": "Order cancel event did not match any workflow. Possible causes: incorrect event name, status mismatch, or entity not found. Event status: NO_MATCH"
|
|
815
|
+
}
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
---
|
|
819
|
+
|
|
820
|
+
## 7. Testing
|
|
821
|
+
|
|
822
|
+
### Test with cURL
|
|
823
|
+
|
|
824
|
+
```bash
|
|
825
|
+
# Test order cancel webhook
|
|
826
|
+
curl -X POST https://{workspace}.versori.run/order-cancel \
|
|
827
|
+
-H "Content-Type: application/json" \
|
|
828
|
+
-H "X-API-Key: your-api-key" \
|
|
829
|
+
-d '{
|
|
830
|
+
"orderRef": "ORD-12345"
|
|
831
|
+
}'
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
### Expected Success Response
|
|
835
|
+
|
|
836
|
+
```json
|
|
837
|
+
{
|
|
838
|
+
"success": true,
|
|
839
|
+
"orderRef": "ORD-12345",
|
|
840
|
+
"eventId": "evt_abc123",
|
|
841
|
+
"message": "Order cancel event sent successfully"
|
|
842
|
+
}
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
**Response Details:**
|
|
846
|
+
- `success`: `true` indicates webhook processed successfully
|
|
847
|
+
- `orderRef`: The order reference that was cancelled
|
|
848
|
+
- `eventId`: Fluent Commerce event ID (returned from Event API async endpoint)
|
|
849
|
+
- `message`: Human-readable success message
|
|
850
|
+
|
|
851
|
+
**Event API Mode: `async` (recommended)**
|
|
852
|
+
- Fluent accepts the event immediately and returns an event ID
|
|
853
|
+
- Event processing happens in the background
|
|
854
|
+
- Webhook response includes the event ID for tracking
|
|
855
|
+
- Response format: `{ id: "evt_abc123" }`
|
|
856
|
+
|
|
857
|
+
**Alternative: `sync` mode**
|
|
858
|
+
- Fluent processes the event synchronously before responding
|
|
859
|
+
- Slower response time (waits for event processing)
|
|
860
|
+
- Success response: `{ eventId: "...", eventStatus: "COMPLETE" }`
|
|
861
|
+
- Failure response: `{ eventStatus: "FAILED" }`
|
|
862
|
+
- No match response: `{ eventId: "...", eventStatus: "NO_MATCH" }` (incorrect event name, status mismatch, or entity not found)
|
|
863
|
+
- Use only if you need immediate confirmation of event processing
|
|
864
|
+
|
|
865
|
+
### Expected Error Response
|
|
866
|
+
|
|
867
|
+
```json
|
|
868
|
+
{
|
|
869
|
+
"success": false,
|
|
870
|
+
"error": "Order reference not found in payload"
|
|
871
|
+
}
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
---
|
|
875
|
+
|
|
876
|
+
## 8. Customization
|
|
877
|
+
|
|
878
|
+
### Custom Order Reference Field
|
|
879
|
+
|
|
880
|
+
If your payload uses a different field name, modify `extractOrderRef()` in `order-cancel.service.ts`:
|
|
881
|
+
|
|
882
|
+
```typescript
|
|
883
|
+
function extractOrderRef(payload: OrderCancelPayload): string | null {
|
|
884
|
+
// Add your custom field extraction logic
|
|
885
|
+
if (payload.customOrderId && typeof payload.customOrderId === 'string') {
|
|
886
|
+
return payload.customOrderId;
|
|
887
|
+
}
|
|
888
|
+
// ... existing logic
|
|
889
|
+
}
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
### Custom Event Name
|
|
893
|
+
|
|
894
|
+
To use a different event name, modify `buildOrderCancelEvent()`:
|
|
895
|
+
|
|
896
|
+
```typescript
|
|
897
|
+
function buildOrderCancelEvent(
|
|
898
|
+
orderRef: string,
|
|
899
|
+
retailerId: string
|
|
900
|
+
) {
|
|
901
|
+
return {
|
|
902
|
+
retailerId,
|
|
903
|
+
name: 'CustomOrderCancel', // Change event name
|
|
904
|
+
entityRef: orderRef,
|
|
905
|
+
entityType: 'ORDER',
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
### Additional Event Data
|
|
911
|
+
|
|
912
|
+
To include additional data in the event:
|
|
913
|
+
|
|
914
|
+
```typescript
|
|
915
|
+
function buildOrderCancelEvent(
|
|
916
|
+
orderRef: string,
|
|
917
|
+
retailerId: string,
|
|
918
|
+
additionalData?: Record<string, unknown>
|
|
919
|
+
) {
|
|
920
|
+
return {
|
|
921
|
+
retailerId,
|
|
922
|
+
name: 'OrderCancel',
|
|
923
|
+
entityRef: orderRef,
|
|
924
|
+
entityType: 'ORDER',
|
|
925
|
+
data: additionalData, // Add custom data
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
---
|
|
931
|
+
|
|
932
|
+
## Summary
|
|
933
|
+
|
|
934
|
+
✅ **DO:**
|
|
935
|
+
- Use Versori connection for Fluent Commerce credentials
|
|
936
|
+
- Handle both pre-parsed and raw JSON payloads
|
|
937
|
+
- Extract order reference with fallback patterns
|
|
938
|
+
- Log all steps for debugging
|
|
939
|
+
- Return clear error messages
|
|
940
|
+
|
|
941
|
+
❌ **DON'T:**
|
|
942
|
+
- Hardcode credentials in code
|
|
943
|
+
- Assume payload format without validation
|
|
944
|
+
- Skip error handling
|
|
945
|
+
- Use `sync` mode for Event API (use `async` for better performance and faster webhook responses)
|
|
946
|
+
|
|
947
|
+
---
|
|
948
|
+
|
|
949
|
+
## Next Steps
|
|
950
|
+
|
|
951
|
+
1. **Deploy:** Copy code to your Versori project
|
|
952
|
+
2. **Configure:** Set up Fluent Commerce connection and activation variables
|
|
953
|
+
3. **Test:** Test webhook with sample payloads
|
|
954
|
+
4. **Monitor:** Check Versori logs for event processing
|
|
955
|
+
|
|
956
|
+
For more templates, see:
|
|
957
|
+
- [XML Payload Template](./template-ingestion-payload-xml-order-cancel-event.md)
|
|
958
|
+
- [Other Event API Templates](./event-api-guide.md)
|
|
959
|
+
|