@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
package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-integration-patterns.md
CHANGED
|
@@ -1,702 +1,702 @@
|
|
|
1
|
-
# Module 6: Integration Patterns
|
|
2
|
-
|
|
3
|
-
**Level:** Advanced
|
|
4
|
-
**Estimated Time:** 25 minutes
|
|
5
|
-
|
|
6
|
-
## Overview
|
|
7
|
-
|
|
8
|
-
This module shows how to combine parsers with other SDK services to build complete integration workflows. You'll learn patterns for ingestion, extraction, transformation, and multi-format ETL pipelines.
|
|
9
|
-
|
|
10
|
-
## Learning Objectives
|
|
11
|
-
|
|
12
|
-
By the end of this module, you will:
|
|
13
|
-
- ✅ Combine parsers with UniversalMapper for transformations
|
|
14
|
-
- ✅ Integrate with Batch API for inventory ingestion
|
|
15
|
-
- ✅ Build extraction pipelines with S3 and Parquet
|
|
16
|
-
- ✅ Create multi-format ETL workflows
|
|
17
|
-
- ✅ Implement Versori webhook handlers
|
|
18
|
-
- ✅ Build complete end-to-end integrations
|
|
19
|
-
|
|
20
|
-
## Common Integration Patterns
|
|
21
|
-
|
|
22
|
-
### Pattern 1: CSV Ingestion Pipeline
|
|
23
|
-
|
|
24
|
-
**Use Case:** Daily inventory feed from warehouse (CSV → Fluent)
|
|
25
|
-
|
|
26
|
-
```typescript
|
|
27
|
-
import {
|
|
28
|
-
createClient,
|
|
29
|
-
CSVParserService,
|
|
30
|
-
UniversalMapper,
|
|
31
|
-
S3DataSource,
|
|
32
|
-
StateService,
|
|
33
|
-
VersoriKVAdapter
|
|
34
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
35
|
-
|
|
36
|
-
async function csvIngestionPipeline(s3Key: string, kvAdapter: VersoriKVAdapter) {
|
|
37
|
-
// 1. Initialize services
|
|
38
|
-
const client = await createClient({ config });
|
|
39
|
-
const csvParser = new CSVParserService();
|
|
40
|
-
const s3DataSource = new S3DataSource(
|
|
41
|
-
{
|
|
42
|
-
type: 'S3_CSV',
|
|
43
|
-
connectionId: 's3-csv-pipeline',
|
|
44
|
-
name: 'S3 CSV Pipeline',
|
|
45
|
-
s3Config: {
|
|
46
|
-
...s3Config,
|
|
47
|
-
bucket: 'inventory-feeds',
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
console
|
|
51
|
-
);
|
|
52
|
-
const stateService = new StateService(kvAdapter);
|
|
53
|
-
|
|
54
|
-
// 2. Check if already processed
|
|
55
|
-
const fileKey = `processed:${s3Key}`;
|
|
56
|
-
const alreadyProcessed = await stateService.isFileProcessed(fileKey);
|
|
57
|
-
|
|
58
|
-
if (alreadyProcessed) {
|
|
59
|
-
console.log(`File ${s3Key} already processed, skipping`);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// 3. Download CSV from S3
|
|
64
|
-
const csvContent = await s3DataSource.downloadFile(s3Key);
|
|
65
|
-
|
|
66
|
-
// 4. Parse CSV
|
|
67
|
-
const records = await csvParser.parse(csvContent);
|
|
68
|
-
console.log(`Parsed ${records.length} records`);
|
|
69
|
-
|
|
70
|
-
// 5. Transform with UniversalMapper
|
|
71
|
-
const mapper = new UniversalMapper({
|
|
72
|
-
fields: {
|
|
73
|
-
ref: { source: 'sku', required: true },
|
|
74
|
-
qty: { source: 'quantity', resolver: 'sdk.parseInt' },
|
|
75
|
-
locationRef: { source: 'warehouse' },
|
|
76
|
-
type: { value: 'LAST' }
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
const result = await mapper.map(records);
|
|
81
|
-
|
|
82
|
-
if (!result.success) {
|
|
83
|
-
throw new Error(`Mapping failed: ${result.errors.join(', ')}`);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// 6. Send to Fluent Batch API (INVENTORY only)
|
|
87
|
-
const job = await client.createJob({
|
|
88
|
-
name: `csv-ingestion-${Date.now()}`,
|
|
89
|
-
type: 'INVENTORY',
|
|
90
|
-
retailerId: process.env.FLUENT_RETAILER_ID!
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
await client.sendBatch(job.id, {
|
|
94
|
-
entities: result.data
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
// 7. Mark as processed
|
|
98
|
-
await stateService.markFileProcessed(fileKey, {
|
|
99
|
-
recordCount: records.length,
|
|
100
|
-
processedAt: new Date().toISOString()
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
console.log(`✅ Processed ${records.length} inventory records`);
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Pattern 2: JSON Webhook Processing
|
|
108
|
-
|
|
109
|
-
**Use Case:** Process incoming webhooks from e-commerce platform
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
import {
|
|
113
|
-
createClient,
|
|
114
|
-
JSONParserService,
|
|
115
|
-
UniversalMapper
|
|
116
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
117
|
-
|
|
118
|
-
async function processOrderWebhook(webhookPayload: string) {
|
|
119
|
-
// 1. Parse JSON webhook
|
|
120
|
-
const jsonParser = new JSONParserService();
|
|
121
|
-
const order = await jsonParser.parse(webhookPayload, {
|
|
122
|
-
parseDates: true,
|
|
123
|
-
validateSchema: true,
|
|
124
|
-
schema: orderSchema
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
// 2. Transform to Fluent format
|
|
128
|
-
const fluentOrder = {
|
|
129
|
-
ref: `WEB-${order.id}`,
|
|
130
|
-
type: 'HD',
|
|
131
|
-
retailerId: '1',
|
|
132
|
-
customer: {
|
|
133
|
-
email: order.customer.email,
|
|
134
|
-
firstName: order.customer.first_name,
|
|
135
|
-
lastName: order.customer.last_name
|
|
136
|
-
},
|
|
137
|
-
items: order.items.map(item => ({
|
|
138
|
-
ref: item.sku,
|
|
139
|
-
quantity: item.quantity,
|
|
140
|
-
price: parseFloat(item.price)
|
|
141
|
-
}))
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
// 3. Send to Fluent (using GraphQL mutation, NOT Batch API)
|
|
145
|
-
const client = await createClient({ config });
|
|
146
|
-
const result = await client.graphql({
|
|
147
|
-
query: `
|
|
148
|
-
mutation CreateOrder($input: CreateOrderInput!) {
|
|
149
|
-
createOrder(input: $input) {
|
|
150
|
-
id
|
|
151
|
-
ref
|
|
152
|
-
status
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
`,
|
|
156
|
-
variables: {
|
|
157
|
-
input: fluentOrder
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
console.log(`✅ Order created: ${result.data.createOrder.ref}`);
|
|
162
|
-
return result.data.createOrder;
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Pattern 3: XML to GraphQL Mutation (SFCC Orders)
|
|
167
|
-
|
|
168
|
-
**Use Case:** SFCC order XML → Fluent GraphQL mutation
|
|
169
|
-
|
|
170
|
-
```typescript
|
|
171
|
-
import {
|
|
172
|
-
createClient,
|
|
173
|
-
XMLParserService,
|
|
174
|
-
GraphQLMutationMapper
|
|
175
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
176
|
-
|
|
177
|
-
async function processSFCCOrder(xmlContent: string) {
|
|
178
|
-
// 1. Parse XML
|
|
179
|
-
const xmlParser = new XMLParserService();
|
|
180
|
-
const parsed = await xmlParser.parse(xmlContent);
|
|
181
|
-
|
|
182
|
-
// 2. Transform with GraphQLMutationMapper
|
|
183
|
-
const mapper = new GraphQLMutationMapper({
|
|
184
|
-
mutation: 'createOrder',
|
|
185
|
-
rootPath: 'Order',
|
|
186
|
-
fields: {
|
|
187
|
-
ref: { xmlPath: '@customerOrderId', required: true },
|
|
188
|
-
type: { value: 'HD' },
|
|
189
|
-
retailerId: { value: '1' },
|
|
190
|
-
customer: {
|
|
191
|
-
email: { xmlPath: 'Customer.EmailAddress' },
|
|
192
|
-
firstName: { xmlPath: 'Customer.Name.FirstName' },
|
|
193
|
-
lastName: { xmlPath: 'Customer.Name.LastName' }
|
|
194
|
-
},
|
|
195
|
-
items: {
|
|
196
|
-
arrayPath: 'OrderItems.OrderItem',
|
|
197
|
-
fields: {
|
|
198
|
-
ref: { xmlPath: 'ItemId' },
|
|
199
|
-
quantity: { xmlPath: 'Quantity', resolver: 'sdk.parseInt' },
|
|
200
|
-
price: { xmlPath: 'Price', resolver: 'sdk.parseFloat' }
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
const mutation = await mapper.map(parsed);
|
|
207
|
-
|
|
208
|
-
// 3. Send to Fluent
|
|
209
|
-
const client = await createClient({ config });
|
|
210
|
-
const result = await client.graphql({
|
|
211
|
-
query: mutation.query,
|
|
212
|
-
variables: mutation.variables
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
console.log(`✅ SFCC order created: ${result.data.createOrder.ref}`);
|
|
216
|
-
return result.data.createOrder;
|
|
217
|
-
}
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### Pattern 4: Parquet Extraction Pipeline
|
|
221
|
-
|
|
222
|
-
**Use Case:** Extract Fluent data to analytics warehouse
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
import {
|
|
226
|
-
createClient,
|
|
227
|
-
ParquetParserService,
|
|
228
|
-
S3DataSource,
|
|
229
|
-
createConsoleLogger
|
|
230
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
231
|
-
|
|
232
|
-
async function extractToParquet(entityType: string) {
|
|
233
|
-
const logger = createConsoleLogger();
|
|
234
|
-
const client = await createClient({ config });
|
|
235
|
-
const s3DataSource = new S3DataSource({
|
|
236
|
-
type: 'S3_PARQUET',
|
|
237
|
-
connectionId: 's3-parquet-extract',
|
|
238
|
-
name: 'S3 Parquet Extract',
|
|
239
|
-
s3Config: s3Config
|
|
240
|
-
}, logger);
|
|
241
|
-
|
|
242
|
-
// 1. Fetch data from Fluent with auto-pagination
|
|
243
|
-
const result = await client.graphql({
|
|
244
|
-
query: `
|
|
245
|
-
query GetVirtualPositions($first: Int!, $after: String) {
|
|
246
|
-
virtualPositions(first: $first, after: $after) {
|
|
247
|
-
edges {
|
|
248
|
-
node {
|
|
249
|
-
id
|
|
250
|
-
productRef
|
|
251
|
-
quantity
|
|
252
|
-
groupRef
|
|
253
|
-
createdOn
|
|
254
|
-
updatedOn
|
|
255
|
-
}
|
|
256
|
-
cursor
|
|
257
|
-
}
|
|
258
|
-
pageInfo {
|
|
259
|
-
hasNextPage
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
`,
|
|
264
|
-
variables: { first: 1000 },
|
|
265
|
-
pagination: { maxRecords: 1000000 }
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
// 2. Transform to flat structure
|
|
269
|
-
const records = result.data.virtualPositions.edges.map(edge => ({
|
|
270
|
-
id: edge.node.id,
|
|
271
|
-
productRef: edge.node.productRef,
|
|
272
|
-
quantity: edge.node.quantity,
|
|
273
|
-
groupRef: edge.node.groupRef,
|
|
274
|
-
createdOn: edge.node.createdOn,
|
|
275
|
-
updatedOn: edge.node.updatedOn
|
|
276
|
-
}));
|
|
277
|
-
|
|
278
|
-
console.log(`Extracted ${records.length} virtual positions`);
|
|
279
|
-
|
|
280
|
-
// 3. Convert to Parquet
|
|
281
|
-
const parquetBuffer = await convertToParquet(records);
|
|
282
|
-
|
|
283
|
-
// 4. Upload to S3 with date partition
|
|
284
|
-
const date = new Date().toISOString().split('T')[0];
|
|
285
|
-
await s3DataSource.uploadFile(
|
|
286
|
-
`virtual-positions/date=${date}/data.parquet`,
|
|
287
|
-
parquetBuffer,
|
|
288
|
-
{ contentType: 'application/octet-stream' }
|
|
289
|
-
);
|
|
290
|
-
|
|
291
|
-
console.log(`✅ Extracted ${records.length} records to S3`);
|
|
292
|
-
}
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
### Pattern 5: Multi-Format ETL Pipeline
|
|
296
|
-
|
|
297
|
-
**Use Case:** Accept multiple formats, detect and route appropriately
|
|
298
|
-
|
|
299
|
-
```typescript
|
|
300
|
-
import {
|
|
301
|
-
CSVParserService,
|
|
302
|
-
JSONParserService,
|
|
303
|
-
XMLParserService,
|
|
304
|
-
ParquetParserService,
|
|
305
|
-
UniversalMapper
|
|
306
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
307
|
-
|
|
308
|
-
async function multiFormatETL(fileContent: string | Buffer, fileType: string) {
|
|
309
|
-
let records: any[];
|
|
310
|
-
|
|
311
|
-
// 1. Parse based on format
|
|
312
|
-
switch (fileType) {
|
|
313
|
-
case 'csv':
|
|
314
|
-
const csvParser = new CSVParserService();
|
|
315
|
-
records = await csvParser.parse(fileContent as string);
|
|
316
|
-
break;
|
|
317
|
-
|
|
318
|
-
case 'json':
|
|
319
|
-
const jsonParser = new JSONParserService();
|
|
320
|
-
records = await jsonParser.parse(fileContent as string);
|
|
321
|
-
break;
|
|
322
|
-
|
|
323
|
-
case 'xml':
|
|
324
|
-
const xmlParser = new XMLParserService();
|
|
325
|
-
const parsed = await xmlParser.parse(fileContent as string);
|
|
326
|
-
records = extractRecordsFromXML(parsed);
|
|
327
|
-
break;
|
|
328
|
-
|
|
329
|
-
case 'parquet':
|
|
330
|
-
const logger = createConsoleLogger();
|
|
331
|
-
const parquetParser = new ParquetParserService(logger);
|
|
332
|
-
records = await parquetParser.parse(fileContent as Buffer);
|
|
333
|
-
break;
|
|
334
|
-
|
|
335
|
-
default:
|
|
336
|
-
throw new Error(`Unsupported file type: ${fileType}`);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
console.log(`Parsed ${records.length} records from ${fileType}`);
|
|
340
|
-
|
|
341
|
-
// 2. Transform with UniversalMapper (works for all formats!)
|
|
342
|
-
const mapper = new UniversalMapper({
|
|
343
|
-
fields: {
|
|
344
|
-
ref: { source: 'sku', required: true },
|
|
345
|
-
qty: { source: 'quantity', resolver: 'sdk.parseInt' },
|
|
346
|
-
locationRef: { source: 'location' }
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
const result = await mapper.map(records);
|
|
351
|
-
|
|
352
|
-
if (!result.success) {
|
|
353
|
-
throw new Error(`Mapping failed: ${result.errors.join(', ')}`);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
// 3. Send to Fluent
|
|
357
|
-
const client = await createClient({ config });
|
|
358
|
-
const job = await client.createJob({
|
|
359
|
-
name: 'inventory-ingestion',
|
|
360
|
-
retailerId: config.config.retailerId
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
await client.sendBatch(job.id, {
|
|
364
|
-
action: 'UPSERT',
|
|
365
|
-
entityType: 'INVENTORY',
|
|
366
|
-
source: 'csv-import',
|
|
367
|
-
event: 'inventory.update',
|
|
368
|
-
entities: result.data
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
console.log(`✅ Processed ${records.length} records`);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
function extractRecordsFromXML(parsed: any): any[] {
|
|
375
|
-
// Extract array from XML structure
|
|
376
|
-
return parsed.products?.product || [];
|
|
377
|
-
}
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
## Versori Platform Patterns
|
|
381
|
-
|
|
382
|
-
### Pattern 6: Versori Scheduled Workflow
|
|
383
|
-
|
|
384
|
-
**Use Case:** Daily S3 CSV ingestion on Versori platform
|
|
385
|
-
|
|
386
|
-
```typescript
|
|
387
|
-
import { fn, schedule } from '@versori/run';
|
|
388
|
-
import {
|
|
389
|
-
createClient,
|
|
390
|
-
CSVParserService,
|
|
391
|
-
UniversalMapper,
|
|
392
|
-
S3DataSource
|
|
393
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
394
|
-
|
|
395
|
-
export const dailyInventorySync = schedule('daily-inventory')
|
|
396
|
-
.cron('0 2 * * *') // 2 AM daily
|
|
397
|
-
.do(async (ctx) => {
|
|
398
|
-
// Auto-detects Versori context
|
|
399
|
-
const client = await createClient(ctx);
|
|
400
|
-
const csvParser = new CSVParserService();
|
|
401
|
-
|
|
402
|
-
// Use S3DataSource for Versori S3 connection
|
|
403
|
-
const s3Source = new S3DataSource(ctx.connections.s3);
|
|
404
|
-
|
|
405
|
-
// Download CSV
|
|
406
|
-
const csvContent = await s3Source.downloadFile({
|
|
407
|
-
bucket: 'inventory-feeds',
|
|
408
|
-
key: 'daily/inventory.csv'
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
// Parse and transform
|
|
412
|
-
const records = await csvParser.parse(csvContent);
|
|
413
|
-
const mapper = new UniversalMapper(mappingConfig);
|
|
414
|
-
const result = await mapper.map(records);
|
|
415
|
-
|
|
416
|
-
// Send to Fluent
|
|
417
|
-
const job = await client.createJob({
|
|
418
|
-
name: 'inventory-ingestion',
|
|
419
|
-
retailerId: config.config.retailerId
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
await client.sendBatch(job.id, {
|
|
423
|
-
action: 'UPSERT',
|
|
424
|
-
entityType: 'INVENTORY',
|
|
425
|
-
source: 'csv-import',
|
|
426
|
-
event: 'inventory.update',
|
|
427
|
-
entities: result.data
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
ctx.log.info(`✅ Processed ${records.length} records`);
|
|
431
|
-
});
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
### Pattern 7: Versori Webhook Handler
|
|
435
|
-
|
|
436
|
-
**Use Case:** Process incoming JSON webhooks on Versori
|
|
437
|
-
|
|
438
|
-
```typescript
|
|
439
|
-
import { webhook, fn } from '@versori/run';
|
|
440
|
-
import {
|
|
441
|
-
createClient,
|
|
442
|
-
JSONParserService,
|
|
443
|
-
UniversalMapper
|
|
444
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
445
|
-
|
|
446
|
-
export const processWebhook = webhook('order-webhook')
|
|
447
|
-
.then(fn('parse', async (ctx) => {
|
|
448
|
-
const jsonParser = new JSONParserService();
|
|
449
|
-
|
|
450
|
-
// Parse webhook payload
|
|
451
|
-
const order = await jsonParser.parse(ctx.trigger.body, {
|
|
452
|
-
parseDates: true
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
return { order };
|
|
456
|
-
}))
|
|
457
|
-
.then(fn('transform', async (ctx) => {
|
|
458
|
-
const mapper = new UniversalMapper(orderMappingConfig);
|
|
459
|
-
const result = await mapper.map(ctx.data.order);
|
|
460
|
-
|
|
461
|
-
if (!result.success) {
|
|
462
|
-
throw new Error(`Mapping failed: ${result.errors.join(', ')}`);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
return { fluentOrder: result.data };
|
|
466
|
-
}))
|
|
467
|
-
.then(fn('send-to-fluent', async (ctx) => {
|
|
468
|
-
const client = await createClient(ctx);
|
|
469
|
-
|
|
470
|
-
const result = await client.graphql({
|
|
471
|
-
query: createOrderMutation,
|
|
472
|
-
variables: { input: ctx.data.fluentOrder }
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
return result.data.createOrder;
|
|
476
|
-
}))
|
|
477
|
-
.catch((ctx) => {
|
|
478
|
-
ctx.log.error('Webhook processing failed:', ctx.error);
|
|
479
|
-
throw ctx.error;
|
|
480
|
-
});
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
## Complete Real-World Examples
|
|
484
|
-
|
|
485
|
-
### Example 1: S3 CSV Inventory Ingestion (Node.js)
|
|
486
|
-
|
|
487
|
-
```typescript
|
|
488
|
-
import {
|
|
489
|
-
createClient,
|
|
490
|
-
CSVParserService,
|
|
491
|
-
UniversalMapper,
|
|
492
|
-
S3DataSource,
|
|
493
|
-
StateService,
|
|
494
|
-
VersoriKVAdapter
|
|
495
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
496
|
-
import * as fs from 'fs/promises';
|
|
497
|
-
|
|
498
|
-
async function s3CsvIngestion() {
|
|
499
|
-
// Initialize services
|
|
500
|
-
const client = await createClient({
|
|
501
|
-
config: {
|
|
502
|
-
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
503
|
-
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
504
|
-
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
505
|
-
retailerId: process.env.FLUENT_RETAILER_ID!
|
|
506
|
-
}
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
const s3DataSource = new S3DataSource(
|
|
510
|
-
{
|
|
511
|
-
type: 'S3_CSV',
|
|
512
|
-
connectionId: 's3-parsers-integration',
|
|
513
|
-
name: 'S3 Parsers Integration',
|
|
514
|
-
s3Config: {
|
|
515
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
516
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
517
|
-
region: process.env.AWS_REGION!,
|
|
518
|
-
bucket: 'inventory-feeds',
|
|
519
|
-
},
|
|
520
|
-
},
|
|
521
|
-
console
|
|
522
|
-
);
|
|
523
|
-
|
|
524
|
-
// List files in S3
|
|
525
|
-
const files = await s3DataSource.listFiles({
|
|
526
|
-
prefix: 'daily/'
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
for (const file of files) {
|
|
530
|
-
console.log(`Processing ${file.path}`);
|
|
531
|
-
|
|
532
|
-
// Download CSV
|
|
533
|
-
const csvContent = await s3DataSource.downloadFile(file.path);
|
|
534
|
-
|
|
535
|
-
// Parse CSV
|
|
536
|
-
const csvParser = new CSVParserService();
|
|
537
|
-
const records = await csvParser.parse(csvContent);
|
|
538
|
-
|
|
539
|
-
// Transform
|
|
540
|
-
const mapper = new UniversalMapper({
|
|
541
|
-
fields: {
|
|
542
|
-
ref: { source: 'sku', required: true },
|
|
543
|
-
qty: { source: 'quantity', resolver: 'sdk.parseInt' },
|
|
544
|
-
locationRef: { source: 'warehouse' },
|
|
545
|
-
type: { value: 'LAST' }
|
|
546
|
-
}
|
|
547
|
-
});
|
|
548
|
-
|
|
549
|
-
const result = await mapper.map(records);
|
|
550
|
-
|
|
551
|
-
// Send to Fluent
|
|
552
|
-
const job = await client.createJob({
|
|
553
|
-
name: 'inventory-ingestion',
|
|
554
|
-
retailerId: config.config.retailerId
|
|
555
|
-
});
|
|
556
|
-
|
|
557
|
-
await client.sendBatch(job.id, {
|
|
558
|
-
action: 'UPSERT',
|
|
559
|
-
entityType: 'INVENTORY',
|
|
560
|
-
source: 'csv-import',
|
|
561
|
-
event: 'inventory.update',
|
|
562
|
-
entities: result.data
|
|
563
|
-
});
|
|
564
|
-
|
|
565
|
-
console.log(`✅ Processed ${records.length} records from ${file.path}`);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
### Example 2: Extraction to Parquet (Node.js)
|
|
571
|
-
|
|
572
|
-
```typescript
|
|
573
|
-
import {
|
|
574
|
-
createClient,
|
|
575
|
-
ParquetParserService,
|
|
576
|
-
S3DataSource,
|
|
577
|
-
createConsoleLogger
|
|
578
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
579
|
-
|
|
580
|
-
async function extractToParquet() {
|
|
581
|
-
const logger = createConsoleLogger();
|
|
582
|
-
const client = await createClient({ config });
|
|
583
|
-
const s3DataSource = new S3DataSource({
|
|
584
|
-
type: 'S3_PARQUET',
|
|
585
|
-
connectionId: 's3-parquet-extract',
|
|
586
|
-
name: 'S3 Parquet Extract',
|
|
587
|
-
s3Config: s3Config
|
|
588
|
-
}, logger);
|
|
589
|
-
|
|
590
|
-
// Fetch data with auto-pagination
|
|
591
|
-
const result = await client.graphql({
|
|
592
|
-
query: virtualPositionsQuery,
|
|
593
|
-
variables: { first: 1000 },
|
|
594
|
-
pagination: { maxRecords: 1000000 }
|
|
595
|
-
});
|
|
596
|
-
|
|
597
|
-
const records = result.data.virtualPositions.edges.map(e => e.node);
|
|
598
|
-
|
|
599
|
-
// Convert to Parquet
|
|
600
|
-
const parquetBuffer = await convertToParquet(records);
|
|
601
|
-
|
|
602
|
-
// Upload to S3
|
|
603
|
-
const date = new Date().toISOString().split('T')[0];
|
|
604
|
-
await s3DataSource.uploadFile(
|
|
605
|
-
`virtual-positions/date=${date}/data.parquet`,
|
|
606
|
-
parquetBuffer
|
|
607
|
-
);
|
|
608
|
-
|
|
609
|
-
console.log(`✅ Extracted ${records.length} records`);
|
|
610
|
-
}
|
|
611
|
-
```
|
|
612
|
-
|
|
613
|
-
## Error Handling Patterns
|
|
614
|
-
|
|
615
|
-
### Comprehensive Error Handling
|
|
616
|
-
|
|
617
|
-
```typescript
|
|
618
|
-
async function robustIntegration(fileContent: string) {
|
|
619
|
-
try {
|
|
620
|
-
// 1. Parse
|
|
621
|
-
const csvParser = new CSVParserService();
|
|
622
|
-
const records = await csvParser.parse(fileContent);
|
|
623
|
-
|
|
624
|
-
// 2. Validate
|
|
625
|
-
if (records.length === 0) {
|
|
626
|
-
throw new Error('No records found in file');
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
// 3. Transform
|
|
630
|
-
const mapper = new UniversalMapper(mappingConfig);
|
|
631
|
-
const result = await mapper.map(records);
|
|
632
|
-
|
|
633
|
-
if (!result.success) {
|
|
634
|
-
// Log mapping errors but continue with successful records
|
|
635
|
-
console.error('Mapping errors:', result.errors);
|
|
636
|
-
|
|
637
|
-
if (result.data.length === 0) {
|
|
638
|
-
throw new Error('All records failed mapping');
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
console.warn(`Proceeding with ${result.data.length}/${records.length} successful records`);
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
// 4. Send to Fluent
|
|
645
|
-
const client = await createClient({ config });
|
|
646
|
-
const job = await client.createJob({
|
|
647
|
-
name: 'inventory-ingestion',
|
|
648
|
-
retailerId: config.config.retailerId
|
|
649
|
-
});
|
|
650
|
-
|
|
651
|
-
await client.sendBatch(job.id, {
|
|
652
|
-
action: 'UPSERT',
|
|
653
|
-
entityType: 'INVENTORY',
|
|
654
|
-
source: 'csv-import',
|
|
655
|
-
event: 'inventory.update',
|
|
656
|
-
entities: result.data
|
|
657
|
-
});
|
|
658
|
-
|
|
659
|
-
console.log(`✅ Processed ${result.data.length} records`);
|
|
660
|
-
|
|
661
|
-
} catch (error) {
|
|
662
|
-
console.error('Integration failed:', error);
|
|
663
|
-
|
|
664
|
-
// Send alert/notification
|
|
665
|
-
await sendAlert(`Integration failed: ${error.message}`);
|
|
666
|
-
|
|
667
|
-
throw error;
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
```
|
|
671
|
-
|
|
672
|
-
## Key Takeaways
|
|
673
|
-
|
|
674
|
-
- 🎯 Combine parsers with UniversalMapper for standard transformation pattern
|
|
675
|
-
- 🎯 Use GraphQLMutationMapper for complex XML→GraphQL transformations
|
|
676
|
-
- 🎯 Integrate with S3DataSource for file operations
|
|
677
|
-
- 🎯 Use StateService to prevent duplicate processing
|
|
678
|
-
- 🎯 Auto-pagination works seamlessly for large extractions
|
|
679
|
-
- 🎯 Versori patterns auto-detect platform context
|
|
680
|
-
- 🎯 Always handle errors and log processing metrics
|
|
681
|
-
|
|
682
|
-
## Practice Exercise
|
|
683
|
-
|
|
684
|
-
**Challenge:** Build complete ingestion pipeline:
|
|
685
|
-
|
|
686
|
-
**Requirements:**
|
|
687
|
-
1. Download CSV from S3: `s3://feeds/inventory-2025-01-15.csv`
|
|
688
|
-
2. Parse CSV with validation
|
|
689
|
-
3. Transform with UniversalMapper (sku→ref, quantity→qty)
|
|
690
|
-
4. Send to Fluent Batch API
|
|
691
|
-
5. Track state to prevent duplicate processing
|
|
692
|
-
6. Handle errors gracefully
|
|
693
|
-
|
|
694
|
-
**Solution:** See [Parser Examples](../examples/)
|
|
695
|
-
|
|
696
|
-
## Next Steps
|
|
697
|
-
|
|
698
|
-
Continue to [Module 7: Troubleshooting →](./02-core-guides-parsers-07-troubleshooting.md) for error handling and optimization.
|
|
699
|
-
|
|
700
|
-
---
|
|
701
|
-
|
|
702
|
-
**Module 6 Complete!** ✅
|
|
1
|
+
# Module 6: Integration Patterns
|
|
2
|
+
|
|
3
|
+
**Level:** Advanced
|
|
4
|
+
**Estimated Time:** 25 minutes
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
This module shows how to combine parsers with other SDK services to build complete integration workflows. You'll learn patterns for ingestion, extraction, transformation, and multi-format ETL pipelines.
|
|
9
|
+
|
|
10
|
+
## Learning Objectives
|
|
11
|
+
|
|
12
|
+
By the end of this module, you will:
|
|
13
|
+
- ✅ Combine parsers with UniversalMapper for transformations
|
|
14
|
+
- ✅ Integrate with Batch API for inventory ingestion
|
|
15
|
+
- ✅ Build extraction pipelines with S3 and Parquet
|
|
16
|
+
- ✅ Create multi-format ETL workflows
|
|
17
|
+
- ✅ Implement Versori webhook handlers
|
|
18
|
+
- ✅ Build complete end-to-end integrations
|
|
19
|
+
|
|
20
|
+
## Common Integration Patterns
|
|
21
|
+
|
|
22
|
+
### Pattern 1: CSV Ingestion Pipeline
|
|
23
|
+
|
|
24
|
+
**Use Case:** Daily inventory feed from warehouse (CSV → Fluent)
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import {
|
|
28
|
+
createClient,
|
|
29
|
+
CSVParserService,
|
|
30
|
+
UniversalMapper,
|
|
31
|
+
S3DataSource,
|
|
32
|
+
StateService,
|
|
33
|
+
VersoriKVAdapter
|
|
34
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
35
|
+
|
|
36
|
+
async function csvIngestionPipeline(s3Key: string, kvAdapter: VersoriKVAdapter) {
|
|
37
|
+
// 1. Initialize services
|
|
38
|
+
const client = await createClient({ config });
|
|
39
|
+
const csvParser = new CSVParserService();
|
|
40
|
+
const s3DataSource = new S3DataSource(
|
|
41
|
+
{
|
|
42
|
+
type: 'S3_CSV',
|
|
43
|
+
connectionId: 's3-csv-pipeline',
|
|
44
|
+
name: 'S3 CSV Pipeline',
|
|
45
|
+
s3Config: {
|
|
46
|
+
...s3Config,
|
|
47
|
+
bucket: 'inventory-feeds',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
console
|
|
51
|
+
);
|
|
52
|
+
const stateService = new StateService(kvAdapter);
|
|
53
|
+
|
|
54
|
+
// 2. Check if already processed
|
|
55
|
+
const fileKey = `processed:${s3Key}`;
|
|
56
|
+
const alreadyProcessed = await stateService.isFileProcessed(fileKey);
|
|
57
|
+
|
|
58
|
+
if (alreadyProcessed) {
|
|
59
|
+
console.log(`File ${s3Key} already processed, skipping`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 3. Download CSV from S3
|
|
64
|
+
const csvContent = await s3DataSource.downloadFile(s3Key);
|
|
65
|
+
|
|
66
|
+
// 4. Parse CSV
|
|
67
|
+
const records = await csvParser.parse(csvContent);
|
|
68
|
+
console.log(`Parsed ${records.length} records`);
|
|
69
|
+
|
|
70
|
+
// 5. Transform with UniversalMapper
|
|
71
|
+
const mapper = new UniversalMapper({
|
|
72
|
+
fields: {
|
|
73
|
+
ref: { source: 'sku', required: true },
|
|
74
|
+
qty: { source: 'quantity', resolver: 'sdk.parseInt' },
|
|
75
|
+
locationRef: { source: 'warehouse' },
|
|
76
|
+
type: { value: 'LAST' }
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const result = await mapper.map(records);
|
|
81
|
+
|
|
82
|
+
if (!result.success) {
|
|
83
|
+
throw new Error(`Mapping failed: ${result.errors.join(', ')}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 6. Send to Fluent Batch API (INVENTORY only)
|
|
87
|
+
const job = await client.createJob({
|
|
88
|
+
name: `csv-ingestion-${Date.now()}`,
|
|
89
|
+
type: 'INVENTORY',
|
|
90
|
+
retailerId: process.env.FLUENT_RETAILER_ID!
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
await client.sendBatch(job.id, {
|
|
94
|
+
entities: result.data
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// 7. Mark as processed
|
|
98
|
+
await stateService.markFileProcessed(fileKey, {
|
|
99
|
+
recordCount: records.length,
|
|
100
|
+
processedAt: new Date().toISOString()
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
console.log(`✅ Processed ${records.length} inventory records`);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Pattern 2: JSON Webhook Processing
|
|
108
|
+
|
|
109
|
+
**Use Case:** Process incoming webhooks from e-commerce platform
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import {
|
|
113
|
+
createClient,
|
|
114
|
+
JSONParserService,
|
|
115
|
+
UniversalMapper
|
|
116
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
117
|
+
|
|
118
|
+
async function processOrderWebhook(webhookPayload: string) {
|
|
119
|
+
// 1. Parse JSON webhook
|
|
120
|
+
const jsonParser = new JSONParserService();
|
|
121
|
+
const order = await jsonParser.parse(webhookPayload, {
|
|
122
|
+
parseDates: true,
|
|
123
|
+
validateSchema: true,
|
|
124
|
+
schema: orderSchema
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// 2. Transform to Fluent format
|
|
128
|
+
const fluentOrder = {
|
|
129
|
+
ref: `WEB-${order.id}`,
|
|
130
|
+
type: 'HD',
|
|
131
|
+
retailerId: '1',
|
|
132
|
+
customer: {
|
|
133
|
+
email: order.customer.email,
|
|
134
|
+
firstName: order.customer.first_name,
|
|
135
|
+
lastName: order.customer.last_name
|
|
136
|
+
},
|
|
137
|
+
items: order.items.map(item => ({
|
|
138
|
+
ref: item.sku,
|
|
139
|
+
quantity: item.quantity,
|
|
140
|
+
price: parseFloat(item.price)
|
|
141
|
+
}))
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// 3. Send to Fluent (using GraphQL mutation, NOT Batch API)
|
|
145
|
+
const client = await createClient({ config });
|
|
146
|
+
const result = await client.graphql({
|
|
147
|
+
query: `
|
|
148
|
+
mutation CreateOrder($input: CreateOrderInput!) {
|
|
149
|
+
createOrder(input: $input) {
|
|
150
|
+
id
|
|
151
|
+
ref
|
|
152
|
+
status
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
`,
|
|
156
|
+
variables: {
|
|
157
|
+
input: fluentOrder
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
console.log(`✅ Order created: ${result.data.createOrder.ref}`);
|
|
162
|
+
return result.data.createOrder;
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Pattern 3: XML to GraphQL Mutation (SFCC Orders)
|
|
167
|
+
|
|
168
|
+
**Use Case:** SFCC order XML → Fluent GraphQL mutation
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import {
|
|
172
|
+
createClient,
|
|
173
|
+
XMLParserService,
|
|
174
|
+
GraphQLMutationMapper
|
|
175
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
176
|
+
|
|
177
|
+
async function processSFCCOrder(xmlContent: string) {
|
|
178
|
+
// 1. Parse XML
|
|
179
|
+
const xmlParser = new XMLParserService();
|
|
180
|
+
const parsed = await xmlParser.parse(xmlContent);
|
|
181
|
+
|
|
182
|
+
// 2. Transform with GraphQLMutationMapper
|
|
183
|
+
const mapper = new GraphQLMutationMapper({
|
|
184
|
+
mutation: 'createOrder',
|
|
185
|
+
rootPath: 'Order',
|
|
186
|
+
fields: {
|
|
187
|
+
ref: { xmlPath: '@customerOrderId', required: true },
|
|
188
|
+
type: { value: 'HD' },
|
|
189
|
+
retailerId: { value: '1' },
|
|
190
|
+
customer: {
|
|
191
|
+
email: { xmlPath: 'Customer.EmailAddress' },
|
|
192
|
+
firstName: { xmlPath: 'Customer.Name.FirstName' },
|
|
193
|
+
lastName: { xmlPath: 'Customer.Name.LastName' }
|
|
194
|
+
},
|
|
195
|
+
items: {
|
|
196
|
+
arrayPath: 'OrderItems.OrderItem',
|
|
197
|
+
fields: {
|
|
198
|
+
ref: { xmlPath: 'ItemId' },
|
|
199
|
+
quantity: { xmlPath: 'Quantity', resolver: 'sdk.parseInt' },
|
|
200
|
+
price: { xmlPath: 'Price', resolver: 'sdk.parseFloat' }
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const mutation = await mapper.map(parsed);
|
|
207
|
+
|
|
208
|
+
// 3. Send to Fluent
|
|
209
|
+
const client = await createClient({ config });
|
|
210
|
+
const result = await client.graphql({
|
|
211
|
+
query: mutation.query,
|
|
212
|
+
variables: mutation.variables
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
console.log(`✅ SFCC order created: ${result.data.createOrder.ref}`);
|
|
216
|
+
return result.data.createOrder;
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Pattern 4: Parquet Extraction Pipeline
|
|
221
|
+
|
|
222
|
+
**Use Case:** Extract Fluent data to analytics warehouse
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
import {
|
|
226
|
+
createClient,
|
|
227
|
+
ParquetParserService,
|
|
228
|
+
S3DataSource,
|
|
229
|
+
createConsoleLogger
|
|
230
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
231
|
+
|
|
232
|
+
async function extractToParquet(entityType: string) {
|
|
233
|
+
const logger = createConsoleLogger();
|
|
234
|
+
const client = await createClient({ config });
|
|
235
|
+
const s3DataSource = new S3DataSource({
|
|
236
|
+
type: 'S3_PARQUET',
|
|
237
|
+
connectionId: 's3-parquet-extract',
|
|
238
|
+
name: 'S3 Parquet Extract',
|
|
239
|
+
s3Config: s3Config
|
|
240
|
+
}, logger);
|
|
241
|
+
|
|
242
|
+
// 1. Fetch data from Fluent with auto-pagination
|
|
243
|
+
const result = await client.graphql({
|
|
244
|
+
query: `
|
|
245
|
+
query GetVirtualPositions($first: Int!, $after: String) {
|
|
246
|
+
virtualPositions(first: $first, after: $after) {
|
|
247
|
+
edges {
|
|
248
|
+
node {
|
|
249
|
+
id
|
|
250
|
+
productRef
|
|
251
|
+
quantity
|
|
252
|
+
groupRef
|
|
253
|
+
createdOn
|
|
254
|
+
updatedOn
|
|
255
|
+
}
|
|
256
|
+
cursor
|
|
257
|
+
}
|
|
258
|
+
pageInfo {
|
|
259
|
+
hasNextPage
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
`,
|
|
264
|
+
variables: { first: 1000 },
|
|
265
|
+
pagination: { maxRecords: 1000000 }
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// 2. Transform to flat structure
|
|
269
|
+
const records = result.data.virtualPositions.edges.map(edge => ({
|
|
270
|
+
id: edge.node.id,
|
|
271
|
+
productRef: edge.node.productRef,
|
|
272
|
+
quantity: edge.node.quantity,
|
|
273
|
+
groupRef: edge.node.groupRef,
|
|
274
|
+
createdOn: edge.node.createdOn,
|
|
275
|
+
updatedOn: edge.node.updatedOn
|
|
276
|
+
}));
|
|
277
|
+
|
|
278
|
+
console.log(`Extracted ${records.length} virtual positions`);
|
|
279
|
+
|
|
280
|
+
// 3. Convert to Parquet
|
|
281
|
+
const parquetBuffer = await convertToParquet(records);
|
|
282
|
+
|
|
283
|
+
// 4. Upload to S3 with date partition
|
|
284
|
+
const date = new Date().toISOString().split('T')[0];
|
|
285
|
+
await s3DataSource.uploadFile(
|
|
286
|
+
`virtual-positions/date=${date}/data.parquet`,
|
|
287
|
+
parquetBuffer,
|
|
288
|
+
{ contentType: 'application/octet-stream' }
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
console.log(`✅ Extracted ${records.length} records to S3`);
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Pattern 5: Multi-Format ETL Pipeline
|
|
296
|
+
|
|
297
|
+
**Use Case:** Accept multiple formats, detect and route appropriately
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
import {
|
|
301
|
+
CSVParserService,
|
|
302
|
+
JSONParserService,
|
|
303
|
+
XMLParserService,
|
|
304
|
+
ParquetParserService,
|
|
305
|
+
UniversalMapper
|
|
306
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
307
|
+
|
|
308
|
+
async function multiFormatETL(fileContent: string | Buffer, fileType: string) {
|
|
309
|
+
let records: any[];
|
|
310
|
+
|
|
311
|
+
// 1. Parse based on format
|
|
312
|
+
switch (fileType) {
|
|
313
|
+
case 'csv':
|
|
314
|
+
const csvParser = new CSVParserService();
|
|
315
|
+
records = await csvParser.parse(fileContent as string);
|
|
316
|
+
break;
|
|
317
|
+
|
|
318
|
+
case 'json':
|
|
319
|
+
const jsonParser = new JSONParserService();
|
|
320
|
+
records = await jsonParser.parse(fileContent as string);
|
|
321
|
+
break;
|
|
322
|
+
|
|
323
|
+
case 'xml':
|
|
324
|
+
const xmlParser = new XMLParserService();
|
|
325
|
+
const parsed = await xmlParser.parse(fileContent as string);
|
|
326
|
+
records = extractRecordsFromXML(parsed);
|
|
327
|
+
break;
|
|
328
|
+
|
|
329
|
+
case 'parquet':
|
|
330
|
+
const logger = createConsoleLogger();
|
|
331
|
+
const parquetParser = new ParquetParserService(logger);
|
|
332
|
+
records = await parquetParser.parse(fileContent as Buffer);
|
|
333
|
+
break;
|
|
334
|
+
|
|
335
|
+
default:
|
|
336
|
+
throw new Error(`Unsupported file type: ${fileType}`);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
console.log(`Parsed ${records.length} records from ${fileType}`);
|
|
340
|
+
|
|
341
|
+
// 2. Transform with UniversalMapper (works for all formats!)
|
|
342
|
+
const mapper = new UniversalMapper({
|
|
343
|
+
fields: {
|
|
344
|
+
ref: { source: 'sku', required: true },
|
|
345
|
+
qty: { source: 'quantity', resolver: 'sdk.parseInt' },
|
|
346
|
+
locationRef: { source: 'location' }
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
const result = await mapper.map(records);
|
|
351
|
+
|
|
352
|
+
if (!result.success) {
|
|
353
|
+
throw new Error(`Mapping failed: ${result.errors.join(', ')}`);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// 3. Send to Fluent
|
|
357
|
+
const client = await createClient({ config });
|
|
358
|
+
const job = await client.createJob({
|
|
359
|
+
name: 'inventory-ingestion',
|
|
360
|
+
retailerId: config.config.retailerId
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
await client.sendBatch(job.id, {
|
|
364
|
+
action: 'UPSERT',
|
|
365
|
+
entityType: 'INVENTORY',
|
|
366
|
+
source: 'csv-import',
|
|
367
|
+
event: 'inventory.update',
|
|
368
|
+
entities: result.data
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
console.log(`✅ Processed ${records.length} records`);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function extractRecordsFromXML(parsed: any): any[] {
|
|
375
|
+
// Extract array from XML structure
|
|
376
|
+
return parsed.products?.product || [];
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Versori Platform Patterns
|
|
381
|
+
|
|
382
|
+
### Pattern 6: Versori Scheduled Workflow
|
|
383
|
+
|
|
384
|
+
**Use Case:** Daily S3 CSV ingestion on Versori platform
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
import { fn, schedule } from '@versori/run';
|
|
388
|
+
import {
|
|
389
|
+
createClient,
|
|
390
|
+
CSVParserService,
|
|
391
|
+
UniversalMapper,
|
|
392
|
+
S3DataSource
|
|
393
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
394
|
+
|
|
395
|
+
export const dailyInventorySync = schedule('daily-inventory')
|
|
396
|
+
.cron('0 2 * * *') // 2 AM daily
|
|
397
|
+
.do(async (ctx) => {
|
|
398
|
+
// Auto-detects Versori context
|
|
399
|
+
const client = await createClient(ctx);
|
|
400
|
+
const csvParser = new CSVParserService();
|
|
401
|
+
|
|
402
|
+
// Use S3DataSource for Versori S3 connection
|
|
403
|
+
const s3Source = new S3DataSource(ctx.connections.s3);
|
|
404
|
+
|
|
405
|
+
// Download CSV
|
|
406
|
+
const csvContent = await s3Source.downloadFile({
|
|
407
|
+
bucket: 'inventory-feeds',
|
|
408
|
+
key: 'daily/inventory.csv'
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
// Parse and transform
|
|
412
|
+
const records = await csvParser.parse(csvContent);
|
|
413
|
+
const mapper = new UniversalMapper(mappingConfig);
|
|
414
|
+
const result = await mapper.map(records);
|
|
415
|
+
|
|
416
|
+
// Send to Fluent
|
|
417
|
+
const job = await client.createJob({
|
|
418
|
+
name: 'inventory-ingestion',
|
|
419
|
+
retailerId: config.config.retailerId
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
await client.sendBatch(job.id, {
|
|
423
|
+
action: 'UPSERT',
|
|
424
|
+
entityType: 'INVENTORY',
|
|
425
|
+
source: 'csv-import',
|
|
426
|
+
event: 'inventory.update',
|
|
427
|
+
entities: result.data
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
ctx.log.info(`✅ Processed ${records.length} records`);
|
|
431
|
+
});
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Pattern 7: Versori Webhook Handler
|
|
435
|
+
|
|
436
|
+
**Use Case:** Process incoming JSON webhooks on Versori
|
|
437
|
+
|
|
438
|
+
```typescript
|
|
439
|
+
import { webhook, fn } from '@versori/run';
|
|
440
|
+
import {
|
|
441
|
+
createClient,
|
|
442
|
+
JSONParserService,
|
|
443
|
+
UniversalMapper
|
|
444
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
445
|
+
|
|
446
|
+
export const processWebhook = webhook('order-webhook')
|
|
447
|
+
.then(fn('parse', async (ctx) => {
|
|
448
|
+
const jsonParser = new JSONParserService();
|
|
449
|
+
|
|
450
|
+
// Parse webhook payload
|
|
451
|
+
const order = await jsonParser.parse(ctx.trigger.body, {
|
|
452
|
+
parseDates: true
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
return { order };
|
|
456
|
+
}))
|
|
457
|
+
.then(fn('transform', async (ctx) => {
|
|
458
|
+
const mapper = new UniversalMapper(orderMappingConfig);
|
|
459
|
+
const result = await mapper.map(ctx.data.order);
|
|
460
|
+
|
|
461
|
+
if (!result.success) {
|
|
462
|
+
throw new Error(`Mapping failed: ${result.errors.join(', ')}`);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return { fluentOrder: result.data };
|
|
466
|
+
}))
|
|
467
|
+
.then(fn('send-to-fluent', async (ctx) => {
|
|
468
|
+
const client = await createClient(ctx);
|
|
469
|
+
|
|
470
|
+
const result = await client.graphql({
|
|
471
|
+
query: createOrderMutation,
|
|
472
|
+
variables: { input: ctx.data.fluentOrder }
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
return result.data.createOrder;
|
|
476
|
+
}))
|
|
477
|
+
.catch((ctx) => {
|
|
478
|
+
ctx.log.error('Webhook processing failed:', ctx.error);
|
|
479
|
+
throw ctx.error;
|
|
480
|
+
});
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
## Complete Real-World Examples
|
|
484
|
+
|
|
485
|
+
### Example 1: S3 CSV Inventory Ingestion (Node.js)
|
|
486
|
+
|
|
487
|
+
```typescript
|
|
488
|
+
import {
|
|
489
|
+
createClient,
|
|
490
|
+
CSVParserService,
|
|
491
|
+
UniversalMapper,
|
|
492
|
+
S3DataSource,
|
|
493
|
+
StateService,
|
|
494
|
+
VersoriKVAdapter
|
|
495
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
496
|
+
import * as fs from 'fs/promises';
|
|
497
|
+
|
|
498
|
+
async function s3CsvIngestion() {
|
|
499
|
+
// Initialize services
|
|
500
|
+
const client = await createClient({
|
|
501
|
+
config: {
|
|
502
|
+
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
503
|
+
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
504
|
+
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
505
|
+
retailerId: process.env.FLUENT_RETAILER_ID!
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
const s3DataSource = new S3DataSource(
|
|
510
|
+
{
|
|
511
|
+
type: 'S3_CSV',
|
|
512
|
+
connectionId: 's3-parsers-integration',
|
|
513
|
+
name: 'S3 Parsers Integration',
|
|
514
|
+
s3Config: {
|
|
515
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
516
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
517
|
+
region: process.env.AWS_REGION!,
|
|
518
|
+
bucket: 'inventory-feeds',
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
console
|
|
522
|
+
);
|
|
523
|
+
|
|
524
|
+
// List files in S3
|
|
525
|
+
const files = await s3DataSource.listFiles({
|
|
526
|
+
prefix: 'daily/'
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
for (const file of files) {
|
|
530
|
+
console.log(`Processing ${file.path}`);
|
|
531
|
+
|
|
532
|
+
// Download CSV
|
|
533
|
+
const csvContent = await s3DataSource.downloadFile(file.path);
|
|
534
|
+
|
|
535
|
+
// Parse CSV
|
|
536
|
+
const csvParser = new CSVParserService();
|
|
537
|
+
const records = await csvParser.parse(csvContent);
|
|
538
|
+
|
|
539
|
+
// Transform
|
|
540
|
+
const mapper = new UniversalMapper({
|
|
541
|
+
fields: {
|
|
542
|
+
ref: { source: 'sku', required: true },
|
|
543
|
+
qty: { source: 'quantity', resolver: 'sdk.parseInt' },
|
|
544
|
+
locationRef: { source: 'warehouse' },
|
|
545
|
+
type: { value: 'LAST' }
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
const result = await mapper.map(records);
|
|
550
|
+
|
|
551
|
+
// Send to Fluent
|
|
552
|
+
const job = await client.createJob({
|
|
553
|
+
name: 'inventory-ingestion',
|
|
554
|
+
retailerId: config.config.retailerId
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
await client.sendBatch(job.id, {
|
|
558
|
+
action: 'UPSERT',
|
|
559
|
+
entityType: 'INVENTORY',
|
|
560
|
+
source: 'csv-import',
|
|
561
|
+
event: 'inventory.update',
|
|
562
|
+
entities: result.data
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
console.log(`✅ Processed ${records.length} records from ${file.path}`);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
### Example 2: Extraction to Parquet (Node.js)
|
|
571
|
+
|
|
572
|
+
```typescript
|
|
573
|
+
import {
|
|
574
|
+
createClient,
|
|
575
|
+
ParquetParserService,
|
|
576
|
+
S3DataSource,
|
|
577
|
+
createConsoleLogger
|
|
578
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
579
|
+
|
|
580
|
+
async function extractToParquet() {
|
|
581
|
+
const logger = createConsoleLogger();
|
|
582
|
+
const client = await createClient({ config });
|
|
583
|
+
const s3DataSource = new S3DataSource({
|
|
584
|
+
type: 'S3_PARQUET',
|
|
585
|
+
connectionId: 's3-parquet-extract',
|
|
586
|
+
name: 'S3 Parquet Extract',
|
|
587
|
+
s3Config: s3Config
|
|
588
|
+
}, logger);
|
|
589
|
+
|
|
590
|
+
// Fetch data with auto-pagination
|
|
591
|
+
const result = await client.graphql({
|
|
592
|
+
query: virtualPositionsQuery,
|
|
593
|
+
variables: { first: 1000 },
|
|
594
|
+
pagination: { maxRecords: 1000000 }
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
const records = result.data.virtualPositions.edges.map(e => e.node);
|
|
598
|
+
|
|
599
|
+
// Convert to Parquet
|
|
600
|
+
const parquetBuffer = await convertToParquet(records);
|
|
601
|
+
|
|
602
|
+
// Upload to S3
|
|
603
|
+
const date = new Date().toISOString().split('T')[0];
|
|
604
|
+
await s3DataSource.uploadFile(
|
|
605
|
+
`virtual-positions/date=${date}/data.parquet`,
|
|
606
|
+
parquetBuffer
|
|
607
|
+
);
|
|
608
|
+
|
|
609
|
+
console.log(`✅ Extracted ${records.length} records`);
|
|
610
|
+
}
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
## Error Handling Patterns
|
|
614
|
+
|
|
615
|
+
### Comprehensive Error Handling
|
|
616
|
+
|
|
617
|
+
```typescript
|
|
618
|
+
async function robustIntegration(fileContent: string) {
|
|
619
|
+
try {
|
|
620
|
+
// 1. Parse
|
|
621
|
+
const csvParser = new CSVParserService();
|
|
622
|
+
const records = await csvParser.parse(fileContent);
|
|
623
|
+
|
|
624
|
+
// 2. Validate
|
|
625
|
+
if (records.length === 0) {
|
|
626
|
+
throw new Error('No records found in file');
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// 3. Transform
|
|
630
|
+
const mapper = new UniversalMapper(mappingConfig);
|
|
631
|
+
const result = await mapper.map(records);
|
|
632
|
+
|
|
633
|
+
if (!result.success) {
|
|
634
|
+
// Log mapping errors but continue with successful records
|
|
635
|
+
console.error('Mapping errors:', result.errors);
|
|
636
|
+
|
|
637
|
+
if (result.data.length === 0) {
|
|
638
|
+
throw new Error('All records failed mapping');
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
console.warn(`Proceeding with ${result.data.length}/${records.length} successful records`);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// 4. Send to Fluent
|
|
645
|
+
const client = await createClient({ config });
|
|
646
|
+
const job = await client.createJob({
|
|
647
|
+
name: 'inventory-ingestion',
|
|
648
|
+
retailerId: config.config.retailerId
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
await client.sendBatch(job.id, {
|
|
652
|
+
action: 'UPSERT',
|
|
653
|
+
entityType: 'INVENTORY',
|
|
654
|
+
source: 'csv-import',
|
|
655
|
+
event: 'inventory.update',
|
|
656
|
+
entities: result.data
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
console.log(`✅ Processed ${result.data.length} records`);
|
|
660
|
+
|
|
661
|
+
} catch (error) {
|
|
662
|
+
console.error('Integration failed:', error);
|
|
663
|
+
|
|
664
|
+
// Send alert/notification
|
|
665
|
+
await sendAlert(`Integration failed: ${error.message}`);
|
|
666
|
+
|
|
667
|
+
throw error;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
## Key Takeaways
|
|
673
|
+
|
|
674
|
+
- 🎯 Combine parsers with UniversalMapper for standard transformation pattern
|
|
675
|
+
- 🎯 Use GraphQLMutationMapper for complex XML→GraphQL transformations
|
|
676
|
+
- 🎯 Integrate with S3DataSource for file operations
|
|
677
|
+
- 🎯 Use StateService to prevent duplicate processing
|
|
678
|
+
- 🎯 Auto-pagination works seamlessly for large extractions
|
|
679
|
+
- 🎯 Versori patterns auto-detect platform context
|
|
680
|
+
- 🎯 Always handle errors and log processing metrics
|
|
681
|
+
|
|
682
|
+
## Practice Exercise
|
|
683
|
+
|
|
684
|
+
**Challenge:** Build complete ingestion pipeline:
|
|
685
|
+
|
|
686
|
+
**Requirements:**
|
|
687
|
+
1. Download CSV from S3: `s3://feeds/inventory-2025-01-15.csv`
|
|
688
|
+
2. Parse CSV with validation
|
|
689
|
+
3. Transform with UniversalMapper (sku→ref, quantity→qty)
|
|
690
|
+
4. Send to Fluent Batch API
|
|
691
|
+
5. Track state to prevent duplicate processing
|
|
692
|
+
6. Handle errors gracefully
|
|
693
|
+
|
|
694
|
+
**Solution:** See [Parser Examples](../examples/)
|
|
695
|
+
|
|
696
|
+
## Next Steps
|
|
697
|
+
|
|
698
|
+
Continue to [Module 7: Troubleshooting →](./02-core-guides-parsers-07-troubleshooting.md) for error handling and optimization.
|
|
699
|
+
|
|
700
|
+
---
|
|
701
|
+
|
|
702
|
+
**Module 6 Complete!** ✅
|