@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,699 +1,699 @@
|
|
|
1
|
-
# Module 4: Integration Testing
|
|
2
|
-
|
|
3
|
-
**Level:** Intermediate
|
|
4
|
-
**Estimated Time:** 35 minutes
|
|
5
|
-
|
|
6
|
-
## Overview
|
|
7
|
-
|
|
8
|
-
This module covers end-to-end integration testing, combining multiple testers to validate complete data pipelines. You'll learn how to test ingestion workflows, measure performance, and ensure reliability.
|
|
9
|
-
|
|
10
|
-
## Learning Objectives
|
|
11
|
-
|
|
12
|
-
By the end of this module, you will:
|
|
13
|
-
- ✅ Understand how to build end-to-end integration tests
|
|
14
|
-
- ✅ Know how to test complete ingestion pipelines
|
|
15
|
-
- ✅ Be able to measure and optimize performance
|
|
16
|
-
- ✅ Understand load testing patterns
|
|
17
|
-
|
|
18
|
-
## End-to-End Ingestion Test
|
|
19
|
-
|
|
20
|
-
Test a complete ingestion pipeline from S3 to Fluent Commerce:
|
|
21
|
-
|
|
22
|
-
```typescript
|
|
23
|
-
import {
|
|
24
|
-
S3SDKTester,
|
|
25
|
-
FluentConnectionTester,
|
|
26
|
-
createClient,
|
|
27
|
-
S3DataSource,
|
|
28
|
-
CSVParserService,
|
|
29
|
-
UniversalMapper
|
|
30
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
31
|
-
|
|
32
|
-
async function testIngestionPipeline() {
|
|
33
|
-
console.log('Starting end-to-end ingestion test...');
|
|
34
|
-
|
|
35
|
-
// Step 1: Test S3 connectivity
|
|
36
|
-
console.log('Step 1: Testing S3 connectivity...');
|
|
37
|
-
const s3Tester = new S3SDKTester({
|
|
38
|
-
region: 'us-east-1',
|
|
39
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
40
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const s3Result = await s3Tester.testAll('test-data');
|
|
44
|
-
if (!s3Result.summary.passed) {
|
|
45
|
-
throw new Error('S3 connectivity test failed');
|
|
46
|
-
}
|
|
47
|
-
console.log('✅ S3 connectivity validated');
|
|
48
|
-
|
|
49
|
-
// Step 2: Test Fluent connectivity
|
|
50
|
-
console.log('Step 2: Testing Fluent API connectivity...');
|
|
51
|
-
const client = await createClient({
|
|
52
|
-
config: {
|
|
53
|
-
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
54
|
-
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
55
|
-
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
56
|
-
username: process.env.FLUENT_USERNAME!,
|
|
57
|
-
password: process.env.FLUENT_PASSWORD!,
|
|
58
|
-
retailerId: '1'
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
const fluentTester = new FluentConnectionTester(client, {
|
|
63
|
-
logger: console
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
const fluentResult = await fluentTester.testConnection();
|
|
67
|
-
if (!fluentResult.success) {
|
|
68
|
-
throw new Error('Fluent connectivity test failed');
|
|
69
|
-
}
|
|
70
|
-
console.log('✅ Fluent API connectivity validated');
|
|
71
|
-
|
|
72
|
-
// Step 3: Upload test data to S3 (done via S3DataSource below)
|
|
73
|
-
console.log('Step 3: Uploading test inventory data...');
|
|
74
|
-
const testData = 'SKU,QTY,LOCATION\nTEST001,100,DC01\nTEST002,50,DC02\nTEST003,75,DC01';
|
|
75
|
-
|
|
76
|
-
// Step 4: Run ingestion using building blocks
|
|
77
|
-
console.log('Step 4: Running ingestion with SDK building blocks...');
|
|
78
|
-
const startTime = Date.now();
|
|
79
|
-
|
|
80
|
-
// Initialize components
|
|
81
|
-
const s3 = new S3DataSource({
|
|
82
|
-
type: 'S3_CSV',
|
|
83
|
-
connectionId: 'test-s3',
|
|
84
|
-
name: 'Test S3',
|
|
85
|
-
s3Config: {
|
|
86
|
-
bucket: 'test-data',
|
|
87
|
-
region: 'us-east-1',
|
|
88
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
89
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const parser = new CSVParserService();
|
|
94
|
-
const mapper = new UniversalMapper({
|
|
95
|
-
fields: {
|
|
96
|
-
ref: { source: 'SKU', required: true },
|
|
97
|
-
qty: { source: 'QTY', resolver: 'sdk.parseInt' },
|
|
98
|
-
locationRef: { source: 'LOCATION', required: true }
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// Download and parse
|
|
103
|
-
const csvContent = await s3.downloadFile('test-inventory.csv');
|
|
104
|
-
const records = await parser.parse(csvContent);
|
|
105
|
-
|
|
106
|
-
// Map records
|
|
107
|
-
const inventory = [];
|
|
108
|
-
const errors = [];
|
|
109
|
-
for (const record of records) {
|
|
110
|
-
const result = await mapper.map(record);
|
|
111
|
-
if (result.success) {
|
|
112
|
-
inventory.push(result.data);
|
|
113
|
-
} else {
|
|
114
|
-
errors.push({ record, errors: result.errors });
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Create job and send batch
|
|
119
|
-
const job = await client.createJob({
|
|
120
|
-
name: 'Test Inventory Ingestion',
|
|
121
|
-
retailerId: '1'
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
await client.sendBatch(job.id, {
|
|
125
|
-
action: 'UPSERT',
|
|
126
|
-
entityType: 'INVENTORY',
|
|
127
|
-
entities: inventory
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const duration = Date.now() - startTime;
|
|
131
|
-
|
|
132
|
-
// Step 5: Verify results
|
|
133
|
-
console.log('Step 5: Verifying ingestion results...');
|
|
134
|
-
const ingestionResult = {
|
|
135
|
-
success: errors.length === 0,
|
|
136
|
-
processedCount: inventory.length,
|
|
137
|
-
errors,
|
|
138
|
-
duration
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
if (ingestionResult.success) {
|
|
142
|
-
console.log('✅ End-to-end test passed!');
|
|
143
|
-
console.log(` Records processed: ${ingestionResult.processedCount}`);
|
|
144
|
-
console.log(` Duration: ${ingestionResult.duration}ms`);
|
|
145
|
-
} else {
|
|
146
|
-
console.error('❌ Ingestion had errors:', ingestionResult.errors);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Step 6: Cleanup (handled by S3 service)
|
|
150
|
-
console.log('Step 6: Test complete');
|
|
151
|
-
|
|
152
|
-
return ingestionResult;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Run test
|
|
156
|
-
testIngestionPipeline()
|
|
157
|
-
.then(result => {
|
|
158
|
-
console.log('Integration test completed:', result.success ? '✅' : ');
|
|
159
|
-
process.exit(result.success ? 0 : 1);
|
|
160
|
-
})
|
|
161
|
-
.catch(error => {
|
|
162
|
-
console.error('Integration test failed:', error);
|
|
163
|
-
process.exit(1);
|
|
164
|
-
});
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
## Testing Different Data Flows
|
|
168
|
-
|
|
169
|
-
### Test CSV Ingestion
|
|
170
|
-
|
|
171
|
-
```typescript
|
|
172
|
-
async function testCSVIngestion() {
|
|
173
|
-
// Create test CSV data
|
|
174
|
-
const csvData = `
|
|
175
|
-
sku,quantity,location,status
|
|
176
|
-
SKU001,100,WH001,available
|
|
177
|
-
SKU002,50,WH001,available
|
|
178
|
-
SKU003,75,WH002,available
|
|
179
|
-
`.trim();
|
|
180
|
-
|
|
181
|
-
// Ingest using building blocks
|
|
182
|
-
const s3 = new S3DataSource({
|
|
183
|
-
type: 'S3_CSV',
|
|
184
|
-
connectionId: 'test-s3',
|
|
185
|
-
name: 'Test S3',
|
|
186
|
-
s3Config: { bucket: 'test-bucket', ...s3Credentials }
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
const parser = new CSVParserService();
|
|
190
|
-
const mapper = new UniversalMapper({
|
|
191
|
-
fields: {
|
|
192
|
-
ref: { source: 'sku', required: true },
|
|
193
|
-
qty: { source: 'quantity', resolver: 'sdk.parseInt' },
|
|
194
|
-
locationRef: { source: 'location', required: true },
|
|
195
|
-
status: { source: 'status' }
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
const content = await s3.downloadFile('inventory.csv');
|
|
200
|
-
const records = await parser.parse(content);
|
|
201
|
-
|
|
202
|
-
const inventory = [];
|
|
203
|
-
for (const record of records) {
|
|
204
|
-
const result = await mapper.map(record);
|
|
205
|
-
if (result.success) inventory.push(result.data);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
const job = await client.createJob({ name: 'Test CSV', retailerId: '1' });
|
|
209
|
-
await client.sendBatch(job.id, {
|
|
210
|
-
action: 'UPSERT',
|
|
211
|
-
entityType: 'INVENTORY',
|
|
212
|
-
entities: inventory
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
// Verify
|
|
216
|
-
const result = {
|
|
217
|
-
success: inventory.length > 0,
|
|
218
|
-
processedCount: inventory.length
|
|
219
|
-
};
|
|
220
|
-
console.log(`CSV Ingestion: ${result.success ? '✅' : '}`);
|
|
221
|
-
console.log(`Records: ${result.processedCount}`);
|
|
222
|
-
|
|
223
|
-
return result;
|
|
224
|
-
}
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### Test Parquet Extraction
|
|
228
|
-
|
|
229
|
-
```typescript
|
|
230
|
-
async function testParquetExtraction() {
|
|
231
|
-
// Query inventory from Fluent
|
|
232
|
-
const query = `
|
|
233
|
-
query GetInventory($first: Int!, $after: String) {
|
|
234
|
-
inventoryPositions(first: $first, after: $after) {
|
|
235
|
-
edges {
|
|
236
|
-
node {
|
|
237
|
-
id
|
|
238
|
-
ref
|
|
239
|
-
productRef
|
|
240
|
-
locationRef
|
|
241
|
-
qty
|
|
242
|
-
}
|
|
243
|
-
cursor
|
|
244
|
-
}
|
|
245
|
-
pageInfo {
|
|
246
|
-
hasNextPage
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
`;
|
|
251
|
-
|
|
252
|
-
const result = await client.graphql({
|
|
253
|
-
query,
|
|
254
|
-
variables: { first: 100 },
|
|
255
|
-
pagination: { maxRecords: 1000 }
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
// Transform to Parquet
|
|
259
|
-
const logger = createConsoleLogger();
|
|
260
|
-
const parquetService = new ParquetParserService(logger);
|
|
261
|
-
const parquetBuffer = await parquetService.arrayToParquet(
|
|
262
|
-
result.data.inventoryPositions.edges.map(e => e.node)
|
|
263
|
-
);
|
|
264
|
-
|
|
265
|
-
// Upload to S3
|
|
266
|
-
const s3 = new S3DataSource(s3Config);
|
|
267
|
-
await s3.putObject('output-bucket', 'inventory.parquet', parquetBuffer);
|
|
268
|
-
|
|
269
|
-
// Verify result
|
|
270
|
-
console.log(`Parquet Extraction: ${parquetBuffer ? '✅' : '}`);
|
|
271
|
-
|
|
272
|
-
return !!parquetBuffer;
|
|
273
|
-
}
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
## Performance Testing
|
|
277
|
-
|
|
278
|
-
### Load Testing S3 Operations
|
|
279
|
-
|
|
280
|
-
Test S3 performance under concurrent load:
|
|
281
|
-
|
|
282
|
-
```typescript
|
|
283
|
-
async function loadTestS3(concurrency: number = 10) {
|
|
284
|
-
const s3 = new S3DataSource({
|
|
285
|
-
type: 'S3_CSV',
|
|
286
|
-
connectionId: 'test-s3',
|
|
287
|
-
name: 'Load Test S3',
|
|
288
|
-
s3Config: {
|
|
289
|
-
region: 'us-east-1',
|
|
290
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
291
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
292
|
-
}
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
const startTime = Date.now();
|
|
296
|
-
const promises = [];
|
|
297
|
-
|
|
298
|
-
// Run concurrent write operations
|
|
299
|
-
for (let i = 0; i < concurrency; i++) {
|
|
300
|
-
promises.push(
|
|
301
|
-
s3.putObject('load-test', `test-${i}.txt`, Buffer.from(`Content ${i}`))
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
const results = await Promise.allSettled(promises);
|
|
306
|
-
const duration = Date.now() - startTime;
|
|
307
|
-
|
|
308
|
-
const successCount = results.filter(r => r.status === 'fulfilled').length;
|
|
309
|
-
const failureCount = results.filter(r => r.status === 'rejected').length;
|
|
310
|
-
|
|
311
|
-
console.log('Load Test Results:');
|
|
312
|
-
console.log(' Concurrency:', concurrency);
|
|
313
|
-
console.log(' Duration:', duration, 'ms');
|
|
314
|
-
console.log(' Success:', successCount);
|
|
315
|
-
console.log(' Failures:', failureCount);
|
|
316
|
-
console.log(' Avg time per operation:', duration / concurrency, 'ms');
|
|
317
|
-
console.log(' Operations per second:', (concurrency / (duration / 1000)).toFixed(2));
|
|
318
|
-
|
|
319
|
-
return {
|
|
320
|
-
concurrency,
|
|
321
|
-
duration,
|
|
322
|
-
successCount,
|
|
323
|
-
failureCount,
|
|
324
|
-
avgTimePerOperation: duration / concurrency,
|
|
325
|
-
operationsPerSecond: concurrency / (duration / 1000)
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// Test with increasing load
|
|
330
|
-
async function performanceTest() {
|
|
331
|
-
const loads = [1, 5, 10, 20, 50];
|
|
332
|
-
const results = [];
|
|
333
|
-
|
|
334
|
-
for (const load of loads) {
|
|
335
|
-
console.log(`\nTesting with ${load} concurrent operations...`);
|
|
336
|
-
const result = await loadTestS3(load);
|
|
337
|
-
results.push(result);
|
|
338
|
-
|
|
339
|
-
// Wait between tests
|
|
340
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Analyze results
|
|
344
|
-
console.log('\nPerformance Analysis:');
|
|
345
|
-
results.forEach(r => {
|
|
346
|
-
console.log(`Load ${r.concurrency}:`);
|
|
347
|
-
console.log(` Avg time: ${r.avgTimePerOperation.toFixed(2)}ms`);
|
|
348
|
-
console.log(` Throughput: ${r.operationsPerSecond.toFixed(2)} ops/sec`);
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
// Identify performance degradation
|
|
352
|
-
const baseline = results[0];
|
|
353
|
-
results.forEach((r, i) => {
|
|
354
|
-
if (i === 0) return;
|
|
355
|
-
const degradation = ((r.avgTimePerOperation - baseline.avgTimePerOperation) / baseline.avgTimePerOperation * 100).toFixed(2);
|
|
356
|
-
console.log(`Load ${r.concurrency} degradation: ${degradation}% slower than baseline`);
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
### Load Testing Fluent API
|
|
362
|
-
|
|
363
|
-
```typescript
|
|
364
|
-
async function loadTestFluentAPI(concurrency: number = 10) {
|
|
365
|
-
const client = await createClient({ config: fluentConfig });
|
|
366
|
-
const startTime = Date.now();
|
|
367
|
-
const promises = [];
|
|
368
|
-
|
|
369
|
-
// Run concurrent GraphQL queries
|
|
370
|
-
const query = `
|
|
371
|
-
query GetInventoryPosition($ref: String!) {
|
|
372
|
-
inventoryPosition(ref: $ref) {
|
|
373
|
-
id
|
|
374
|
-
ref
|
|
375
|
-
qty
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
`;
|
|
379
|
-
|
|
380
|
-
for (let i = 0; i < concurrency; i++) {
|
|
381
|
-
promises.push(
|
|
382
|
-
client.graphql({
|
|
383
|
-
query,
|
|
384
|
-
variables: { ref: `TEST${i}` }
|
|
385
|
-
})
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
const results = await Promise.all(promises.map(p =>
|
|
390
|
-
p.then(() => ({ success: true }))
|
|
391
|
-
.catch(error => ({ success: false, error }))
|
|
392
|
-
));
|
|
393
|
-
|
|
394
|
-
const duration = Date.now() - startTime;
|
|
395
|
-
const successCount = results.filter(r => r.success).length;
|
|
396
|
-
const failureCount = results.filter(r => !r.success).length;
|
|
397
|
-
|
|
398
|
-
console.log('Fluent API Load Test:');
|
|
399
|
-
console.log(' Concurrency:', concurrency);
|
|
400
|
-
console.log(' Duration:', duration, 'ms');
|
|
401
|
-
console.log(' Success:', successCount);
|
|
402
|
-
console.log(' Failures:', failureCount);
|
|
403
|
-
console.log(' Avg response time:', duration / concurrency, 'ms');
|
|
404
|
-
|
|
405
|
-
return {
|
|
406
|
-
concurrency,
|
|
407
|
-
duration,
|
|
408
|
-
successCount,
|
|
409
|
-
failureCount,
|
|
410
|
-
avgResponseTime: duration / concurrency
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
## Reliability Testing
|
|
416
|
-
|
|
417
|
-
### Retry Logic Testing
|
|
418
|
-
|
|
419
|
-
Test error recovery and retry mechanisms:
|
|
420
|
-
|
|
421
|
-
```typescript
|
|
422
|
-
async function testRetryLogic() {
|
|
423
|
-
let attemptCount = 0;
|
|
424
|
-
const maxAttempts = 3;
|
|
425
|
-
|
|
426
|
-
async function operationWithRetry() {
|
|
427
|
-
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
428
|
-
try {
|
|
429
|
-
attemptCount++;
|
|
430
|
-
console.log(`Attempt ${attempt}/${maxAttempts}...`);
|
|
431
|
-
|
|
432
|
-
// Simulate operation
|
|
433
|
-
const result = await client.graphql({ query });
|
|
434
|
-
|
|
435
|
-
console.log(`✅ Succeeded on attempt ${attempt}`);
|
|
436
|
-
return result;
|
|
437
|
-
} catch (error) {
|
|
438
|
-
if (attempt === maxAttempts) {
|
|
439
|
-
console.error(`❌ Failed after ${maxAttempts} attempts`);
|
|
440
|
-
throw error;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
const backoff = Math.pow(2, attempt) * 1000;
|
|
444
|
-
console.log(`⚠️ Attempt ${attempt} failed, retrying in ${backoff}ms...`);
|
|
445
|
-
await new Promise(resolve => setTimeout(resolve, backoff));
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
try {
|
|
451
|
-
await operationWithRetry();
|
|
452
|
-
console.log(`Total attempts: ${attemptCount}`);
|
|
453
|
-
return true;
|
|
454
|
-
} catch (error) {
|
|
455
|
-
console.error('Operation failed after retries:', error);
|
|
456
|
-
return false;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
```
|
|
460
|
-
|
|
461
|
-
### Circuit Breaker Testing
|
|
462
|
-
|
|
463
|
-
Test circuit breaker patterns:
|
|
464
|
-
|
|
465
|
-
```typescript
|
|
466
|
-
class CircuitBreaker {
|
|
467
|
-
private failures = 0;
|
|
468
|
-
private lastFailureTime = 0;
|
|
469
|
-
private state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED';
|
|
470
|
-
|
|
471
|
-
constructor(
|
|
472
|
-
private threshold: number = 5,
|
|
473
|
-
private timeout: number = 60000
|
|
474
|
-
) {}
|
|
475
|
-
|
|
476
|
-
async execute<T>(operation: () => Promise<T>): Promise<T> {
|
|
477
|
-
if (this.state === 'OPEN') {
|
|
478
|
-
if (Date.now() - this.lastFailureTime > this.timeout) {
|
|
479
|
-
this.state = 'HALF_OPEN';
|
|
480
|
-
console.log('Circuit breaker: HALF_OPEN');
|
|
481
|
-
} else {
|
|
482
|
-
throw new Error('Circuit breaker is OPEN');
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
try {
|
|
487
|
-
const result = await operation();
|
|
488
|
-
this.onSuccess();
|
|
489
|
-
return result;
|
|
490
|
-
} catch (error) {
|
|
491
|
-
this.onFailure();
|
|
492
|
-
throw error;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
private onSuccess() {
|
|
497
|
-
this.failures = 0;
|
|
498
|
-
if (this.state === 'HALF_OPEN') {
|
|
499
|
-
this.state = 'CLOSED';
|
|
500
|
-
console.log('Circuit breaker: CLOSED');
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
private onFailure() {
|
|
505
|
-
this.failures++;
|
|
506
|
-
this.lastFailureTime = Date.now();
|
|
507
|
-
|
|
508
|
-
if (this.failures >= this.threshold) {
|
|
509
|
-
this.state = 'OPEN';
|
|
510
|
-
console.log('Circuit breaker: OPEN');
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
getState() {
|
|
515
|
-
return this.state;
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
// Test circuit breaker
|
|
520
|
-
async function testCircuitBreaker() {
|
|
521
|
-
const breaker = new CircuitBreaker(3, 5000);
|
|
522
|
-
|
|
523
|
-
// Simulate failures
|
|
524
|
-
for (let i = 0; i < 5; i++) {
|
|
525
|
-
try {
|
|
526
|
-
await breaker.execute(async () => {
|
|
527
|
-
throw new Error('Simulated failure');
|
|
528
|
-
});
|
|
529
|
-
} catch (error) {
|
|
530
|
-
console.log(`Request ${i + 1}:`, error.message);
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
console.log('Circuit breaker state:', breaker.getState());
|
|
535
|
-
}
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
## Complete Integration Test Suite
|
|
539
|
-
|
|
540
|
-
```typescript
|
|
541
|
-
import {
|
|
542
|
-
S3SDKTester,
|
|
543
|
-
FluentConnectionTester,
|
|
544
|
-
createClient
|
|
545
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
546
|
-
|
|
547
|
-
class IntegrationTestSuite {
|
|
548
|
-
private s3Tester: S3SDKTester;
|
|
549
|
-
private fluentTester: FluentConnectionTester;
|
|
550
|
-
private client: any;
|
|
551
|
-
|
|
552
|
-
async setup() {
|
|
553
|
-
console.log('Setting up integration test suite...');
|
|
554
|
-
|
|
555
|
-
// Initialize S3 tester
|
|
556
|
-
this.s3Tester = new S3SDKTester({
|
|
557
|
-
region: process.env.AWS_REGION!,
|
|
558
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
559
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
// Initialize Fluent client
|
|
563
|
-
this.client = await createClient({
|
|
564
|
-
config: {
|
|
565
|
-
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
566
|
-
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
567
|
-
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
568
|
-
username: process.env.FLUENT_USERNAME!,
|
|
569
|
-
password: process.env.FLUENT_PASSWORD!,
|
|
570
|
-
retailerId: process.env.FLUENT_RETAILER_ID!
|
|
571
|
-
}
|
|
572
|
-
});
|
|
573
|
-
|
|
574
|
-
// Initialize Fluent tester
|
|
575
|
-
this.fluentTester = new FluentConnectionTester(this.client, {
|
|
576
|
-
logger: console
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
console.log('✅ Setup complete');
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
async testConnectivity() {
|
|
583
|
-
console.log('\n--- Testing Connectivity ---');
|
|
584
|
-
|
|
585
|
-
const s3Result = await this.s3Tester.testAll(process.env.TEST_BUCKET!);
|
|
586
|
-
const fluentResult = await this.fluentTester.testConnection();
|
|
587
|
-
|
|
588
|
-
return {
|
|
589
|
-
s3: s3Result.summary.passed,
|
|
590
|
-
fluent: fluentResult.success,
|
|
591
|
-
overall: s3Result.summary.passed && fluentResult.success
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
async testIngestion() {
|
|
596
|
-
console.log('\n--- Testing Ingestion ---');
|
|
597
|
-
|
|
598
|
-
// TODO: Implement ingestion test with S3DataSource
|
|
599
|
-
// Use S3DataSource to upload, parse, and ingest test data
|
|
600
|
-
// Similar to testIngestionPipeline example above
|
|
601
|
-
|
|
602
|
-
return { success: true };
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
async testPerformance() {
|
|
606
|
-
console.log('\n--- Testing Performance ---');
|
|
607
|
-
|
|
608
|
-
const s3Performance = await loadTestS3(10);
|
|
609
|
-
const fluentPerformance = await loadTestFluentAPI(10);
|
|
610
|
-
|
|
611
|
-
return {
|
|
612
|
-
s3: s3Performance,
|
|
613
|
-
fluent: fluentPerformance
|
|
614
|
-
};
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
async cleanup() {
|
|
618
|
-
console.log('\n--- Cleanup ---');
|
|
619
|
-
// Cleanup handled by S3 service when operations complete
|
|
620
|
-
console.log('✅ Cleanup complete');
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
async run() {
|
|
624
|
-
try {
|
|
625
|
-
await this.setup();
|
|
626
|
-
|
|
627
|
-
const connectivity = await this.testConnectivity();
|
|
628
|
-
console.log('Connectivity:', connectivity.overall ? '✅' : ');
|
|
629
|
-
|
|
630
|
-
const ingestion = await this.testIngestion();
|
|
631
|
-
console.log('Ingestion:', ingestion.success ? '✅' : ');
|
|
632
|
-
|
|
633
|
-
const performance = await this.testPerformance();
|
|
634
|
-
console.log('Performance tests complete');
|
|
635
|
-
|
|
636
|
-
await this.cleanup();
|
|
637
|
-
|
|
638
|
-
return {
|
|
639
|
-
connectivity,
|
|
640
|
-
ingestion,
|
|
641
|
-
performance
|
|
642
|
-
};
|
|
643
|
-
} catch (error) {
|
|
644
|
-
console.error('Test suite failed:', error);
|
|
645
|
-
await this.cleanup();
|
|
646
|
-
throw error;
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
// Run test suite
|
|
652
|
-
const suite = new IntegrationTestSuite();
|
|
653
|
-
suite.run()
|
|
654
|
-
.then(results => {
|
|
655
|
-
console.log('\n=== Test Suite Results ===');
|
|
656
|
-
console.log(JSON.stringify(results, null, 2));
|
|
657
|
-
})
|
|
658
|
-
.catch(error => {
|
|
659
|
-
console.error('Test suite error:', error);
|
|
660
|
-
process.exit(1);
|
|
661
|
-
});
|
|
662
|
-
```
|
|
663
|
-
|
|
664
|
-
## Key Takeaways
|
|
665
|
-
|
|
666
|
-
- 🎯 Integration tests validate complete data pipelines
|
|
667
|
-
- 🎯 Always test connectivity before running integration tests
|
|
668
|
-
- 🎯 Performance testing helps identify bottlenecks
|
|
669
|
-
- 🎯 Load testing reveals scalability limits
|
|
670
|
-
- 🎯 Reliability testing ensures error recovery works
|
|
671
|
-
|
|
672
|
-
## Practice Exercise
|
|
673
|
-
|
|
674
|
-
Build an integration test for your specific use case:
|
|
675
|
-
|
|
676
|
-
```typescript
|
|
677
|
-
async function myIntegrationTest() {
|
|
678
|
-
// TODO: Test S3 connectivity
|
|
679
|
-
// TODO: Test Fluent connectivity
|
|
680
|
-
// TODO: Upload test data
|
|
681
|
-
// TODO: Run ingestion
|
|
682
|
-
// TODO: Verify results
|
|
683
|
-
// TODO: Cleanup
|
|
684
|
-
}
|
|
685
|
-
```
|
|
686
|
-
|
|
687
|
-
**Solution:** See [examples/integration-test.ts](../examples/integration-test.ts)
|
|
688
|
-
|
|
689
|
-
## Next Steps
|
|
690
|
-
|
|
691
|
-
Continue to [Module 5: Debugging →](./04-reference-testing-05-debugging.md) to learn debugging techniques.
|
|
692
|
-
|
|
693
|
-
---
|
|
694
|
-
|
|
695
|
-
**Module Navigation:**
|
|
696
|
-
- **Previous:** [Module 3 - Fluent Testing](./04-reference-testing-03-fluent-testing.md)
|
|
697
|
-
- **Current:** Module 4 - Integration Testing
|
|
698
|
-
- **Next:** [Module 5 - Debugging](./04-reference-testing-05-debugging.md)
|
|
699
|
-
- **Back to:** [Testing Guide Index](../testing-readme.md)
|
|
1
|
+
# Module 4: Integration Testing
|
|
2
|
+
|
|
3
|
+
**Level:** Intermediate
|
|
4
|
+
**Estimated Time:** 35 minutes
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
This module covers end-to-end integration testing, combining multiple testers to validate complete data pipelines. You'll learn how to test ingestion workflows, measure performance, and ensure reliability.
|
|
9
|
+
|
|
10
|
+
## Learning Objectives
|
|
11
|
+
|
|
12
|
+
By the end of this module, you will:
|
|
13
|
+
- ✅ Understand how to build end-to-end integration tests
|
|
14
|
+
- ✅ Know how to test complete ingestion pipelines
|
|
15
|
+
- ✅ Be able to measure and optimize performance
|
|
16
|
+
- ✅ Understand load testing patterns
|
|
17
|
+
|
|
18
|
+
## End-to-End Ingestion Test
|
|
19
|
+
|
|
20
|
+
Test a complete ingestion pipeline from S3 to Fluent Commerce:
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import {
|
|
24
|
+
S3SDKTester,
|
|
25
|
+
FluentConnectionTester,
|
|
26
|
+
createClient,
|
|
27
|
+
S3DataSource,
|
|
28
|
+
CSVParserService,
|
|
29
|
+
UniversalMapper
|
|
30
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
31
|
+
|
|
32
|
+
async function testIngestionPipeline() {
|
|
33
|
+
console.log('Starting end-to-end ingestion test...');
|
|
34
|
+
|
|
35
|
+
// Step 1: Test S3 connectivity
|
|
36
|
+
console.log('Step 1: Testing S3 connectivity...');
|
|
37
|
+
const s3Tester = new S3SDKTester({
|
|
38
|
+
region: 'us-east-1',
|
|
39
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
40
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const s3Result = await s3Tester.testAll('test-data');
|
|
44
|
+
if (!s3Result.summary.passed) {
|
|
45
|
+
throw new Error('S3 connectivity test failed');
|
|
46
|
+
}
|
|
47
|
+
console.log('✅ S3 connectivity validated');
|
|
48
|
+
|
|
49
|
+
// Step 2: Test Fluent connectivity
|
|
50
|
+
console.log('Step 2: Testing Fluent API connectivity...');
|
|
51
|
+
const client = await createClient({
|
|
52
|
+
config: {
|
|
53
|
+
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
54
|
+
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
55
|
+
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
56
|
+
username: process.env.FLUENT_USERNAME!,
|
|
57
|
+
password: process.env.FLUENT_PASSWORD!,
|
|
58
|
+
retailerId: '1'
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const fluentTester = new FluentConnectionTester(client, {
|
|
63
|
+
logger: console
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const fluentResult = await fluentTester.testConnection();
|
|
67
|
+
if (!fluentResult.success) {
|
|
68
|
+
throw new Error('Fluent connectivity test failed');
|
|
69
|
+
}
|
|
70
|
+
console.log('✅ Fluent API connectivity validated');
|
|
71
|
+
|
|
72
|
+
// Step 3: Upload test data to S3 (done via S3DataSource below)
|
|
73
|
+
console.log('Step 3: Uploading test inventory data...');
|
|
74
|
+
const testData = 'SKU,QTY,LOCATION\nTEST001,100,DC01\nTEST002,50,DC02\nTEST003,75,DC01';
|
|
75
|
+
|
|
76
|
+
// Step 4: Run ingestion using building blocks
|
|
77
|
+
console.log('Step 4: Running ingestion with SDK building blocks...');
|
|
78
|
+
const startTime = Date.now();
|
|
79
|
+
|
|
80
|
+
// Initialize components
|
|
81
|
+
const s3 = new S3DataSource({
|
|
82
|
+
type: 'S3_CSV',
|
|
83
|
+
connectionId: 'test-s3',
|
|
84
|
+
name: 'Test S3',
|
|
85
|
+
s3Config: {
|
|
86
|
+
bucket: 'test-data',
|
|
87
|
+
region: 'us-east-1',
|
|
88
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
89
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const parser = new CSVParserService();
|
|
94
|
+
const mapper = new UniversalMapper({
|
|
95
|
+
fields: {
|
|
96
|
+
ref: { source: 'SKU', required: true },
|
|
97
|
+
qty: { source: 'QTY', resolver: 'sdk.parseInt' },
|
|
98
|
+
locationRef: { source: 'LOCATION', required: true }
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Download and parse
|
|
103
|
+
const csvContent = await s3.downloadFile('test-inventory.csv');
|
|
104
|
+
const records = await parser.parse(csvContent);
|
|
105
|
+
|
|
106
|
+
// Map records
|
|
107
|
+
const inventory = [];
|
|
108
|
+
const errors = [];
|
|
109
|
+
for (const record of records) {
|
|
110
|
+
const result = await mapper.map(record);
|
|
111
|
+
if (result.success) {
|
|
112
|
+
inventory.push(result.data);
|
|
113
|
+
} else {
|
|
114
|
+
errors.push({ record, errors: result.errors });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Create job and send batch
|
|
119
|
+
const job = await client.createJob({
|
|
120
|
+
name: 'Test Inventory Ingestion',
|
|
121
|
+
retailerId: '1'
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
await client.sendBatch(job.id, {
|
|
125
|
+
action: 'UPSERT',
|
|
126
|
+
entityType: 'INVENTORY',
|
|
127
|
+
entities: inventory
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const duration = Date.now() - startTime;
|
|
131
|
+
|
|
132
|
+
// Step 5: Verify results
|
|
133
|
+
console.log('Step 5: Verifying ingestion results...');
|
|
134
|
+
const ingestionResult = {
|
|
135
|
+
success: errors.length === 0,
|
|
136
|
+
processedCount: inventory.length,
|
|
137
|
+
errors,
|
|
138
|
+
duration
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
if (ingestionResult.success) {
|
|
142
|
+
console.log('✅ End-to-end test passed!');
|
|
143
|
+
console.log(` Records processed: ${ingestionResult.processedCount}`);
|
|
144
|
+
console.log(` Duration: ${ingestionResult.duration}ms`);
|
|
145
|
+
} else {
|
|
146
|
+
console.error('❌ Ingestion had errors:', ingestionResult.errors);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Step 6: Cleanup (handled by S3 service)
|
|
150
|
+
console.log('Step 6: Test complete');
|
|
151
|
+
|
|
152
|
+
return ingestionResult;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Run test
|
|
156
|
+
testIngestionPipeline()
|
|
157
|
+
.then(result => {
|
|
158
|
+
console.log('Integration test completed:', result.success ? '✅' : ');
|
|
159
|
+
process.exit(result.success ? 0 : 1);
|
|
160
|
+
})
|
|
161
|
+
.catch(error => {
|
|
162
|
+
console.error('Integration test failed:', error);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Testing Different Data Flows
|
|
168
|
+
|
|
169
|
+
### Test CSV Ingestion
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
async function testCSVIngestion() {
|
|
173
|
+
// Create test CSV data
|
|
174
|
+
const csvData = `
|
|
175
|
+
sku,quantity,location,status
|
|
176
|
+
SKU001,100,WH001,available
|
|
177
|
+
SKU002,50,WH001,available
|
|
178
|
+
SKU003,75,WH002,available
|
|
179
|
+
`.trim();
|
|
180
|
+
|
|
181
|
+
// Ingest using building blocks
|
|
182
|
+
const s3 = new S3DataSource({
|
|
183
|
+
type: 'S3_CSV',
|
|
184
|
+
connectionId: 'test-s3',
|
|
185
|
+
name: 'Test S3',
|
|
186
|
+
s3Config: { bucket: 'test-bucket', ...s3Credentials }
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const parser = new CSVParserService();
|
|
190
|
+
const mapper = new UniversalMapper({
|
|
191
|
+
fields: {
|
|
192
|
+
ref: { source: 'sku', required: true },
|
|
193
|
+
qty: { source: 'quantity', resolver: 'sdk.parseInt' },
|
|
194
|
+
locationRef: { source: 'location', required: true },
|
|
195
|
+
status: { source: 'status' }
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const content = await s3.downloadFile('inventory.csv');
|
|
200
|
+
const records = await parser.parse(content);
|
|
201
|
+
|
|
202
|
+
const inventory = [];
|
|
203
|
+
for (const record of records) {
|
|
204
|
+
const result = await mapper.map(record);
|
|
205
|
+
if (result.success) inventory.push(result.data);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const job = await client.createJob({ name: 'Test CSV', retailerId: '1' });
|
|
209
|
+
await client.sendBatch(job.id, {
|
|
210
|
+
action: 'UPSERT',
|
|
211
|
+
entityType: 'INVENTORY',
|
|
212
|
+
entities: inventory
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Verify
|
|
216
|
+
const result = {
|
|
217
|
+
success: inventory.length > 0,
|
|
218
|
+
processedCount: inventory.length
|
|
219
|
+
};
|
|
220
|
+
console.log(`CSV Ingestion: ${result.success ? '✅' : '}`);
|
|
221
|
+
console.log(`Records: ${result.processedCount}`);
|
|
222
|
+
|
|
223
|
+
return result;
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Test Parquet Extraction
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
async function testParquetExtraction() {
|
|
231
|
+
// Query inventory from Fluent
|
|
232
|
+
const query = `
|
|
233
|
+
query GetInventory($first: Int!, $after: String) {
|
|
234
|
+
inventoryPositions(first: $first, after: $after) {
|
|
235
|
+
edges {
|
|
236
|
+
node {
|
|
237
|
+
id
|
|
238
|
+
ref
|
|
239
|
+
productRef
|
|
240
|
+
locationRef
|
|
241
|
+
qty
|
|
242
|
+
}
|
|
243
|
+
cursor
|
|
244
|
+
}
|
|
245
|
+
pageInfo {
|
|
246
|
+
hasNextPage
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
`;
|
|
251
|
+
|
|
252
|
+
const result = await client.graphql({
|
|
253
|
+
query,
|
|
254
|
+
variables: { first: 100 },
|
|
255
|
+
pagination: { maxRecords: 1000 }
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// Transform to Parquet
|
|
259
|
+
const logger = createConsoleLogger();
|
|
260
|
+
const parquetService = new ParquetParserService(logger);
|
|
261
|
+
const parquetBuffer = await parquetService.arrayToParquet(
|
|
262
|
+
result.data.inventoryPositions.edges.map(e => e.node)
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
// Upload to S3
|
|
266
|
+
const s3 = new S3DataSource(s3Config);
|
|
267
|
+
await s3.putObject('output-bucket', 'inventory.parquet', parquetBuffer);
|
|
268
|
+
|
|
269
|
+
// Verify result
|
|
270
|
+
console.log(`Parquet Extraction: ${parquetBuffer ? '✅' : '}`);
|
|
271
|
+
|
|
272
|
+
return !!parquetBuffer;
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Performance Testing
|
|
277
|
+
|
|
278
|
+
### Load Testing S3 Operations
|
|
279
|
+
|
|
280
|
+
Test S3 performance under concurrent load:
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
async function loadTestS3(concurrency: number = 10) {
|
|
284
|
+
const s3 = new S3DataSource({
|
|
285
|
+
type: 'S3_CSV',
|
|
286
|
+
connectionId: 'test-s3',
|
|
287
|
+
name: 'Load Test S3',
|
|
288
|
+
s3Config: {
|
|
289
|
+
region: 'us-east-1',
|
|
290
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
291
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const startTime = Date.now();
|
|
296
|
+
const promises = [];
|
|
297
|
+
|
|
298
|
+
// Run concurrent write operations
|
|
299
|
+
for (let i = 0; i < concurrency; i++) {
|
|
300
|
+
promises.push(
|
|
301
|
+
s3.putObject('load-test', `test-${i}.txt`, Buffer.from(`Content ${i}`))
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const results = await Promise.allSettled(promises);
|
|
306
|
+
const duration = Date.now() - startTime;
|
|
307
|
+
|
|
308
|
+
const successCount = results.filter(r => r.status === 'fulfilled').length;
|
|
309
|
+
const failureCount = results.filter(r => r.status === 'rejected').length;
|
|
310
|
+
|
|
311
|
+
console.log('Load Test Results:');
|
|
312
|
+
console.log(' Concurrency:', concurrency);
|
|
313
|
+
console.log(' Duration:', duration, 'ms');
|
|
314
|
+
console.log(' Success:', successCount);
|
|
315
|
+
console.log(' Failures:', failureCount);
|
|
316
|
+
console.log(' Avg time per operation:', duration / concurrency, 'ms');
|
|
317
|
+
console.log(' Operations per second:', (concurrency / (duration / 1000)).toFixed(2));
|
|
318
|
+
|
|
319
|
+
return {
|
|
320
|
+
concurrency,
|
|
321
|
+
duration,
|
|
322
|
+
successCount,
|
|
323
|
+
failureCount,
|
|
324
|
+
avgTimePerOperation: duration / concurrency,
|
|
325
|
+
operationsPerSecond: concurrency / (duration / 1000)
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Test with increasing load
|
|
330
|
+
async function performanceTest() {
|
|
331
|
+
const loads = [1, 5, 10, 20, 50];
|
|
332
|
+
const results = [];
|
|
333
|
+
|
|
334
|
+
for (const load of loads) {
|
|
335
|
+
console.log(`\nTesting with ${load} concurrent operations...`);
|
|
336
|
+
const result = await loadTestS3(load);
|
|
337
|
+
results.push(result);
|
|
338
|
+
|
|
339
|
+
// Wait between tests
|
|
340
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Analyze results
|
|
344
|
+
console.log('\nPerformance Analysis:');
|
|
345
|
+
results.forEach(r => {
|
|
346
|
+
console.log(`Load ${r.concurrency}:`);
|
|
347
|
+
console.log(` Avg time: ${r.avgTimePerOperation.toFixed(2)}ms`);
|
|
348
|
+
console.log(` Throughput: ${r.operationsPerSecond.toFixed(2)} ops/sec`);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// Identify performance degradation
|
|
352
|
+
const baseline = results[0];
|
|
353
|
+
results.forEach((r, i) => {
|
|
354
|
+
if (i === 0) return;
|
|
355
|
+
const degradation = ((r.avgTimePerOperation - baseline.avgTimePerOperation) / baseline.avgTimePerOperation * 100).toFixed(2);
|
|
356
|
+
console.log(`Load ${r.concurrency} degradation: ${degradation}% slower than baseline`);
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Load Testing Fluent API
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
async function loadTestFluentAPI(concurrency: number = 10) {
|
|
365
|
+
const client = await createClient({ config: fluentConfig });
|
|
366
|
+
const startTime = Date.now();
|
|
367
|
+
const promises = [];
|
|
368
|
+
|
|
369
|
+
// Run concurrent GraphQL queries
|
|
370
|
+
const query = `
|
|
371
|
+
query GetInventoryPosition($ref: String!) {
|
|
372
|
+
inventoryPosition(ref: $ref) {
|
|
373
|
+
id
|
|
374
|
+
ref
|
|
375
|
+
qty
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
`;
|
|
379
|
+
|
|
380
|
+
for (let i = 0; i < concurrency; i++) {
|
|
381
|
+
promises.push(
|
|
382
|
+
client.graphql({
|
|
383
|
+
query,
|
|
384
|
+
variables: { ref: `TEST${i}` }
|
|
385
|
+
})
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const results = await Promise.all(promises.map(p =>
|
|
390
|
+
p.then(() => ({ success: true }))
|
|
391
|
+
.catch(error => ({ success: false, error }))
|
|
392
|
+
));
|
|
393
|
+
|
|
394
|
+
const duration = Date.now() - startTime;
|
|
395
|
+
const successCount = results.filter(r => r.success).length;
|
|
396
|
+
const failureCount = results.filter(r => !r.success).length;
|
|
397
|
+
|
|
398
|
+
console.log('Fluent API Load Test:');
|
|
399
|
+
console.log(' Concurrency:', concurrency);
|
|
400
|
+
console.log(' Duration:', duration, 'ms');
|
|
401
|
+
console.log(' Success:', successCount);
|
|
402
|
+
console.log(' Failures:', failureCount);
|
|
403
|
+
console.log(' Avg response time:', duration / concurrency, 'ms');
|
|
404
|
+
|
|
405
|
+
return {
|
|
406
|
+
concurrency,
|
|
407
|
+
duration,
|
|
408
|
+
successCount,
|
|
409
|
+
failureCount,
|
|
410
|
+
avgResponseTime: duration / concurrency
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
## Reliability Testing
|
|
416
|
+
|
|
417
|
+
### Retry Logic Testing
|
|
418
|
+
|
|
419
|
+
Test error recovery and retry mechanisms:
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
async function testRetryLogic() {
|
|
423
|
+
let attemptCount = 0;
|
|
424
|
+
const maxAttempts = 3;
|
|
425
|
+
|
|
426
|
+
async function operationWithRetry() {
|
|
427
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
428
|
+
try {
|
|
429
|
+
attemptCount++;
|
|
430
|
+
console.log(`Attempt ${attempt}/${maxAttempts}...`);
|
|
431
|
+
|
|
432
|
+
// Simulate operation
|
|
433
|
+
const result = await client.graphql({ query });
|
|
434
|
+
|
|
435
|
+
console.log(`✅ Succeeded on attempt ${attempt}`);
|
|
436
|
+
return result;
|
|
437
|
+
} catch (error) {
|
|
438
|
+
if (attempt === maxAttempts) {
|
|
439
|
+
console.error(`❌ Failed after ${maxAttempts} attempts`);
|
|
440
|
+
throw error;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const backoff = Math.pow(2, attempt) * 1000;
|
|
444
|
+
console.log(`⚠️ Attempt ${attempt} failed, retrying in ${backoff}ms...`);
|
|
445
|
+
await new Promise(resolve => setTimeout(resolve, backoff));
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
try {
|
|
451
|
+
await operationWithRetry();
|
|
452
|
+
console.log(`Total attempts: ${attemptCount}`);
|
|
453
|
+
return true;
|
|
454
|
+
} catch (error) {
|
|
455
|
+
console.error('Operation failed after retries:', error);
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Circuit Breaker Testing
|
|
462
|
+
|
|
463
|
+
Test circuit breaker patterns:
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
class CircuitBreaker {
|
|
467
|
+
private failures = 0;
|
|
468
|
+
private lastFailureTime = 0;
|
|
469
|
+
private state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED';
|
|
470
|
+
|
|
471
|
+
constructor(
|
|
472
|
+
private threshold: number = 5,
|
|
473
|
+
private timeout: number = 60000
|
|
474
|
+
) {}
|
|
475
|
+
|
|
476
|
+
async execute<T>(operation: () => Promise<T>): Promise<T> {
|
|
477
|
+
if (this.state === 'OPEN') {
|
|
478
|
+
if (Date.now() - this.lastFailureTime > this.timeout) {
|
|
479
|
+
this.state = 'HALF_OPEN';
|
|
480
|
+
console.log('Circuit breaker: HALF_OPEN');
|
|
481
|
+
} else {
|
|
482
|
+
throw new Error('Circuit breaker is OPEN');
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
try {
|
|
487
|
+
const result = await operation();
|
|
488
|
+
this.onSuccess();
|
|
489
|
+
return result;
|
|
490
|
+
} catch (error) {
|
|
491
|
+
this.onFailure();
|
|
492
|
+
throw error;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
private onSuccess() {
|
|
497
|
+
this.failures = 0;
|
|
498
|
+
if (this.state === 'HALF_OPEN') {
|
|
499
|
+
this.state = 'CLOSED';
|
|
500
|
+
console.log('Circuit breaker: CLOSED');
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
private onFailure() {
|
|
505
|
+
this.failures++;
|
|
506
|
+
this.lastFailureTime = Date.now();
|
|
507
|
+
|
|
508
|
+
if (this.failures >= this.threshold) {
|
|
509
|
+
this.state = 'OPEN';
|
|
510
|
+
console.log('Circuit breaker: OPEN');
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
getState() {
|
|
515
|
+
return this.state;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// Test circuit breaker
|
|
520
|
+
async function testCircuitBreaker() {
|
|
521
|
+
const breaker = new CircuitBreaker(3, 5000);
|
|
522
|
+
|
|
523
|
+
// Simulate failures
|
|
524
|
+
for (let i = 0; i < 5; i++) {
|
|
525
|
+
try {
|
|
526
|
+
await breaker.execute(async () => {
|
|
527
|
+
throw new Error('Simulated failure');
|
|
528
|
+
});
|
|
529
|
+
} catch (error) {
|
|
530
|
+
console.log(`Request ${i + 1}:`, error.message);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
console.log('Circuit breaker state:', breaker.getState());
|
|
535
|
+
}
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
## Complete Integration Test Suite
|
|
539
|
+
|
|
540
|
+
```typescript
|
|
541
|
+
import {
|
|
542
|
+
S3SDKTester,
|
|
543
|
+
FluentConnectionTester,
|
|
544
|
+
createClient
|
|
545
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
546
|
+
|
|
547
|
+
class IntegrationTestSuite {
|
|
548
|
+
private s3Tester: S3SDKTester;
|
|
549
|
+
private fluentTester: FluentConnectionTester;
|
|
550
|
+
private client: any;
|
|
551
|
+
|
|
552
|
+
async setup() {
|
|
553
|
+
console.log('Setting up integration test suite...');
|
|
554
|
+
|
|
555
|
+
// Initialize S3 tester
|
|
556
|
+
this.s3Tester = new S3SDKTester({
|
|
557
|
+
region: process.env.AWS_REGION!,
|
|
558
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
559
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
// Initialize Fluent client
|
|
563
|
+
this.client = await createClient({
|
|
564
|
+
config: {
|
|
565
|
+
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
566
|
+
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
567
|
+
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
568
|
+
username: process.env.FLUENT_USERNAME!,
|
|
569
|
+
password: process.env.FLUENT_PASSWORD!,
|
|
570
|
+
retailerId: process.env.FLUENT_RETAILER_ID!
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
// Initialize Fluent tester
|
|
575
|
+
this.fluentTester = new FluentConnectionTester(this.client, {
|
|
576
|
+
logger: console
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
console.log('✅ Setup complete');
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
async testConnectivity() {
|
|
583
|
+
console.log('\n--- Testing Connectivity ---');
|
|
584
|
+
|
|
585
|
+
const s3Result = await this.s3Tester.testAll(process.env.TEST_BUCKET!);
|
|
586
|
+
const fluentResult = await this.fluentTester.testConnection();
|
|
587
|
+
|
|
588
|
+
return {
|
|
589
|
+
s3: s3Result.summary.passed,
|
|
590
|
+
fluent: fluentResult.success,
|
|
591
|
+
overall: s3Result.summary.passed && fluentResult.success
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
async testIngestion() {
|
|
596
|
+
console.log('\n--- Testing Ingestion ---');
|
|
597
|
+
|
|
598
|
+
// TODO: Implement ingestion test with S3DataSource
|
|
599
|
+
// Use S3DataSource to upload, parse, and ingest test data
|
|
600
|
+
// Similar to testIngestionPipeline example above
|
|
601
|
+
|
|
602
|
+
return { success: true };
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
async testPerformance() {
|
|
606
|
+
console.log('\n--- Testing Performance ---');
|
|
607
|
+
|
|
608
|
+
const s3Performance = await loadTestS3(10);
|
|
609
|
+
const fluentPerformance = await loadTestFluentAPI(10);
|
|
610
|
+
|
|
611
|
+
return {
|
|
612
|
+
s3: s3Performance,
|
|
613
|
+
fluent: fluentPerformance
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
async cleanup() {
|
|
618
|
+
console.log('\n--- Cleanup ---');
|
|
619
|
+
// Cleanup handled by S3 service when operations complete
|
|
620
|
+
console.log('✅ Cleanup complete');
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
async run() {
|
|
624
|
+
try {
|
|
625
|
+
await this.setup();
|
|
626
|
+
|
|
627
|
+
const connectivity = await this.testConnectivity();
|
|
628
|
+
console.log('Connectivity:', connectivity.overall ? '✅' : ');
|
|
629
|
+
|
|
630
|
+
const ingestion = await this.testIngestion();
|
|
631
|
+
console.log('Ingestion:', ingestion.success ? '✅' : ');
|
|
632
|
+
|
|
633
|
+
const performance = await this.testPerformance();
|
|
634
|
+
console.log('Performance tests complete');
|
|
635
|
+
|
|
636
|
+
await this.cleanup();
|
|
637
|
+
|
|
638
|
+
return {
|
|
639
|
+
connectivity,
|
|
640
|
+
ingestion,
|
|
641
|
+
performance
|
|
642
|
+
};
|
|
643
|
+
} catch (error) {
|
|
644
|
+
console.error('Test suite failed:', error);
|
|
645
|
+
await this.cleanup();
|
|
646
|
+
throw error;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// Run test suite
|
|
652
|
+
const suite = new IntegrationTestSuite();
|
|
653
|
+
suite.run()
|
|
654
|
+
.then(results => {
|
|
655
|
+
console.log('\n=== Test Suite Results ===');
|
|
656
|
+
console.log(JSON.stringify(results, null, 2));
|
|
657
|
+
})
|
|
658
|
+
.catch(error => {
|
|
659
|
+
console.error('Test suite error:', error);
|
|
660
|
+
process.exit(1);
|
|
661
|
+
});
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
## Key Takeaways
|
|
665
|
+
|
|
666
|
+
- 🎯 Integration tests validate complete data pipelines
|
|
667
|
+
- 🎯 Always test connectivity before running integration tests
|
|
668
|
+
- 🎯 Performance testing helps identify bottlenecks
|
|
669
|
+
- 🎯 Load testing reveals scalability limits
|
|
670
|
+
- 🎯 Reliability testing ensures error recovery works
|
|
671
|
+
|
|
672
|
+
## Practice Exercise
|
|
673
|
+
|
|
674
|
+
Build an integration test for your specific use case:
|
|
675
|
+
|
|
676
|
+
```typescript
|
|
677
|
+
async function myIntegrationTest() {
|
|
678
|
+
// TODO: Test S3 connectivity
|
|
679
|
+
// TODO: Test Fluent connectivity
|
|
680
|
+
// TODO: Upload test data
|
|
681
|
+
// TODO: Run ingestion
|
|
682
|
+
// TODO: Verify results
|
|
683
|
+
// TODO: Cleanup
|
|
684
|
+
}
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
**Solution:** See [examples/integration-test.ts](../examples/integration-test.ts)
|
|
688
|
+
|
|
689
|
+
## Next Steps
|
|
690
|
+
|
|
691
|
+
Continue to [Module 5: Debugging →](./04-reference-testing-05-debugging.md) to learn debugging techniques.
|
|
692
|
+
|
|
693
|
+
---
|
|
694
|
+
|
|
695
|
+
**Module Navigation:**
|
|
696
|
+
- **Previous:** [Module 3 - Fluent Testing](./04-reference-testing-03-fluent-testing.md)
|
|
697
|
+
- **Current:** Module 4 - Integration Testing
|
|
698
|
+
- **Next:** [Module 5 - Debugging](./04-reference-testing-05-debugging.md)
|
|
699
|
+
- **Back to:** [Testing Guide Index](../testing-readme.md)
|