@fluentcommerce/fc-connect-sdk 0.1.53 → 0.1.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -2
- package/README.md +39 -0
- package/dist/cjs/auth/index.d.ts +3 -0
- package/dist/cjs/auth/index.js +13 -0
- package/dist/cjs/auth/profile-loader.d.ts +18 -0
- package/dist/cjs/auth/profile-loader.js +208 -0
- package/dist/cjs/client-factory.d.ts +4 -0
- package/dist/cjs/client-factory.js +10 -0
- package/dist/cjs/clients/fluent-client.js +13 -6
- package/dist/cjs/index.d.ts +3 -1
- package/dist/cjs/index.js +8 -2
- package/dist/cjs/utils/pagination-helpers.js +38 -2
- package/dist/cjs/versori/fluent-versori-client.js +11 -5
- package/dist/esm/auth/index.d.ts +3 -0
- package/dist/esm/auth/index.js +2 -0
- package/dist/esm/auth/profile-loader.d.ts +18 -0
- package/dist/esm/auth/profile-loader.js +169 -0
- package/dist/esm/client-factory.d.ts +4 -0
- package/dist/esm/client-factory.js +9 -0
- package/dist/esm/clients/fluent-client.js +13 -6
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/utils/pagination-helpers.js +38 -2
- package/dist/esm/versori/fluent-versori-client.js +11 -5
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/tsconfig.types.tsbuildinfo +1 -1
- package/dist/types/auth/index.d.ts +3 -0
- package/dist/types/auth/profile-loader.d.ts +18 -0
- package/dist/types/client-factory.d.ts +4 -0
- package/dist/types/index.d.ts +3 -1
- package/docs/00-START-HERE/EXPORT-VALIDATION.md +158 -158
- package/docs/00-START-HERE/cli-analyze-source-structure-guide.md +655 -655
- package/docs/00-START-HERE/cli-documentation-index.md +202 -202
- package/docs/00-START-HERE/cli-quick-reference.md +252 -252
- package/docs/00-START-HERE/decision-tree.md +552 -552
- package/docs/00-START-HERE/getting-started.md +1070 -1070
- package/docs/00-START-HERE/mapper-quick-decision-guide.md +235 -235
- package/docs/00-START-HERE/readme.md +237 -237
- package/docs/00-START-HERE/retailerid-configuration.md +404 -404
- package/docs/00-START-HERE/sdk-philosophy.md +794 -794
- package/docs/00-START-HERE/troubleshooting-quick-reference.md +1086 -1086
- package/docs/01-TEMPLATES/faq.md +686 -686
- package/docs/01-TEMPLATES/patterns/pattern-templates-guide.md +68 -68
- package/docs/01-TEMPLATES/patterns/patterns-csv-schema-validation-and-rejection-report.md +233 -233
- package/docs/01-TEMPLATES/patterns/patterns-custom-resolvers.md +407 -407
- package/docs/01-TEMPLATES/patterns/patterns-error-handling-retry.md +511 -511
- package/docs/01-TEMPLATES/patterns/patterns-field-mapping-universal.md +701 -701
- package/docs/01-TEMPLATES/patterns/patterns-large-file-splitting.md +1430 -1430
- package/docs/01-TEMPLATES/patterns/patterns-master-data-etl.md +2399 -2399
- package/docs/01-TEMPLATES/patterns/patterns-pagination-streaming.md +447 -447
- package/docs/01-TEMPLATES/patterns/patterns-state-duplicate-prevention.md +385 -385
- package/docs/01-TEMPLATES/readme.md +957 -957
- package/docs/01-TEMPLATES/standalone/standalone-asn-inbound-processing.md +1209 -1209
- package/docs/01-TEMPLATES/standalone/standalone-graphql-query-export.md +1140 -1140
- package/docs/01-TEMPLATES/standalone/standalone-graphql-to-parquet-partitioned-s3.md +432 -432
- package/docs/01-TEMPLATES/standalone/standalone-multi-channel-inventory-sync.md +1185 -1185
- package/docs/01-TEMPLATES/standalone/standalone-multi-source-aggregation.md +1462 -1462
- package/docs/01-TEMPLATES/standalone/standalone-s3-csv-batch-api.md +1390 -1390
- package/docs/01-TEMPLATES/standalone/standalone-s3-csv-inventory-to-batch.md +330 -330
- package/docs/01-TEMPLATES/standalone/standalone-scripts-guide.md +87 -87
- package/docs/01-TEMPLATES/standalone/standalone-sftp-xml-graphql.md +1444 -1444
- package/docs/01-TEMPLATES/standalone/standalone-webhook-payload-processing.md +688 -688
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-dropship-order-routing.md +193 -193
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-graphql-parquet-extraction.md +518 -518
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-inter-location-transfers.md +2162 -2162
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-pre-order-allocation.md +2226 -2226
- package/docs/01-TEMPLATES/versori/business-examples/business-scenarios-guide.md +87 -87
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-connection-validation-pattern.md +656 -656
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-dual-workflow-connector.md +835 -835
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-guide.md +108 -108
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-kv-state-management.md +1533 -1533
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-xml-response-patterns.md +1160 -1160
- package/docs/01-TEMPLATES/versori/versori-platform-guide.md +201 -201
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-asn-purchase-order.md +1906 -1906
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-dropship-routing.md +1074 -1074
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-flash-sale-reserve.md +1395 -1395
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-generic-xml-order.md +888 -888
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-payment-gateway-integration.md +2478 -2478
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-rma-returns-comprehensive.md +2240 -2240
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-xml-order-ingestion.md +2029 -2029
- package/docs/01-TEMPLATES/versori/webhooks/webhook-templates-guide.md +140 -140
- package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/inventory-mapping.json +20 -20
- package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/products_2025-01-22.csv +11 -11
- package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/sample-data-guide.md +34 -34
- package/docs/01-TEMPLATES/versori/workflows/_examples/workflow-examples-guide.md +36 -36
- package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-modes-guide.md +1038 -1038
- package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-workflows-guide.md +138 -138
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/graphql-extraction-guide.md +63 -63
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-csv.md +2062 -2062
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-xml.md +2294 -2294
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-s3-csv.md +2461 -2461
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-sftp-xml.md +2529 -2529
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-csv.md +2464 -2464
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-json.md +1959 -1959
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-s3-csv.md +1953 -1953
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-sftp-xml.md +2541 -2541
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-s3-json.md +2384 -2384
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-sftp-xml.md +2445 -2445
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-csv.md +2355 -2355
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-json.md +2042 -2042
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-sftp-xml.md +2726 -2726
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/batch-api-guide.md +206 -206
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-cycle-count-reconciliation.md +2030 -2030
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-multi-channel-inventory-sync.md +1882 -1882
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-csv-inventory-batch.md +2827 -2827
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-json-inventory-batch.md +1952 -1952
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-xml-inventory-batch.md +3289 -3289
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-csv-inventory-batch.md +3064 -3064
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-json-inventory-batch.md +3238 -3238
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-xml-inventory-batch.md +2977 -2977
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/event-api-guide.md +321 -321
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-json-order-cancel-event.md +959 -959
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-xml-order-cancel-event.md +1170 -1170
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-csv-product-event.md +2312 -2312
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-json-product-event.md +2999 -2999
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-parquet-product-event.md +2836 -2836
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-xml-product-event.md +2395 -2395
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-csv-product-event.md +2295 -2295
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-json-product-event.md +2602 -2602
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-parquet-product-event.md +2589 -2589
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-xml-product-event.md +3578 -3578
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/graphql-mutations-guide.md +93 -93
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-json-order-update-graphql.md +1260 -1260
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-xml-order-update-graphql.md +1472 -1472
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-control-graphql.md +2417 -2417
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-location-graphql.md +2811 -2811
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-price-graphql.md +2619 -2619
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-json-location-graphql.md +2807 -2807
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-xml-location-graphql.md +2373 -2373
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-control-graphql.md +2740 -2740
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-location-graphql.md +2760 -2760
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-json-location-graphql.md +1710 -1710
- package/docs/01-TEMPLATES/versori/workflows/ingestion/ingestion-workflows-guide.md +136 -136
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/rubix-webhooks-guide.md +520 -520
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-inline.md +1418 -1418
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-universal-mapper.md +1785 -1785
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-order-attribute-update.md +824 -824
- package/docs/01-TEMPLATES/versori/workflows/workflows-overview-guide.md +646 -646
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-batch-archival.md +724 -724
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-job-tracker.md +627 -627
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-partial-batch-recovery.md +561 -561
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-quick-reference.md +367 -367
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-readme.md +407 -407
- package/docs/02-CORE-GUIDES/advanced-services/readme.md +49 -49
- package/docs/02-CORE-GUIDES/api-reference/api-reference-quick-reference.md +548 -548
- package/docs/02-CORE-GUIDES/api-reference/event-api-input-output-reference.md +702 -1171
- package/docs/02-CORE-GUIDES/api-reference/examples/client-initialization.ts +286 -286
- package/docs/02-CORE-GUIDES/api-reference/graphql-error-classification.md +337 -337
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-01-client-api.md +399 -482
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-03-authentication.md +199 -199
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-04-graphql-mapping.md +925 -925
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-05-services.md +1198 -1198
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-06-data-sources.md +1083 -1083
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-07-parsers.md +1097 -1097
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-pagination.md +513 -513
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-types.md +545 -597
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-error-handling.md +527 -527
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-webhook-validation.md +514 -514
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-extraction.md +557 -557
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-utilities.md +412 -412
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-cli-tools.md +423 -423
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-error-handling.md +716 -716
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-analyze-source-structure.md +518 -518
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-partial-responses.md +212 -212
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-testing.md +300 -300
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-13-resolver-builder.md +322 -322
- package/docs/02-CORE-GUIDES/api-reference/readme.md +279 -279
- package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-quick-reference.md +351 -351
- package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-readme.md +277 -277
- package/docs/02-CORE-GUIDES/auto-pagination/examples/auto-pagination-readme.md +178 -178
- package/docs/02-CORE-GUIDES/auto-pagination/examples/common-patterns.ts +351 -351
- package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-products.ts +384 -384
- package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-virtual-positions.ts +308 -308
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-01-foundations.md +470 -470
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-02-quick-start.md +713 -713
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-03-configuration.md +754 -754
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-04-advanced-patterns.md +732 -732
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-05-sdk-integration.md +847 -847
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-06-troubleshooting.md +359 -359
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-07-api-reference.md +462 -462
- package/docs/02-CORE-GUIDES/auto-pagination/readme.md +54 -54
- package/docs/02-CORE-GUIDES/data-sources/data-sources-file-operations-error-handling.md +1487 -1487
- package/docs/02-CORE-GUIDES/data-sources/data-sources-quick-reference.md +836 -836
- package/docs/02-CORE-GUIDES/data-sources/data-sources-readme.md +276 -276
- package/docs/02-CORE-GUIDES/data-sources/data-sources-sftp-credential-access-security.md +553 -553
- package/docs/02-CORE-GUIDES/data-sources/examples/common-patterns.ts +409 -409
- package/docs/02-CORE-GUIDES/data-sources/examples/data-sources-readme.md +178 -178
- package/docs/02-CORE-GUIDES/data-sources/examples/s3-operations.ts +308 -308
- package/docs/02-CORE-GUIDES/data-sources/examples/sftp-operations.ts +371 -371
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-01-foundations.md +735 -735
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-02-s3-operations.md +1302 -1302
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-03-sftp-operations.md +1379 -1379
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-04-file-patterns.md +941 -941
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-05-advanced-topics.md +813 -813
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-06-integration-patterns.md +486 -486
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-07-troubleshooting.md +387 -387
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-08-api-reference.md +417 -417
- package/docs/02-CORE-GUIDES/data-sources/readme.md +77 -77
- package/docs/02-CORE-GUIDES/error-handling-guide.md +936 -936
- package/docs/02-CORE-GUIDES/extraction/examples/02-core-guides-extraction-readme.md +116 -116
- package/docs/02-CORE-GUIDES/extraction/examples/common-patterns.ts +428 -428
- package/docs/02-CORE-GUIDES/extraction/examples/extract-inventory-basic.ts +187 -187
- package/docs/02-CORE-GUIDES/extraction/extraction-quick-reference.md +596 -596
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-01-foundations.md +514 -514
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-02-basic-extraction.md +823 -823
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-03-parquet-processing.md +507 -507
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-04-data-enrichment.md +546 -546
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-05-transformation.md +494 -494
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-export-formats.md +458 -458
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-performance.md +138 -138
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-api-reference.md +148 -148
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-optimization.md +692 -692
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-08-extraction-orchestrator.md +1008 -1008
- package/docs/02-CORE-GUIDES/extraction/readme.md +151 -151
- package/docs/02-CORE-GUIDES/ingestion/examples/_simple-kv-store.ts +40 -40
- package/docs/02-CORE-GUIDES/ingestion/examples/error-recovery.ts +728 -728
- package/docs/02-CORE-GUIDES/ingestion/examples/event-driven.ts +501 -501
- package/docs/02-CORE-GUIDES/ingestion/examples/local-file-ingestion.ts +88 -88
- package/docs/02-CORE-GUIDES/ingestion/examples/parquet-ingestion.ts +117 -117
- package/docs/02-CORE-GUIDES/ingestion/examples/performance-optimized.ts +647 -647
- package/docs/02-CORE-GUIDES/ingestion/examples/s3-csv-ingestion.ts +169 -169
- package/docs/02-CORE-GUIDES/ingestion/examples/sftp-csv-ingestion.ts +134 -134
- package/docs/02-CORE-GUIDES/ingestion/ingestion-quick-reference.md +546 -546
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-01-introduction.md +626 -626
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-02-quick-start.md +658 -658
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-03-data-sources.md +1052 -1052
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-04-field-mapping.md +763 -763
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-05-advanced-parsers.md +676 -676
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-06-batch-api.md +1295 -1295
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-api-reference.md +138 -138
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-state-management.md +1037 -1037
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-08-performance-optimization.md +1349 -1349
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-09-best-practices.md +1893 -1893
- package/docs/02-CORE-GUIDES/ingestion/readme.md +160 -160
- package/docs/02-CORE-GUIDES/logging-guide.md +585 -585
- package/docs/02-CORE-GUIDES/mapping/error-handling-patterns.md +401 -401
- package/docs/02-CORE-GUIDES/mapping/examples/02-core-guides-mapping-readme.md +128 -128
- package/docs/02-CORE-GUIDES/mapping/examples/common-patterns.ts +273 -273
- package/docs/02-CORE-GUIDES/mapping/examples/csv-location-ingestion.json +36 -36
- package/docs/02-CORE-GUIDES/mapping/examples/csv-mapping.ts +242 -242
- package/docs/02-CORE-GUIDES/mapping/examples/graphql-to-parquet-extraction.json +36 -36
- package/docs/02-CORE-GUIDES/mapping/examples/json-mapping.ts +213 -213
- package/docs/02-CORE-GUIDES/mapping/examples/json-product-to-mutation.json +48 -48
- package/docs/02-CORE-GUIDES/mapping/examples/xml-mapping.ts +291 -291
- package/docs/02-CORE-GUIDES/mapping/examples/xml-order-to-mutation.json +45 -45
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-quick-reference.md +463 -463
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-readme.md +227 -227
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-01-introduction.md +222 -222
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-02-quick-start.md +351 -351
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-03-schema-validation.md +569 -569
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-04-mapping-patterns.md +471 -471
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-05-configuration-reference.md +611 -611
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-advanced-xpath.md +148 -148
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-path-syntax.md +464 -464
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-api-reference.md +94 -94
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-array-handling.md +307 -307
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-08-custom-resolvers.md +544 -544
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-09-advanced-patterns.md +427 -427
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-10-hooks-and-variables.md +336 -336
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-11-error-handling.md +488 -488
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-12-arguments-vs-nodes.md +383 -383
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-13-best-practices.md +477 -477
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/readme.md +62 -62
- package/docs/02-CORE-GUIDES/mapping/mapping-format-decision-tree.md +480 -480
- package/docs/02-CORE-GUIDES/mapping/mapping-graphql-alias-batching-guide.md +820 -820
- package/docs/02-CORE-GUIDES/mapping/mapping-javascript-objects.md +2369 -2369
- package/docs/02-CORE-GUIDES/mapping/mapping-mapper-comparison-guide.md +682 -682
- package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-07-api-reference.md +1327 -1327
- package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-08-error-handling.md +1142 -1142
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-04-use-cases.md +891 -891
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-helpers-resolvers.md +1126 -1126
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-sdk-resolvers.md +199 -199
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-07-api-reference.md +1319 -1319
- package/docs/02-CORE-GUIDES/mapping/readme.md +178 -178
- package/docs/02-CORE-GUIDES/mapping/resolver-registration.md +410 -410
- package/docs/02-CORE-GUIDES/mapping/resolvers/examples/common-patterns.ts +226 -226
- package/docs/02-CORE-GUIDES/mapping/resolvers/examples/custom-resolvers.ts +227 -227
- package/docs/02-CORE-GUIDES/mapping/resolvers/examples/sdk-resolvers-usage.ts +203 -203
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-readme.md +274 -274
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-api-reference.md +679 -679
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-cookbook.md +826 -826
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-guide.md +1330 -1330
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-helpers-reference.md +1437 -1437
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-parameters-reference.md +553 -553
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-troubleshooting.md +854 -854
- package/docs/02-CORE-GUIDES/mapping/resolvers/readme.md +75 -75
- package/docs/02-CORE-GUIDES/parsers/examples/02-core-guides-parsers-readme.md +161 -161
- package/docs/02-CORE-GUIDES/parsers/examples/csv-parser-examples.ts +110 -110
- package/docs/02-CORE-GUIDES/parsers/examples/json-parser-examples.ts +33 -33
- package/docs/02-CORE-GUIDES/parsers/examples/parquet-parser-examples.ts +47 -47
- package/docs/02-CORE-GUIDES/parsers/examples/xml-parser-examples.ts +38 -38
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-01-foundations.md +355 -355
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-02-csv-parser.md +772 -772
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-03-json-parser.md +789 -789
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-04-xml-parser.md +857 -857
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-05-parquet-parser.md +603 -603
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-integration-patterns.md +702 -702
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-streaming.md +121 -121
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-api-reference.md +89 -89
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-troubleshooting.md +727 -727
- package/docs/02-CORE-GUIDES/parsers/parsers-quick-reference.md +482 -482
- package/docs/02-CORE-GUIDES/parsers/parsers-readme.md +258 -258
- package/docs/02-CORE-GUIDES/parsers/readme.md +65 -65
- package/docs/02-CORE-GUIDES/readme.md +194 -194
- package/docs/02-CORE-GUIDES/webhook-validation/examples/basic-validation.ts +108 -108
- package/docs/02-CORE-GUIDES/webhook-validation/examples/common-patterns.ts +316 -316
- package/docs/02-CORE-GUIDES/webhook-validation/examples/webhook-validation-readme.md +61 -61
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-01-foundations.md +440 -440
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-02-quick-start.md +525 -525
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-03-versori-integration.md +741 -741
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-04-platform-integration.md +629 -629
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-05-configuration.md +535 -535
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-error-handling.md +611 -611
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-troubleshooting.md +124 -124
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-07-api-reference.md +511 -511
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-08-rubix-webhooks.md +590 -590
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-09-rubix-event-vs-http-call.md +432 -432
- package/docs/02-CORE-GUIDES/webhook-validation/readme.md +239 -239
- package/docs/02-CORE-GUIDES/webhook-validation/webhook-validation-quick-reference.md +392 -392
- package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-quick-reference.md +498 -498
- package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-readme.md +313 -313
- package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/common-patterns.ts +612 -612
- package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/connector-scenarios-readme.md +253 -253
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-01-foundations.md +452 -452
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-02-simple-scenarios.md +681 -681
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-03-intermediate-scenarios.md +637 -637
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-04-advanced-scenarios.md +650 -650
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-05-bidirectional-sync.md +233 -233
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-06-production-patterns.md +442 -442
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-07-reference.md +445 -445
- package/docs/03-PATTERN-GUIDES/connector-scenarios/readme.md +31 -31
- package/docs/03-PATTERN-GUIDES/enterprise-integration-patterns.md +1528 -1528
- package/docs/03-PATTERN-GUIDES/error-handling/comprehensive-error-handling-guide.md +1437 -1437
- package/docs/03-PATTERN-GUIDES/error-handling/error-handling-quick-reference.md +390 -390
- package/docs/03-PATTERN-GUIDES/error-handling/examples/common-patterns.ts +438 -438
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-01-foundations.md +362 -362
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-02-error-types.md +850 -850
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-03-utf8-handling.md +456 -456
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-04-error-scenarios.md +658 -658
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-05-calling-patterns.md +671 -671
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-06-retry-strategies.md +1034 -1034
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-07-monitoring.md +653 -653
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-08-api-reference.md +847 -847
- package/docs/03-PATTERN-GUIDES/error-handling/readme.md +36 -36
- package/docs/03-PATTERN-GUIDES/examples/__tests__/readme.md +40 -40
- package/docs/03-PATTERN-GUIDES/examples/__tests__/resolver-examples.test.js +282 -282
- package/docs/03-PATTERN-GUIDES/examples/test-data/03-pattern-guides-readme.md +110 -110
- package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-inventory.json +123 -123
- package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-order.json +171 -171
- package/docs/03-PATTERN-GUIDES/examples/test-data/readme.md +28 -28
- package/docs/03-PATTERN-GUIDES/extraction/extraction-readme.md +15 -15
- package/docs/03-PATTERN-GUIDES/extraction/readme.md +25 -25
- package/docs/03-PATTERN-GUIDES/file-operations/examples/common-patterns.ts +407 -407
- package/docs/03-PATTERN-GUIDES/file-operations/examples/file-operations-readme.md +142 -142
- package/docs/03-PATTERN-GUIDES/file-operations/file-operations-quick-reference.md +462 -462
- package/docs/03-PATTERN-GUIDES/file-operations/file-operations-readme.md +379 -379
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-01-foundations.md +430 -430
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-02-quick-start.md +484 -484
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-03-s3-operations.md +507 -507
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-04-sftp-operations.md +963 -963
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-05-streaming-performance.md +503 -503
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-archive-patterns.md +386 -386
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-error-handling.md +117 -117
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-api-reference.md +78 -78
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-testing-troubleshooting.md +567 -567
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-08-api-reference.md +1055 -1055
- package/docs/03-PATTERN-GUIDES/file-operations/readme.md +32 -32
- package/docs/03-PATTERN-GUIDES/ingestion/ingestion-readme.md +15 -15
- package/docs/03-PATTERN-GUIDES/ingestion/readme.md +25 -25
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/batch-processing.ts +130 -130
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/common-patterns.ts +360 -360
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/delta-sync.ts +130 -130
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/integration-patterns-readme.md +100 -100
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/real-time-webhook.ts +398 -398
- package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-quick-reference.md +962 -962
- package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-readme.md +134 -134
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-01-real-time-processing.md +991 -991
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-02-batch-processing.md +1547 -1547
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-03-delta-sync.md +1108 -1108
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-04-webhook-patterns.md +1181 -1181
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-05-error-handling.md +1061 -1061
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-advanced-integration-services.md +1547 -1547
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-performance.md +109 -109
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-07-api-reference.md +34 -34
- package/docs/03-PATTERN-GUIDES/integration-patterns/readme.md +30 -30
- package/docs/03-PATTERN-GUIDES/logging-minimal-mode.md +128 -128
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/common-patterns.ts +380 -380
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/multiple-connections-readme.md +139 -139
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/parallel-root-connections.ts +149 -149
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/real-world-scenarios.ts +405 -405
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-01-foundations.md +378 -378
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-02-quick-start.md +566 -566
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-03-targeting-connections.md +659 -659
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-04-parallel-queries.md +656 -656
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-05-best-practices.md +624 -624
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-api-reference.md +824 -824
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-versori.md +119 -119
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-07-api-reference.md +87 -87
- package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-quick-reference.md +353 -353
- package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-readme.md +270 -270
- package/docs/03-PATTERN-GUIDES/multiple-connections/readme.md +30 -30
- package/docs/03-PATTERN-GUIDES/pagination/pagination-readme.md +14 -14
- package/docs/03-PATTERN-GUIDES/pagination/readme.md +24 -24
- package/docs/03-PATTERN-GUIDES/parquet/examples/common-patterns.ts +180 -180
- package/docs/03-PATTERN-GUIDES/parquet/examples/read-parquet.ts +48 -48
- package/docs/03-PATTERN-GUIDES/parquet/examples/write-parquet.ts +65 -65
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-01-introduction.md +393 -393
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-02-quick-start.md +572 -572
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-03-reading-parquet.md +525 -525
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-04-writing-parquet.md +554 -554
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-05-graphql-extraction.md +405 -405
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-performance.md +104 -104
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-s3-integration.md +511 -511
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-api-reference.md +90 -90
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-performance-optimization.md +525 -525
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-08-best-practices.md +712 -712
- package/docs/03-PATTERN-GUIDES/parquet/parquet-quick-reference.md +683 -683
- package/docs/03-PATTERN-GUIDES/parquet/parquet-readme.md +248 -248
- package/docs/03-PATTERN-GUIDES/parquet/readme.md +32 -32
- package/docs/03-PATTERN-GUIDES/parsers/parsers-readme.md +12 -12
- package/docs/03-PATTERN-GUIDES/parsers/readme.md +24 -24
- package/docs/03-PATTERN-GUIDES/readme.md +159 -159
- package/docs/03-PATTERN-GUIDES/webhooks/readme.md +24 -24
- package/docs/03-PATTERN-GUIDES/webhooks/webhooks-readme.md +8 -8
- package/docs/04-REFERENCE/architecture/architecture-01-overview.md +427 -427
- package/docs/04-REFERENCE/architecture/architecture-02-client-architecture.md +424 -424
- package/docs/04-REFERENCE/architecture/architecture-03-data-flow.md +690 -690
- package/docs/04-REFERENCE/architecture/architecture-04-service-layer.md +834 -834
- package/docs/04-REFERENCE/architecture/architecture-05-integration-architecture.md +655 -655
- package/docs/04-REFERENCE/architecture/architecture-06-state-management.md +653 -653
- package/docs/04-REFERENCE/architecture/architecture-adding-new-data-sources.md +686 -686
- package/docs/04-REFERENCE/architecture/readme.md +279 -279
- package/docs/04-REFERENCE/platforms/deno/readme.md +117 -117
- package/docs/04-REFERENCE/platforms/nodejs/readme.md +146 -146
- package/docs/04-REFERENCE/platforms/readme.md +135 -135
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-01-introduction.md +398 -398
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-02-quick-start.md +560 -560
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-03-authentication.md +757 -757
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-04-workflows.md +2476 -2476
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-05-connections.md +1167 -1167
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-kv-storage.md +990 -990
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-state-management.md +121 -121
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-api-reference.md +68 -68
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-deployment.md +731 -731
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-08-best-practices.md +1111 -1111
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-09-signature-reference.md +766 -766
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-readme.md +299 -299
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-s3-sftp-configuration-guide.md +1425 -1425
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-api-key-security.md +816 -816
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-connection-security.md +681 -681
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-workflow-task-types.md +708 -708
- package/docs/04-REFERENCE/platforms/versori/readme.md +108 -108
- package/docs/04-REFERENCE/readme.md +148 -148
- package/docs/04-REFERENCE/resolver-signature/examples/advanced-resolvers.ts +482 -482
- package/docs/04-REFERENCE/resolver-signature/examples/async-resolvers.ts +496 -496
- package/docs/04-REFERENCE/resolver-signature/examples/basic-resolvers.ts +343 -343
- package/docs/04-REFERENCE/resolver-signature/examples/resolver-signature-readme.md +188 -188
- package/docs/04-REFERENCE/resolver-signature/examples/testing-resolvers.ts +463 -463
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-01-foundations.md +286 -286
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-02-parameter-reference.md +643 -643
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-03-basic-examples.md +521 -521
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-04-advanced-patterns.md +739 -739
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-05-sdk-resolvers.md +531 -531
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-migration-guide.md +650 -650
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-testing.md +125 -125
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-07-api-reference.md +794 -794
- package/docs/04-REFERENCE/resolver-signature/readme.md +64 -64
- package/docs/04-REFERENCE/resolver-signature/resolver-signature-quick-reference.md +270 -270
- package/docs/04-REFERENCE/resolver-signature/resolver-signature-readme.md +351 -351
- package/docs/04-REFERENCE/schema/fluent-commerce-schema.json +764 -764
- package/docs/04-REFERENCE/schema/readme.md +141 -141
- package/docs/04-REFERENCE/testing/examples/04-reference-testing-readme.md +158 -158
- package/docs/04-REFERENCE/testing/examples/fluent-testing.ts +62 -62
- package/docs/04-REFERENCE/testing/examples/health-check.ts +155 -155
- package/docs/04-REFERENCE/testing/examples/integration-test.ts +119 -119
- package/docs/04-REFERENCE/testing/examples/performance-test.ts +183 -183
- package/docs/04-REFERENCE/testing/examples/s3-testing.ts +127 -127
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-01-foundations.md +267 -267
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-02-s3-testing.md +599 -599
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-03-fluent-testing.md +589 -589
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-04-integration-testing.md +699 -699
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-05-debugging.md +478 -478
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-cicd-integration.md +463 -463
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-preflight-validation.md +131 -131
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-best-practices.md +499 -499
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-coverage-ci.md +165 -165
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-08-api-reference.md +634 -634
- package/docs/04-REFERENCE/testing/readme.md +86 -86
- package/docs/04-REFERENCE/testing/testing-quick-reference.md +667 -667
- package/docs/04-REFERENCE/testing/testing-readme.md +286 -286
- package/docs/04-REFERENCE/troubleshooting/readme.md +144 -144
- package/docs/04-REFERENCE/troubleshooting/troubleshooting-deno-sftp-compatibility.md +392 -392
- package/docs/template-loading-matrix.md +242 -242
- package/package.json +5 -3
|
@@ -1,891 +1,891 @@
|
|
|
1
|
-
# Module 4: Use Cases
|
|
2
|
-
|
|
3
|
-
**Real-world transformation scenarios**
|
|
4
|
-
|
|
5
|
-
**Level:** Intermediate
|
|
6
|
-
**Time:** 45 minutes
|
|
7
|
-
**Prerequisites:** [Module 3: Schema Validation](./mapping-03-schema-validation.md)
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## Learning Objectives
|
|
12
|
-
|
|
13
|
-
After completing this module, you will:
|
|
14
|
-
|
|
15
|
-
- ✅ Implement CSV ingestion to Fluent Batch API
|
|
16
|
-
- ✅ Transform XML to GraphQL mutations for order creation
|
|
17
|
-
- ✅ Generate XML from Fluent data for external APIs
|
|
18
|
-
- ✅ Extract GraphQL data to Parquet format
|
|
19
|
-
- ✅ Understand real-world connector patterns
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## Use Case 1: CSV Ingestion → Fluent Batch API
|
|
24
|
-
|
|
25
|
-
**Scenario:** Import inventory positions from CSV files to Fluent Commerce
|
|
26
|
-
|
|
27
|
-
### Source Data
|
|
28
|
-
|
|
29
|
-
**CSV Format:**
|
|
30
|
-
|
|
31
|
-
```csv
|
|
32
|
-
sku,location,quantity,status
|
|
33
|
-
PROD-001,WAREHOUSE-A,100,active
|
|
34
|
-
PROD-002,WAREHOUSE-A,50,reserved
|
|
35
|
-
PROD-003,WAREHOUSE-B,200,active
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### Mapping Configuration
|
|
39
|
-
|
|
40
|
-
**File: `config/inventory-ingestion.json`**
|
|
41
|
-
|
|
42
|
-
```json
|
|
43
|
-
{
|
|
44
|
-
"direction": "ingest",
|
|
45
|
-
"sourceFormat": "csv",
|
|
46
|
-
"mutation": "upsertInventoryPosition",
|
|
47
|
-
"comment": "✅ Validated against schema: docs/schema/fluent-commerce-schema.json → Mutation.upsertInventoryPosition",
|
|
48
|
-
|
|
49
|
-
"fields": {
|
|
50
|
-
"ref": {
|
|
51
|
-
"source": "sku",
|
|
52
|
-
"required": true,
|
|
53
|
-
"comment": "✅ UpsertInventoryPositionInput.ref (String! required) - unique position identifier"
|
|
54
|
-
},
|
|
55
|
-
"productRef": {
|
|
56
|
-
"source": "sku",
|
|
57
|
-
"required": true,
|
|
58
|
-
"comment": "✅ UpsertInventoryPositionInput.productRef (String! required)"
|
|
59
|
-
},
|
|
60
|
-
"locationRef": {
|
|
61
|
-
"source": "location",
|
|
62
|
-
"required": true,
|
|
63
|
-
"comment": "✅ UpsertInventoryPositionInput.locationRef (String! required)"
|
|
64
|
-
},
|
|
65
|
-
"qty": {
|
|
66
|
-
"source": "quantity",
|
|
67
|
-
"resolver": "sdk.parseInt",
|
|
68
|
-
"required": true,
|
|
69
|
-
"comment": "✅ UpsertInventoryPositionInput.qty (Int! required)"
|
|
70
|
-
},
|
|
71
|
-
"status": {
|
|
72
|
-
"source": "status",
|
|
73
|
-
"resolver": "sdk.uppercase",
|
|
74
|
-
"defaultValue": "AVAILABLE",
|
|
75
|
-
"comment": "✅ UpsertInventoryPositionInput.status (String) - e.g., AVAILABLE, RESERVED"
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Implementation
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
import { UniversalMapper, CSVParserService, createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
85
|
-
import * as fs from 'fs';
|
|
86
|
-
|
|
87
|
-
// Load mapping configuration
|
|
88
|
-
const mappingConfig = JSON.parse(fs.readFileSync('./config/inventory-ingestion.json', 'utf-8'));
|
|
89
|
-
|
|
90
|
-
// Load and parse CSV
|
|
91
|
-
const csvContent = fs.readFileSync('./data/inventory.csv', 'utf-8');
|
|
92
|
-
const parser = new CSVParserService();
|
|
93
|
-
const records = await parser.parse(csvContent);
|
|
94
|
-
|
|
95
|
-
// Create mapper
|
|
96
|
-
const mapper = new UniversalMapper(mappingConfig);
|
|
97
|
-
|
|
98
|
-
// Process each CSV row
|
|
99
|
-
const batchEntities = [];
|
|
100
|
-
for (const row of records) {
|
|
101
|
-
const result = await mapper.map(row);
|
|
102
|
-
|
|
103
|
-
if (result.success) {
|
|
104
|
-
batchEntities.push(result.data);
|
|
105
|
-
} else {
|
|
106
|
-
console.error('Mapping failed for row:', row);
|
|
107
|
-
console.error('Errors:', result.errors);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Create Fluent client
|
|
112
|
-
const client = await createClient({
|
|
113
|
-
config: {
|
|
114
|
-
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
115
|
-
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
116
|
-
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
117
|
-
username: process.env.FLUENT_USERNAME!,
|
|
118
|
-
password: process.env.FLUENT_PASSWORD!,
|
|
119
|
-
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
120
|
-
},
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
// Create batch job
|
|
124
|
-
const job = await client.createJob({
|
|
125
|
-
name: 'inventory-update',
|
|
126
|
-
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
// Send batch to Fluent Commerce
|
|
130
|
-
await client.sendBatch(job.id, {
|
|
131
|
-
action: 'UPSERT',
|
|
132
|
-
entityType: 'INVENTORY',
|
|
133
|
-
source: 'CSV_IMPORT',
|
|
134
|
-
event: 'INVENTORY_UPDATE',
|
|
135
|
-
entities: batchEntities,
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
console.log(`✅ Successfully processed ${batchEntities.length} inventory positions`);
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### Key Points
|
|
142
|
-
|
|
143
|
-
- **Batch Processing:** Efficient for high-volume imports (1000s of records)
|
|
144
|
-
- **Validation:** `required: true` catches missing data before API calls
|
|
145
|
-
- **Resolvers:** `sdk.parseInt` ensures numeric types, `sdk.uppercase` normalizes status
|
|
146
|
-
- **Error Handling:** Individual row failures don't stop the entire batch
|
|
147
|
-
|
|
148
|
-
**Schema Reference:**
|
|
149
|
-
|
|
150
|
-
- Mutation: `upsertInventoryPosition(input: UpsertInventoryPositionInput!): InventoryPosition`
|
|
151
|
-
- See [`docs/schema/fluent-commerce-schema.json`](../../../04-REFERENCE/schema/fluent-commerce-schema.json) → `inputs.UpsertInventoryPositionInput`
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## Use Case 2: XML → GraphQL Mutation
|
|
156
|
-
|
|
157
|
-
**Scenario:** Transform SFCC order XML to Fluent order mutation
|
|
158
|
-
|
|
159
|
-
### Source Data
|
|
160
|
-
|
|
161
|
-
**SFCC Order XML:**
|
|
162
|
-
|
|
163
|
-
```xml
|
|
164
|
-
<order id="ORD-123" type="standard">
|
|
165
|
-
<customer email="john@example.com" />
|
|
166
|
-
<total currency="USD">99.99</total>
|
|
167
|
-
<items>
|
|
168
|
-
<item id="ITEM-1" sku="PROD-001" qty="2" unitPrice="49.99" />
|
|
169
|
-
</items>
|
|
170
|
-
</order>
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### Mapping Configuration
|
|
174
|
-
|
|
175
|
-
**File: `mappings/sfcc-order-to-fluent.json`**
|
|
176
|
-
|
|
177
|
-
```json
|
|
178
|
-
{
|
|
179
|
-
"direction": "ingest",
|
|
180
|
-
"sourceFormat": "xml",
|
|
181
|
-
"mutation": "createOrder",
|
|
182
|
-
"comment": "✅ Validated against schema: docs/schema/fluent-commerce-schema.json → Mutation.createOrder",
|
|
183
|
-
|
|
184
|
-
"fields": {
|
|
185
|
-
"ref": {
|
|
186
|
-
"source": "order@id",
|
|
187
|
-
"required": true,
|
|
188
|
-
"comment": "✅ CreateOrderInput.ref (String! required)"
|
|
189
|
-
},
|
|
190
|
-
"type": {
|
|
191
|
-
"source": "order@type",
|
|
192
|
-
"resolver": "custom.mapOrderType",
|
|
193
|
-
"comment": "✅ CreateOrderInput.type (OrderType! enum required) - maps 'standard' → 'STANDARD'"
|
|
194
|
-
},
|
|
195
|
-
"retailer": {
|
|
196
|
-
"fields": {
|
|
197
|
-
"id": {
|
|
198
|
-
"value": "1",
|
|
199
|
-
"comment": "✅ CreateOrderInput.retailer (RetailerInput! required)"
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
},
|
|
203
|
-
"customer": {
|
|
204
|
-
"fields": {
|
|
205
|
-
"email": {
|
|
206
|
-
"source": "order.customer@email",
|
|
207
|
-
"resolver": "sdk.lowercase",
|
|
208
|
-
"comment": "✅ CreateOrderInput.customer.email (String!)"
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
"totalPrice": {
|
|
213
|
-
"source": "order.total",
|
|
214
|
-
"resolver": "sdk.parseFloat",
|
|
215
|
-
"required": true,
|
|
216
|
-
"comment": "✅ CreateOrderInput.totalPrice (Float! required)"
|
|
217
|
-
},
|
|
218
|
-
"currency": {
|
|
219
|
-
"source": "order.total@currency",
|
|
220
|
-
"defaultValue": "USD",
|
|
221
|
-
"comment": "✅ CreateOrderInput.currency (String! required)"
|
|
222
|
-
},
|
|
223
|
-
"items": {
|
|
224
|
-
"source": "order.items.item",
|
|
225
|
-
"isArray": true,
|
|
226
|
-
"comment": "✅ CreateOrderInput.items ([OrderItemInput]! required)",
|
|
227
|
-
"fields": {
|
|
228
|
-
"ref": {
|
|
229
|
-
"source": "$.@id",
|
|
230
|
-
"required": true,
|
|
231
|
-
"comment": "✅ OrderItemInput.ref (String! required)"
|
|
232
|
-
},
|
|
233
|
-
"productRef": {
|
|
234
|
-
"source": "$.@sku",
|
|
235
|
-
"required": true,
|
|
236
|
-
"comment": "✅ OrderItemInput.productRef (String! required)"
|
|
237
|
-
},
|
|
238
|
-
"quantity": {
|
|
239
|
-
"source": "$.@qty",
|
|
240
|
-
"resolver": "sdk.parseInt",
|
|
241
|
-
"required": true,
|
|
242
|
-
"comment": "✅ OrderItemInput.quantity (Int! required)"
|
|
243
|
-
},
|
|
244
|
-
"price": {
|
|
245
|
-
"source": "$.@unitPrice",
|
|
246
|
-
"resolver": "sdk.parseFloat",
|
|
247
|
-
"required": true,
|
|
248
|
-
"comment": "✅ OrderItemInput.price (Float! required)"
|
|
249
|
-
},
|
|
250
|
-
"totalPrice": {
|
|
251
|
-
"resolver": "custom.calculateItemTotal",
|
|
252
|
-
"required": true,
|
|
253
|
-
"comment": "✅ OrderItemInput.totalPrice (Float! required) - calculated from qty * price"
|
|
254
|
-
},
|
|
255
|
-
"currency": {
|
|
256
|
-
"source": "order.total@currency",
|
|
257
|
-
"required": true,
|
|
258
|
-
"comment": "✅ OrderItemInput.currency (String! required)"
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
### Implementation
|
|
267
|
-
|
|
268
|
-
```typescript
|
|
269
|
-
import { GraphQLMutationMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
270
|
-
|
|
271
|
-
// Load mapping configuration
|
|
272
|
-
const mappingConfig = JSON.parse(fs.readFileSync('./mappings/sfcc-order-to-fluent.json', 'utf-8'));
|
|
273
|
-
|
|
274
|
-
// Custom resolvers for business logic
|
|
275
|
-
const customResolvers = {
|
|
276
|
-
'custom.mapOrderType': (value: string) => {
|
|
277
|
-
// Map SFCC order types to Fluent OrderType enum
|
|
278
|
-
const typeMap: Record<string, string> = {
|
|
279
|
-
standard: 'STANDARD',
|
|
280
|
-
express: 'HD',
|
|
281
|
-
'store-pickup': 'CC',
|
|
282
|
-
};
|
|
283
|
-
return typeMap[value.toLowerCase()] || 'STANDARD';
|
|
284
|
-
},
|
|
285
|
-
|
|
286
|
-
'custom.calculateItemTotal': (value: any, sourceData: any, config: any, helpers: any) => {
|
|
287
|
-
// Calculate item total from quantity and price
|
|
288
|
-
const qty = helpers.parseIntSafe(sourceData['@qty'], 0);
|
|
289
|
-
const price = helpers.parseFloatSafe(sourceData['@unitPrice'], 0);
|
|
290
|
-
return qty * price;
|
|
291
|
-
},
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
// Create mapper
|
|
295
|
-
const mapper = new GraphQLMutationMapper(mappingConfig, logger, { fluentClient: client });
|
|
296
|
-
|
|
297
|
-
// Parse XML and map to mutation
|
|
298
|
-
const payload = await mapper.mapWithNodes(xmlData, customResolvers);
|
|
299
|
-
|
|
300
|
-
if (payload.success) {
|
|
301
|
-
// ✅ Execute GraphQL mutation (mapper only generates payload, you must execute)
|
|
302
|
-
const result = await client.graphql(payload.data);
|
|
303
|
-
console.log('Order created:', result.data.createOrder.id);
|
|
304
|
-
} else {
|
|
305
|
-
console.error('Mapping failed:', payload.errors);
|
|
306
|
-
}
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
### Key Points
|
|
310
|
-
|
|
311
|
-
- **XML Attributes:** Use `@` prefix for attributes (e.g., `order@id`)
|
|
312
|
-
- **XML Nested Paths:** Use dot notation (e.g., `order.customer@email`)
|
|
313
|
-
- **Array Context:** `$.@id` references current array item
|
|
314
|
-
- **Custom Resolvers:** Business logic for type mapping and calculations
|
|
315
|
-
- **GraphQL Execution:** `GraphQLMutationMapper` generates the mutation payload only - you must call `client.graphql(payload)` to execute
|
|
316
|
-
|
|
317
|
-
**Schema Reference:**
|
|
318
|
-
|
|
319
|
-
- Mutation: `createOrder(input: CreateOrderInput!): Order!`
|
|
320
|
-
- See [`docs/schema/fluent-commerce-schema.json`](../../../04-REFERENCE/schema/fluent-commerce-schema.json) → `inputs.CreateOrderInput`
|
|
321
|
-
|
|
322
|
-
---
|
|
323
|
-
|
|
324
|
-
## Use Case 3: Fluent → XML Generation (SFCC Order Detail)
|
|
325
|
-
|
|
326
|
-
**Scenario:** Generate SFCC-compatible XML from Fluent order data
|
|
327
|
-
|
|
328
|
-
### Source Data
|
|
329
|
-
|
|
330
|
-
**Fluent GraphQL Response:**
|
|
331
|
-
|
|
332
|
-
```json
|
|
333
|
-
{
|
|
334
|
-
"order": {
|
|
335
|
-
"ref": "ORD-2025-001",
|
|
336
|
-
"customer": {
|
|
337
|
-
"id": "232",
|
|
338
|
-
"firstName": "Justin",
|
|
339
|
-
"lastName": "Kerr"
|
|
340
|
-
},
|
|
341
|
-
"items": [
|
|
342
|
-
{
|
|
343
|
-
"id": "ITEM-1",
|
|
344
|
-
"productRef": "SKU-WM-001",
|
|
345
|
-
"color": { "id": "9101", "value": "MULTI-COLOR" },
|
|
346
|
-
"quantity": 2,
|
|
347
|
-
"price": 49.99
|
|
348
|
-
}
|
|
349
|
-
]
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
### Mapping Configuration
|
|
355
|
-
|
|
356
|
-
**File: `config/fluent-to-xml.json`**
|
|
357
|
-
|
|
358
|
-
```json
|
|
359
|
-
{
|
|
360
|
-
"direction": "extract",
|
|
361
|
-
"sourceFormat": "graphql",
|
|
362
|
-
"targetFormat": "xml",
|
|
363
|
-
"comment": "Generate SFCC-compatible XML from Fluent order data",
|
|
364
|
-
|
|
365
|
-
"fields": {
|
|
366
|
-
"@xmlns": {
|
|
367
|
-
"value": "http://api.gsicommerce.com/schema/checkout/1.0",
|
|
368
|
-
"comment": "XML namespace for SFCC"
|
|
369
|
-
},
|
|
370
|
-
"Customer": {
|
|
371
|
-
"fields": {
|
|
372
|
-
"@customerId": {
|
|
373
|
-
"source": "customer.id",
|
|
374
|
-
"comment": "Customer ID as XML attribute"
|
|
375
|
-
},
|
|
376
|
-
"Name": {
|
|
377
|
-
"fields": {
|
|
378
|
-
"FirstName": {
|
|
379
|
-
"source": "customer.firstName",
|
|
380
|
-
"comment": "Simple element with text content"
|
|
381
|
-
},
|
|
382
|
-
"LastName": {
|
|
383
|
-
"source": "customer.lastName"
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
},
|
|
389
|
-
"OrderLines": {
|
|
390
|
-
"fields": {
|
|
391
|
-
"OrderLine": {
|
|
392
|
-
"source": "items",
|
|
393
|
-
"isArray": true,
|
|
394
|
-
"comment": "Array of order line items",
|
|
395
|
-
"fields": {
|
|
396
|
-
"@itemId": {
|
|
397
|
-
"source": "id",
|
|
398
|
-
"comment": "Item ID as XML attribute"
|
|
399
|
-
},
|
|
400
|
-
"ProductRef": {
|
|
401
|
-
"source": "productRef",
|
|
402
|
-
"comment": "Simple element - no attributes"
|
|
403
|
-
},
|
|
404
|
-
"Color": {
|
|
405
|
-
"fields": {
|
|
406
|
-
"@id": {
|
|
407
|
-
"source": "color.id",
|
|
408
|
-
"comment": "Color ID as attribute"
|
|
409
|
-
},
|
|
410
|
-
"#text": {
|
|
411
|
-
"source": "color.value",
|
|
412
|
-
"comment": "⚠️ Use #text for text content when element has attributes"
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
},
|
|
416
|
-
"Quantity": {
|
|
417
|
-
"source": "quantity",
|
|
418
|
-
"resolver": "sdk.toString"
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
### XML Output Patterns
|
|
429
|
-
|
|
430
|
-
| Pattern | JSON Mapping | XML Output |
|
|
431
|
-
| -------------------- | ---------------------------------- | ------------------------------------------ |
|
|
432
|
-
| **Simple Element** | `"ItemId": { "source": "id" }` | `<ItemId>SKU001</ItemId>` |
|
|
433
|
-
| **Attribute Only** | `"@orderId": { "source": "ref" }` | `<Order orderId="12345"/>` |
|
|
434
|
-
| **Attribute + Text** | `"@id": {...}, "#text": {...}` | `<Color id="9101">MULTI-COLOR</Color>` |
|
|
435
|
-
| **Nested Elements** | `"fields": { "FirstName": {...} }` | `<Name><FirstName>John</FirstName></Name>` |
|
|
436
|
-
| **Array** | `"isArray": true, "fields": {...}` | Multiple `<OrderLine>` elements |
|
|
437
|
-
|
|
438
|
-
### Decision Tree - When to use `#text`
|
|
439
|
-
|
|
440
|
-
```
|
|
441
|
-
Does the XML element need attributes (@id, @status, etc.)?
|
|
442
|
-
├─ NO → Just use field name
|
|
443
|
-
│ "ItemId": { "source": "id" }
|
|
444
|
-
│ Result: <ItemId>SKU001</ItemId>
|
|
445
|
-
│
|
|
446
|
-
└─ YES → Does it ALSO have text content?
|
|
447
|
-
├─ NO → Just use @prefix
|
|
448
|
-
│ "@orderId": { "source": "ref" }
|
|
449
|
-
│ Result: <Order orderId="12345"/>
|
|
450
|
-
│
|
|
451
|
-
└─ YES → Use BOTH @prefix AND #text ⚠️
|
|
452
|
-
"@id": { "source": "color.id" }
|
|
453
|
-
"#text": { "source": "color.value" }
|
|
454
|
-
Result: <Color id="9101">MULTI-COLOR</Color>
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
### Common Mistake
|
|
458
|
-
|
|
459
|
-
```json
|
|
460
|
-
// ❌ WRONG - Will create nested <value> element
|
|
461
|
-
"Color": {
|
|
462
|
-
"fields": {
|
|
463
|
-
"@id": { "source": "color.id" },
|
|
464
|
-
"value": { "source": "color.value" }
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
// Output: <Color id="9101"><value>MULTI-COLOR</value></Color>
|
|
468
|
-
|
|
469
|
-
// ✅ CORRECT - Use #text for text content
|
|
470
|
-
"Color": {
|
|
471
|
-
"fields": {
|
|
472
|
-
"@id": { "source": "color.id" },
|
|
473
|
-
"#text": { "source": "color.value" }
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
// Output: <Color id="9101">MULTI-COLOR</Color>
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
### Implementation
|
|
480
|
-
|
|
481
|
-
```typescript
|
|
482
|
-
import { UniversalMapper, XMLBuilder } from '@fluentcommerce/fc-connect-sdk';
|
|
483
|
-
|
|
484
|
-
// Load mapping configuration
|
|
485
|
-
const mappingConfig = JSON.parse(fs.readFileSync('./config/fluent-to-xml.json', 'utf-8'));
|
|
486
|
-
|
|
487
|
-
// Create mapper (no GraphQL execution - just transformation)
|
|
488
|
-
const mapper = new UniversalMapper(mappingConfig);
|
|
489
|
-
|
|
490
|
-
// Map Fluent data to XML structure
|
|
491
|
-
const result = await mapper.map(fluentOrderData);
|
|
492
|
-
|
|
493
|
-
if (result.success) {
|
|
494
|
-
// Generate XML
|
|
495
|
-
const builder = new XMLBuilder({
|
|
496
|
-
prettyPrint: true,
|
|
497
|
-
xmlDeclaration: true,
|
|
498
|
-
});
|
|
499
|
-
const xml = builder.build(result.data, 'OrderDetailResponse');
|
|
500
|
-
|
|
501
|
-
console.log('Generated XML:', xml);
|
|
502
|
-
|
|
503
|
-
// Save or send to external system
|
|
504
|
-
await s3.uploadFile('order-detail.xml', xml);
|
|
505
|
-
}
|
|
506
|
-
```
|
|
507
|
-
|
|
508
|
-
### Generated XML Output
|
|
509
|
-
|
|
510
|
-
```xml
|
|
511
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
512
|
-
<OrderDetailResponse xmlns="http://api.gsicommerce.com/schema/checkout/1.0">
|
|
513
|
-
<Customer customerId="232">
|
|
514
|
-
<Name>
|
|
515
|
-
<FirstName>Justin</FirstName>
|
|
516
|
-
<LastName>Kerr</LastName>
|
|
517
|
-
</Name>
|
|
518
|
-
</Customer>
|
|
519
|
-
<OrderLines>
|
|
520
|
-
<OrderLine itemId="ITEM-1">
|
|
521
|
-
<ProductRef>SKU-WM-001</ProductRef>
|
|
522
|
-
<Color id="9101">MULTI-COLOR</Color>
|
|
523
|
-
<Quantity>2</Quantity>
|
|
524
|
-
</OrderLine>
|
|
525
|
-
</OrderLines>
|
|
526
|
-
</OrderDetailResponse>
|
|
527
|
-
```
|
|
528
|
-
|
|
529
|
-
### Key Points
|
|
530
|
-
|
|
531
|
-
- **No GraphQL Execution:** `UniversalMapper` only transforms data
|
|
532
|
-
- **XML Attributes:** Use `@` prefix for attributes
|
|
533
|
-
- **XML Text Content:** Use `#text` when element has both attributes and text
|
|
534
|
-
- **Arrays:** Use `isArray: true` to map array elements
|
|
535
|
-
- **XMLBuilder:** Handles formatting, namespaces, and declarations
|
|
536
|
-
|
|
537
|
-
📖 **For detailed XML patterns**, see [XML Parser Guide](../../parsers/modules/parsers-04-xml-parser.md)
|
|
538
|
-
|
|
539
|
-
---
|
|
540
|
-
|
|
541
|
-
## Use Case 4: Fluent GraphQL → Parquet Extraction
|
|
542
|
-
|
|
543
|
-
**Scenario:** Export inventory positions to data lake in Parquet format
|
|
544
|
-
|
|
545
|
-
### Source Data
|
|
546
|
-
|
|
547
|
-
**GraphQL Query:**
|
|
548
|
-
|
|
549
|
-
```graphql
|
|
550
|
-
query ExtractInventoryPositions($after: String, $first: Int!) {
|
|
551
|
-
inventoryPositions(after: $after, first: $first) {
|
|
552
|
-
pageInfo {
|
|
553
|
-
hasNextPage
|
|
554
|
-
}
|
|
555
|
-
edges {
|
|
556
|
-
cursor
|
|
557
|
-
node {
|
|
558
|
-
id
|
|
559
|
-
ref
|
|
560
|
-
productRef
|
|
561
|
-
locationRef
|
|
562
|
-
qty
|
|
563
|
-
updatedOn
|
|
564
|
-
product {
|
|
565
|
-
name
|
|
566
|
-
gtin
|
|
567
|
-
catalogue {
|
|
568
|
-
ref
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
location {
|
|
572
|
-
name
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
```
|
|
579
|
-
|
|
580
|
-
**GraphQL Response:**
|
|
581
|
-
|
|
582
|
-
```json
|
|
583
|
-
{
|
|
584
|
-
"inventoryPositions": {
|
|
585
|
-
"edges": [
|
|
586
|
-
{
|
|
587
|
-
"node": {
|
|
588
|
-
"id": "POS-1",
|
|
589
|
-
"ref": "WH-001:PROD-001",
|
|
590
|
-
"productRef": "PROD-001",
|
|
591
|
-
"locationRef": "WH-001",
|
|
592
|
-
"qty": 50,
|
|
593
|
-
"updatedOn": "2024-01-15T10:30:00Z",
|
|
594
|
-
"product": {
|
|
595
|
-
"name": "Widget Master 3000",
|
|
596
|
-
"gtin": "1234567890123",
|
|
597
|
-
"catalogue": {
|
|
598
|
-
"ref": "MAIN"
|
|
599
|
-
}
|
|
600
|
-
},
|
|
601
|
-
"location": {
|
|
602
|
-
"name": "Springfield Distribution Center"
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
]
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
```
|
|
610
|
-
|
|
611
|
-
### Mapping Configuration
|
|
612
|
-
|
|
613
|
-
**File: `config/extraction-mappings.json`**
|
|
614
|
-
|
|
615
|
-
```json
|
|
616
|
-
{
|
|
617
|
-
"direction": "extract",
|
|
618
|
-
"sourceFormat": "graphql",
|
|
619
|
-
"targetFormat": "parquet",
|
|
620
|
-
"comment": "✅ Extract inventory from Fluent query response to Parquet format",
|
|
621
|
-
|
|
622
|
-
"fields": {
|
|
623
|
-
"position_id": {
|
|
624
|
-
"source": "id",
|
|
625
|
-
"comment": "✅ From InventoryPosition.id (ID!)"
|
|
626
|
-
},
|
|
627
|
-
"position_ref": {
|
|
628
|
-
"source": "ref",
|
|
629
|
-
"comment": "✅ From InventoryPosition.ref (String!)"
|
|
630
|
-
},
|
|
631
|
-
"sku": {
|
|
632
|
-
"source": "productRef",
|
|
633
|
-
"comment": "✅ From InventoryPosition.productRef (String!)"
|
|
634
|
-
},
|
|
635
|
-
"warehouse": {
|
|
636
|
-
"source": "locationRef",
|
|
637
|
-
"comment": "✅ From InventoryPosition.locationRef (String!)"
|
|
638
|
-
},
|
|
639
|
-
"available_qty": {
|
|
640
|
-
"source": "qty",
|
|
641
|
-
"comment": "✅ From InventoryPosition.qty (Int!)"
|
|
642
|
-
},
|
|
643
|
-
"product_name": {
|
|
644
|
-
"source": "product.name",
|
|
645
|
-
"comment": "✅ From InventoryPosition.product.name (String) - nested"
|
|
646
|
-
},
|
|
647
|
-
"product_gtin": {
|
|
648
|
-
"source": "product.gtin",
|
|
649
|
-
"comment": "✅ From InventoryPosition.product.gtin (String) - nested"
|
|
650
|
-
},
|
|
651
|
-
"catalogue": {
|
|
652
|
-
"source": "product.catalogue.ref",
|
|
653
|
-
"comment": "✅ From InventoryPosition.product.catalogue.ref (String!) - deeply nested"
|
|
654
|
-
},
|
|
655
|
-
"warehouse_name": {
|
|
656
|
-
"source": "location.name",
|
|
657
|
-
"comment": "✅ From InventoryPosition.location.name (String!) - nested"
|
|
658
|
-
},
|
|
659
|
-
"updated_at": {
|
|
660
|
-
"source": "updatedOn",
|
|
661
|
-
"comment": "✅ From InventoryPosition.updatedOn (DateTime)"
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
```
|
|
666
|
-
|
|
667
|
-
### Implementation
|
|
668
|
-
|
|
669
|
-
```typescript
|
|
670
|
-
import { UniversalMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
671
|
-
import { writeParquetFile } from './utils/parquet-writer';
|
|
672
|
-
|
|
673
|
-
// Load mapping configuration
|
|
674
|
-
const mappingConfig = JSON.parse(fs.readFileSync('./config/extraction-mappings.json', 'utf-8'));
|
|
675
|
-
|
|
676
|
-
// Create mapper
|
|
677
|
-
const mapper = new UniversalMapper(mappingConfig);
|
|
678
|
-
|
|
679
|
-
// Query Fluent Commerce (with pagination)
|
|
680
|
-
const allRecords = [];
|
|
681
|
-
let hasNextPage = true;
|
|
682
|
-
let cursor = null;
|
|
683
|
-
|
|
684
|
-
while (hasNextPage) {
|
|
685
|
-
const result = await client.graphql({
|
|
686
|
-
query: extractionQuery,
|
|
687
|
-
variables: { after: cursor, first: 100 },
|
|
688
|
-
});
|
|
689
|
-
|
|
690
|
-
const edges = result.data.inventoryPositions.edges;
|
|
691
|
-
|
|
692
|
-
// Process each GraphQL node
|
|
693
|
-
for (const edge of edges) {
|
|
694
|
-
const mapResult = await mapper.map(edge.node);
|
|
695
|
-
|
|
696
|
-
if (mapResult.success) {
|
|
697
|
-
allRecords.push(mapResult.data);
|
|
698
|
-
} else {
|
|
699
|
-
console.error('Mapping failed for node:', edge.node.id);
|
|
700
|
-
console.error('Errors:', mapResult.errors);
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// Check pagination
|
|
705
|
-
hasNextPage = result.data.inventoryPositions.pageInfo.hasNextPage;
|
|
706
|
-
cursor = edges[edges.length - 1]?.cursor;
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
// Write to Parquet file
|
|
710
|
-
await writeParquetFile('inventory-positions.parquet', allRecords, {
|
|
711
|
-
schema: {
|
|
712
|
-
position_id: { type: 'UTF8' },
|
|
713
|
-
position_ref: { type: 'UTF8' },
|
|
714
|
-
sku: { type: 'UTF8' },
|
|
715
|
-
warehouse: { type: 'UTF8' },
|
|
716
|
-
available_qty: { type: 'INT32' },
|
|
717
|
-
product_name: { type: 'UTF8' },
|
|
718
|
-
product_gtin: { type: 'UTF8' },
|
|
719
|
-
catalogue: { type: 'UTF8' },
|
|
720
|
-
warehouse_name: { type: 'UTF8' },
|
|
721
|
-
updated_at: { type: 'TIMESTAMP_MILLIS' },
|
|
722
|
-
},
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
console.log(`✅ Extracted ${allRecords.length} inventory positions to Parquet`);
|
|
726
|
-
```
|
|
727
|
-
|
|
728
|
-
### Parquet Output
|
|
729
|
-
|
|
730
|
-
The Parquet file will contain columnar data optimized for analytics:
|
|
731
|
-
|
|
732
|
-
| position_id | sku | warehouse | available_qty | product_name | warehouse_name |
|
|
733
|
-
| ----------- | -------- | --------- | ------------- | ------------------ | ------------------------------- |
|
|
734
|
-
| POS-1 | PROD-001 | WH-001 | 50 | Widget Master 3000 | Springfield Distribution Center |
|
|
735
|
-
| POS-2 | PROD-002 | WH-001 | 150 | Keyboard Elite | Springfield Distribution Center |
|
|
736
|
-
|
|
737
|
-
### Key Points
|
|
738
|
-
|
|
739
|
-
- **Nested Field Access:** Use dot notation for nested GraphQL fields
|
|
740
|
-
- **GraphQL Pagination:** Handle `edges` and `nodes` structure
|
|
741
|
-
- **No GraphQL Execution:** Mapper only transforms pre-fetched data
|
|
742
|
-
- **Parquet Schema:** Define column types for efficient storage
|
|
743
|
-
- **Data Lake Ready:** Columnar format for analytics and BI tools
|
|
744
|
-
|
|
745
|
-
**Schema Reference:**
|
|
746
|
-
|
|
747
|
-
- Query: `inventoryPositions(first: Int, after: String): InventoryPositionConnection!`
|
|
748
|
-
- See [`docs/schema/fluent-commerce-schema.json`](../../../04-REFERENCE/schema/fluent-commerce-schema.json) → `types.InventoryPosition`
|
|
749
|
-
|
|
750
|
-
---
|
|
751
|
-
|
|
752
|
-
## Comparison Matrix
|
|
753
|
-
|
|
754
|
-
| Use Case | Direction | Source Format | Target Format | GraphQL Execution | Component | Platform |
|
|
755
|
-
| -------------------- | --------- | ------------- | ------------- | ----------------- | ---------------------------------- | -------- |
|
|
756
|
-
| **CSV → Fluent** | `ingest` | CSV | N/A | ❌ No (generates payload) | `UniversalMapper` + Batch API | Standalone |
|
|
757
|
-
| **XML → Fluent** | `ingest` | XML | N/A | ❌ No (generates payload) | `GraphQLMutationMapper` | Standalone |
|
|
758
|
-
| **Fluent → XML** | `extract` | GraphQL | XML | ❌ No | `UniversalMapper` + `XMLBuilder` | Standalone |
|
|
759
|
-
| **Fluent → Parquet** | `extract` | GraphQL | Parquet | ❌ No | `UniversalMapper` + Parquet writer | Standalone |
|
|
760
|
-
|
|
761
|
-
**Note:** For `ingest` direction, mappers generate GraphQL payloads but do NOT execute them. You must call `client.graphql(payload)` separately.
|
|
762
|
-
|
|
763
|
-
---
|
|
764
|
-
|
|
765
|
-
## Key Takeaways
|
|
766
|
-
|
|
767
|
-
1. **Same Pattern Everywhere:** All use cases use the same `fields` mapping structure
|
|
768
|
-
2. **Direction Matters:** `ingest` executes mutations, `extract` only transforms
|
|
769
|
-
3. **Resolvers Are Universal:** SDK resolvers work across all formats
|
|
770
|
-
4. **Custom Logic:** Use custom resolvers for business-specific transformations
|
|
771
|
-
5. **Validation First:** Always validate against schema before deployment
|
|
772
|
-
|
|
773
|
-
---
|
|
774
|
-
|
|
775
|
-
## Practice Exercise
|
|
776
|
-
|
|
777
|
-
**Task:** Create a mapping for extracting Fluent orders to JSON for a data warehouse.
|
|
778
|
-
|
|
779
|
-
**Requirements:**
|
|
780
|
-
|
|
781
|
-
1. Query orders with customer and items
|
|
782
|
-
2. Flatten nested customer data
|
|
783
|
-
3. Map items array
|
|
784
|
-
4. Include calculated fields (item totals)
|
|
785
|
-
5. Format dates as ISO8601
|
|
786
|
-
|
|
787
|
-
<details>
|
|
788
|
-
<summary>Click to see solution</summary>
|
|
789
|
-
|
|
790
|
-
**Mapping Configuration:**
|
|
791
|
-
|
|
792
|
-
```json
|
|
793
|
-
{
|
|
794
|
-
"direction": "extract",
|
|
795
|
-
"sourceFormat": "graphql",
|
|
796
|
-
"targetFormat": "json",
|
|
797
|
-
|
|
798
|
-
"fields": {
|
|
799
|
-
"order_id": {
|
|
800
|
-
"source": "id"
|
|
801
|
-
},
|
|
802
|
-
"order_ref": {
|
|
803
|
-
"source": "ref"
|
|
804
|
-
},
|
|
805
|
-
"customer_id": {
|
|
806
|
-
"source": "customer.id"
|
|
807
|
-
},
|
|
808
|
-
"customer_email": {
|
|
809
|
-
"source": "customer.email",
|
|
810
|
-
"resolver": "sdk.lowercase"
|
|
811
|
-
},
|
|
812
|
-
"customer_name": {
|
|
813
|
-
"resolver": "custom.fullName"
|
|
814
|
-
},
|
|
815
|
-
"total_price": {
|
|
816
|
-
"source": "totalPrice",
|
|
817
|
-
"resolver": "sdk.parseFloat"
|
|
818
|
-
},
|
|
819
|
-
"created_at": {
|
|
820
|
-
"source": "createdOn",
|
|
821
|
-
"resolver": "sdk.formatDate"
|
|
822
|
-
},
|
|
823
|
-
"items": {
|
|
824
|
-
"source": "items",
|
|
825
|
-
"isArray": true,
|
|
826
|
-
"fields": {
|
|
827
|
-
"item_ref": {
|
|
828
|
-
"source": "ref"
|
|
829
|
-
},
|
|
830
|
-
"product_ref": {
|
|
831
|
-
"source": "productRef"
|
|
832
|
-
},
|
|
833
|
-
"quantity": {
|
|
834
|
-
"source": "quantity",
|
|
835
|
-
"resolver": "sdk.parseInt"
|
|
836
|
-
},
|
|
837
|
-
"unit_price": {
|
|
838
|
-
"source": "price",
|
|
839
|
-
"resolver": "sdk.parseFloat"
|
|
840
|
-
},
|
|
841
|
-
"total_price": {
|
|
842
|
-
"resolver": "custom.calculateItemTotal"
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
```
|
|
849
|
-
|
|
850
|
-
**Custom Resolvers:**
|
|
851
|
-
|
|
852
|
-
```typescript
|
|
853
|
-
const customResolvers = {
|
|
854
|
-
'custom.fullName': (value: any, sourceData: any, config: any, helpers: any) => {
|
|
855
|
-
const firstName = helpers.get(sourceData, 'customer.firstName', '');
|
|
856
|
-
const lastName = helpers.get(sourceData, 'customer.lastName', '');
|
|
857
|
-
return `${firstName} ${lastName}`.trim();
|
|
858
|
-
},
|
|
859
|
-
|
|
860
|
-
'custom.calculateItemTotal': (value: any, sourceData: any, config: any, helpers: any) => {
|
|
861
|
-
const qty = helpers.parseIntSafe(sourceData.quantity, 0);
|
|
862
|
-
const price = helpers.parseFloatSafe(sourceData.price, 0);
|
|
863
|
-
return qty * price;
|
|
864
|
-
},
|
|
865
|
-
};
|
|
866
|
-
```
|
|
867
|
-
|
|
868
|
-
</details>
|
|
869
|
-
|
|
870
|
-
---
|
|
871
|
-
|
|
872
|
-
## Next Steps
|
|
873
|
-
|
|
874
|
-
Now that you've seen real-world use cases, you're ready for advanced patterns:
|
|
875
|
-
|
|
876
|
-
→ Continue to [Module 5: Advanced Patterns](./mapping-05-advanced-patterns.md)
|
|
877
|
-
|
|
878
|
-
**Alternative paths:**
|
|
879
|
-
|
|
880
|
-
- Review [Helpers & Resolvers](./mapping-06-helpers-resolvers.md) for complete helper documentation
|
|
881
|
-
- Check [API Reference](../api-reference/readme.md) for TypeScript usage
|
|
882
|
-
|
|
883
|
-
---
|
|
884
|
-
|
|
885
|
-
[← Back to Schema Validation](./mapping-03-schema-validation.md) | [Next: Advanced Patterns →](./mapping-05-advanced-patterns.md)
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1
|
+
# Module 4: Use Cases
|
|
2
|
+
|
|
3
|
+
**Real-world transformation scenarios**
|
|
4
|
+
|
|
5
|
+
**Level:** Intermediate
|
|
6
|
+
**Time:** 45 minutes
|
|
7
|
+
**Prerequisites:** [Module 3: Schema Validation](./mapping-03-schema-validation.md)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Learning Objectives
|
|
12
|
+
|
|
13
|
+
After completing this module, you will:
|
|
14
|
+
|
|
15
|
+
- ✅ Implement CSV ingestion to Fluent Batch API
|
|
16
|
+
- ✅ Transform XML to GraphQL mutations for order creation
|
|
17
|
+
- ✅ Generate XML from Fluent data for external APIs
|
|
18
|
+
- ✅ Extract GraphQL data to Parquet format
|
|
19
|
+
- ✅ Understand real-world connector patterns
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Use Case 1: CSV Ingestion → Fluent Batch API
|
|
24
|
+
|
|
25
|
+
**Scenario:** Import inventory positions from CSV files to Fluent Commerce
|
|
26
|
+
|
|
27
|
+
### Source Data
|
|
28
|
+
|
|
29
|
+
**CSV Format:**
|
|
30
|
+
|
|
31
|
+
```csv
|
|
32
|
+
sku,location,quantity,status
|
|
33
|
+
PROD-001,WAREHOUSE-A,100,active
|
|
34
|
+
PROD-002,WAREHOUSE-A,50,reserved
|
|
35
|
+
PROD-003,WAREHOUSE-B,200,active
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Mapping Configuration
|
|
39
|
+
|
|
40
|
+
**File: `config/inventory-ingestion.json`**
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"direction": "ingest",
|
|
45
|
+
"sourceFormat": "csv",
|
|
46
|
+
"mutation": "upsertInventoryPosition",
|
|
47
|
+
"comment": "✅ Validated against schema: docs/schema/fluent-commerce-schema.json → Mutation.upsertInventoryPosition",
|
|
48
|
+
|
|
49
|
+
"fields": {
|
|
50
|
+
"ref": {
|
|
51
|
+
"source": "sku",
|
|
52
|
+
"required": true,
|
|
53
|
+
"comment": "✅ UpsertInventoryPositionInput.ref (String! required) - unique position identifier"
|
|
54
|
+
},
|
|
55
|
+
"productRef": {
|
|
56
|
+
"source": "sku",
|
|
57
|
+
"required": true,
|
|
58
|
+
"comment": "✅ UpsertInventoryPositionInput.productRef (String! required)"
|
|
59
|
+
},
|
|
60
|
+
"locationRef": {
|
|
61
|
+
"source": "location",
|
|
62
|
+
"required": true,
|
|
63
|
+
"comment": "✅ UpsertInventoryPositionInput.locationRef (String! required)"
|
|
64
|
+
},
|
|
65
|
+
"qty": {
|
|
66
|
+
"source": "quantity",
|
|
67
|
+
"resolver": "sdk.parseInt",
|
|
68
|
+
"required": true,
|
|
69
|
+
"comment": "✅ UpsertInventoryPositionInput.qty (Int! required)"
|
|
70
|
+
},
|
|
71
|
+
"status": {
|
|
72
|
+
"source": "status",
|
|
73
|
+
"resolver": "sdk.uppercase",
|
|
74
|
+
"defaultValue": "AVAILABLE",
|
|
75
|
+
"comment": "✅ UpsertInventoryPositionInput.status (String) - e.g., AVAILABLE, RESERVED"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Implementation
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { UniversalMapper, CSVParserService, createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
85
|
+
import * as fs from 'fs';
|
|
86
|
+
|
|
87
|
+
// Load mapping configuration
|
|
88
|
+
const mappingConfig = JSON.parse(fs.readFileSync('./config/inventory-ingestion.json', 'utf-8'));
|
|
89
|
+
|
|
90
|
+
// Load and parse CSV
|
|
91
|
+
const csvContent = fs.readFileSync('./data/inventory.csv', 'utf-8');
|
|
92
|
+
const parser = new CSVParserService();
|
|
93
|
+
const records = await parser.parse(csvContent);
|
|
94
|
+
|
|
95
|
+
// Create mapper
|
|
96
|
+
const mapper = new UniversalMapper(mappingConfig);
|
|
97
|
+
|
|
98
|
+
// Process each CSV row
|
|
99
|
+
const batchEntities = [];
|
|
100
|
+
for (const row of records) {
|
|
101
|
+
const result = await mapper.map(row);
|
|
102
|
+
|
|
103
|
+
if (result.success) {
|
|
104
|
+
batchEntities.push(result.data);
|
|
105
|
+
} else {
|
|
106
|
+
console.error('Mapping failed for row:', row);
|
|
107
|
+
console.error('Errors:', result.errors);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Create Fluent client
|
|
112
|
+
const client = await createClient({
|
|
113
|
+
config: {
|
|
114
|
+
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
115
|
+
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
116
|
+
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
117
|
+
username: process.env.FLUENT_USERNAME!,
|
|
118
|
+
password: process.env.FLUENT_PASSWORD!,
|
|
119
|
+
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Create batch job
|
|
124
|
+
const job = await client.createJob({
|
|
125
|
+
name: 'inventory-update',
|
|
126
|
+
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Send batch to Fluent Commerce
|
|
130
|
+
await client.sendBatch(job.id, {
|
|
131
|
+
action: 'UPSERT',
|
|
132
|
+
entityType: 'INVENTORY',
|
|
133
|
+
source: 'CSV_IMPORT',
|
|
134
|
+
event: 'INVENTORY_UPDATE',
|
|
135
|
+
entities: batchEntities,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
console.log(`✅ Successfully processed ${batchEntities.length} inventory positions`);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Key Points
|
|
142
|
+
|
|
143
|
+
- **Batch Processing:** Efficient for high-volume imports (1000s of records)
|
|
144
|
+
- **Validation:** `required: true` catches missing data before API calls
|
|
145
|
+
- **Resolvers:** `sdk.parseInt` ensures numeric types, `sdk.uppercase` normalizes status
|
|
146
|
+
- **Error Handling:** Individual row failures don't stop the entire batch
|
|
147
|
+
|
|
148
|
+
**Schema Reference:**
|
|
149
|
+
|
|
150
|
+
- Mutation: `upsertInventoryPosition(input: UpsertInventoryPositionInput!): InventoryPosition`
|
|
151
|
+
- See [`docs/schema/fluent-commerce-schema.json`](../../../04-REFERENCE/schema/fluent-commerce-schema.json) → `inputs.UpsertInventoryPositionInput`
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Use Case 2: XML → GraphQL Mutation
|
|
156
|
+
|
|
157
|
+
**Scenario:** Transform SFCC order XML to Fluent order mutation
|
|
158
|
+
|
|
159
|
+
### Source Data
|
|
160
|
+
|
|
161
|
+
**SFCC Order XML:**
|
|
162
|
+
|
|
163
|
+
```xml
|
|
164
|
+
<order id="ORD-123" type="standard">
|
|
165
|
+
<customer email="john@example.com" />
|
|
166
|
+
<total currency="USD">99.99</total>
|
|
167
|
+
<items>
|
|
168
|
+
<item id="ITEM-1" sku="PROD-001" qty="2" unitPrice="49.99" />
|
|
169
|
+
</items>
|
|
170
|
+
</order>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Mapping Configuration
|
|
174
|
+
|
|
175
|
+
**File: `mappings/sfcc-order-to-fluent.json`**
|
|
176
|
+
|
|
177
|
+
```json
|
|
178
|
+
{
|
|
179
|
+
"direction": "ingest",
|
|
180
|
+
"sourceFormat": "xml",
|
|
181
|
+
"mutation": "createOrder",
|
|
182
|
+
"comment": "✅ Validated against schema: docs/schema/fluent-commerce-schema.json → Mutation.createOrder",
|
|
183
|
+
|
|
184
|
+
"fields": {
|
|
185
|
+
"ref": {
|
|
186
|
+
"source": "order@id",
|
|
187
|
+
"required": true,
|
|
188
|
+
"comment": "✅ CreateOrderInput.ref (String! required)"
|
|
189
|
+
},
|
|
190
|
+
"type": {
|
|
191
|
+
"source": "order@type",
|
|
192
|
+
"resolver": "custom.mapOrderType",
|
|
193
|
+
"comment": "✅ CreateOrderInput.type (OrderType! enum required) - maps 'standard' → 'STANDARD'"
|
|
194
|
+
},
|
|
195
|
+
"retailer": {
|
|
196
|
+
"fields": {
|
|
197
|
+
"id": {
|
|
198
|
+
"value": "1",
|
|
199
|
+
"comment": "✅ CreateOrderInput.retailer (RetailerInput! required)"
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
"customer": {
|
|
204
|
+
"fields": {
|
|
205
|
+
"email": {
|
|
206
|
+
"source": "order.customer@email",
|
|
207
|
+
"resolver": "sdk.lowercase",
|
|
208
|
+
"comment": "✅ CreateOrderInput.customer.email (String!)"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
"totalPrice": {
|
|
213
|
+
"source": "order.total",
|
|
214
|
+
"resolver": "sdk.parseFloat",
|
|
215
|
+
"required": true,
|
|
216
|
+
"comment": "✅ CreateOrderInput.totalPrice (Float! required)"
|
|
217
|
+
},
|
|
218
|
+
"currency": {
|
|
219
|
+
"source": "order.total@currency",
|
|
220
|
+
"defaultValue": "USD",
|
|
221
|
+
"comment": "✅ CreateOrderInput.currency (String! required)"
|
|
222
|
+
},
|
|
223
|
+
"items": {
|
|
224
|
+
"source": "order.items.item",
|
|
225
|
+
"isArray": true,
|
|
226
|
+
"comment": "✅ CreateOrderInput.items ([OrderItemInput]! required)",
|
|
227
|
+
"fields": {
|
|
228
|
+
"ref": {
|
|
229
|
+
"source": "$.@id",
|
|
230
|
+
"required": true,
|
|
231
|
+
"comment": "✅ OrderItemInput.ref (String! required)"
|
|
232
|
+
},
|
|
233
|
+
"productRef": {
|
|
234
|
+
"source": "$.@sku",
|
|
235
|
+
"required": true,
|
|
236
|
+
"comment": "✅ OrderItemInput.productRef (String! required)"
|
|
237
|
+
},
|
|
238
|
+
"quantity": {
|
|
239
|
+
"source": "$.@qty",
|
|
240
|
+
"resolver": "sdk.parseInt",
|
|
241
|
+
"required": true,
|
|
242
|
+
"comment": "✅ OrderItemInput.quantity (Int! required)"
|
|
243
|
+
},
|
|
244
|
+
"price": {
|
|
245
|
+
"source": "$.@unitPrice",
|
|
246
|
+
"resolver": "sdk.parseFloat",
|
|
247
|
+
"required": true,
|
|
248
|
+
"comment": "✅ OrderItemInput.price (Float! required)"
|
|
249
|
+
},
|
|
250
|
+
"totalPrice": {
|
|
251
|
+
"resolver": "custom.calculateItemTotal",
|
|
252
|
+
"required": true,
|
|
253
|
+
"comment": "✅ OrderItemInput.totalPrice (Float! required) - calculated from qty * price"
|
|
254
|
+
},
|
|
255
|
+
"currency": {
|
|
256
|
+
"source": "order.total@currency",
|
|
257
|
+
"required": true,
|
|
258
|
+
"comment": "✅ OrderItemInput.currency (String! required)"
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Implementation
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
import { GraphQLMutationMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
270
|
+
|
|
271
|
+
// Load mapping configuration
|
|
272
|
+
const mappingConfig = JSON.parse(fs.readFileSync('./mappings/sfcc-order-to-fluent.json', 'utf-8'));
|
|
273
|
+
|
|
274
|
+
// Custom resolvers for business logic
|
|
275
|
+
const customResolvers = {
|
|
276
|
+
'custom.mapOrderType': (value: string) => {
|
|
277
|
+
// Map SFCC order types to Fluent OrderType enum
|
|
278
|
+
const typeMap: Record<string, string> = {
|
|
279
|
+
standard: 'STANDARD',
|
|
280
|
+
express: 'HD',
|
|
281
|
+
'store-pickup': 'CC',
|
|
282
|
+
};
|
|
283
|
+
return typeMap[value.toLowerCase()] || 'STANDARD';
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
'custom.calculateItemTotal': (value: any, sourceData: any, config: any, helpers: any) => {
|
|
287
|
+
// Calculate item total from quantity and price
|
|
288
|
+
const qty = helpers.parseIntSafe(sourceData['@qty'], 0);
|
|
289
|
+
const price = helpers.parseFloatSafe(sourceData['@unitPrice'], 0);
|
|
290
|
+
return qty * price;
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
// Create mapper
|
|
295
|
+
const mapper = new GraphQLMutationMapper(mappingConfig, logger, { fluentClient: client });
|
|
296
|
+
|
|
297
|
+
// Parse XML and map to mutation
|
|
298
|
+
const payload = await mapper.mapWithNodes(xmlData, customResolvers);
|
|
299
|
+
|
|
300
|
+
if (payload.success) {
|
|
301
|
+
// ✅ Execute GraphQL mutation (mapper only generates payload, you must execute)
|
|
302
|
+
const result = await client.graphql(payload.data);
|
|
303
|
+
console.log('Order created:', result.data.createOrder.id);
|
|
304
|
+
} else {
|
|
305
|
+
console.error('Mapping failed:', payload.errors);
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Key Points
|
|
310
|
+
|
|
311
|
+
- **XML Attributes:** Use `@` prefix for attributes (e.g., `order@id`)
|
|
312
|
+
- **XML Nested Paths:** Use dot notation (e.g., `order.customer@email`)
|
|
313
|
+
- **Array Context:** `$.@id` references current array item
|
|
314
|
+
- **Custom Resolvers:** Business logic for type mapping and calculations
|
|
315
|
+
- **GraphQL Execution:** `GraphQLMutationMapper` generates the mutation payload only - you must call `client.graphql(payload)` to execute
|
|
316
|
+
|
|
317
|
+
**Schema Reference:**
|
|
318
|
+
|
|
319
|
+
- Mutation: `createOrder(input: CreateOrderInput!): Order!`
|
|
320
|
+
- See [`docs/schema/fluent-commerce-schema.json`](../../../04-REFERENCE/schema/fluent-commerce-schema.json) → `inputs.CreateOrderInput`
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Use Case 3: Fluent → XML Generation (SFCC Order Detail)
|
|
325
|
+
|
|
326
|
+
**Scenario:** Generate SFCC-compatible XML from Fluent order data
|
|
327
|
+
|
|
328
|
+
### Source Data
|
|
329
|
+
|
|
330
|
+
**Fluent GraphQL Response:**
|
|
331
|
+
|
|
332
|
+
```json
|
|
333
|
+
{
|
|
334
|
+
"order": {
|
|
335
|
+
"ref": "ORD-2025-001",
|
|
336
|
+
"customer": {
|
|
337
|
+
"id": "232",
|
|
338
|
+
"firstName": "Justin",
|
|
339
|
+
"lastName": "Kerr"
|
|
340
|
+
},
|
|
341
|
+
"items": [
|
|
342
|
+
{
|
|
343
|
+
"id": "ITEM-1",
|
|
344
|
+
"productRef": "SKU-WM-001",
|
|
345
|
+
"color": { "id": "9101", "value": "MULTI-COLOR" },
|
|
346
|
+
"quantity": 2,
|
|
347
|
+
"price": 49.99
|
|
348
|
+
}
|
|
349
|
+
]
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Mapping Configuration
|
|
355
|
+
|
|
356
|
+
**File: `config/fluent-to-xml.json`**
|
|
357
|
+
|
|
358
|
+
```json
|
|
359
|
+
{
|
|
360
|
+
"direction": "extract",
|
|
361
|
+
"sourceFormat": "graphql",
|
|
362
|
+
"targetFormat": "xml",
|
|
363
|
+
"comment": "Generate SFCC-compatible XML from Fluent order data",
|
|
364
|
+
|
|
365
|
+
"fields": {
|
|
366
|
+
"@xmlns": {
|
|
367
|
+
"value": "http://api.gsicommerce.com/schema/checkout/1.0",
|
|
368
|
+
"comment": "XML namespace for SFCC"
|
|
369
|
+
},
|
|
370
|
+
"Customer": {
|
|
371
|
+
"fields": {
|
|
372
|
+
"@customerId": {
|
|
373
|
+
"source": "customer.id",
|
|
374
|
+
"comment": "Customer ID as XML attribute"
|
|
375
|
+
},
|
|
376
|
+
"Name": {
|
|
377
|
+
"fields": {
|
|
378
|
+
"FirstName": {
|
|
379
|
+
"source": "customer.firstName",
|
|
380
|
+
"comment": "Simple element with text content"
|
|
381
|
+
},
|
|
382
|
+
"LastName": {
|
|
383
|
+
"source": "customer.lastName"
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
"OrderLines": {
|
|
390
|
+
"fields": {
|
|
391
|
+
"OrderLine": {
|
|
392
|
+
"source": "items",
|
|
393
|
+
"isArray": true,
|
|
394
|
+
"comment": "Array of order line items",
|
|
395
|
+
"fields": {
|
|
396
|
+
"@itemId": {
|
|
397
|
+
"source": "id",
|
|
398
|
+
"comment": "Item ID as XML attribute"
|
|
399
|
+
},
|
|
400
|
+
"ProductRef": {
|
|
401
|
+
"source": "productRef",
|
|
402
|
+
"comment": "Simple element - no attributes"
|
|
403
|
+
},
|
|
404
|
+
"Color": {
|
|
405
|
+
"fields": {
|
|
406
|
+
"@id": {
|
|
407
|
+
"source": "color.id",
|
|
408
|
+
"comment": "Color ID as attribute"
|
|
409
|
+
},
|
|
410
|
+
"#text": {
|
|
411
|
+
"source": "color.value",
|
|
412
|
+
"comment": "⚠️ Use #text for text content when element has attributes"
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
"Quantity": {
|
|
417
|
+
"source": "quantity",
|
|
418
|
+
"resolver": "sdk.toString"
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### XML Output Patterns
|
|
429
|
+
|
|
430
|
+
| Pattern | JSON Mapping | XML Output |
|
|
431
|
+
| -------------------- | ---------------------------------- | ------------------------------------------ |
|
|
432
|
+
| **Simple Element** | `"ItemId": { "source": "id" }` | `<ItemId>SKU001</ItemId>` |
|
|
433
|
+
| **Attribute Only** | `"@orderId": { "source": "ref" }` | `<Order orderId="12345"/>` |
|
|
434
|
+
| **Attribute + Text** | `"@id": {...}, "#text": {...}` | `<Color id="9101">MULTI-COLOR</Color>` |
|
|
435
|
+
| **Nested Elements** | `"fields": { "FirstName": {...} }` | `<Name><FirstName>John</FirstName></Name>` |
|
|
436
|
+
| **Array** | `"isArray": true, "fields": {...}` | Multiple `<OrderLine>` elements |
|
|
437
|
+
|
|
438
|
+
### Decision Tree - When to use `#text`
|
|
439
|
+
|
|
440
|
+
```
|
|
441
|
+
Does the XML element need attributes (@id, @status, etc.)?
|
|
442
|
+
├─ NO → Just use field name
|
|
443
|
+
│ "ItemId": { "source": "id" }
|
|
444
|
+
│ Result: <ItemId>SKU001</ItemId>
|
|
445
|
+
│
|
|
446
|
+
└─ YES → Does it ALSO have text content?
|
|
447
|
+
├─ NO → Just use @prefix
|
|
448
|
+
│ "@orderId": { "source": "ref" }
|
|
449
|
+
│ Result: <Order orderId="12345"/>
|
|
450
|
+
│
|
|
451
|
+
└─ YES → Use BOTH @prefix AND #text ⚠️
|
|
452
|
+
"@id": { "source": "color.id" }
|
|
453
|
+
"#text": { "source": "color.value" }
|
|
454
|
+
Result: <Color id="9101">MULTI-COLOR</Color>
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Common Mistake
|
|
458
|
+
|
|
459
|
+
```json
|
|
460
|
+
// ❌ WRONG - Will create nested <value> element
|
|
461
|
+
"Color": {
|
|
462
|
+
"fields": {
|
|
463
|
+
"@id": { "source": "color.id" },
|
|
464
|
+
"value": { "source": "color.value" }
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
// Output: <Color id="9101"><value>MULTI-COLOR</value></Color>
|
|
468
|
+
|
|
469
|
+
// ✅ CORRECT - Use #text for text content
|
|
470
|
+
"Color": {
|
|
471
|
+
"fields": {
|
|
472
|
+
"@id": { "source": "color.id" },
|
|
473
|
+
"#text": { "source": "color.value" }
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
// Output: <Color id="9101">MULTI-COLOR</Color>
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### Implementation
|
|
480
|
+
|
|
481
|
+
```typescript
|
|
482
|
+
import { UniversalMapper, XMLBuilder } from '@fluentcommerce/fc-connect-sdk';
|
|
483
|
+
|
|
484
|
+
// Load mapping configuration
|
|
485
|
+
const mappingConfig = JSON.parse(fs.readFileSync('./config/fluent-to-xml.json', 'utf-8'));
|
|
486
|
+
|
|
487
|
+
// Create mapper (no GraphQL execution - just transformation)
|
|
488
|
+
const mapper = new UniversalMapper(mappingConfig);
|
|
489
|
+
|
|
490
|
+
// Map Fluent data to XML structure
|
|
491
|
+
const result = await mapper.map(fluentOrderData);
|
|
492
|
+
|
|
493
|
+
if (result.success) {
|
|
494
|
+
// Generate XML
|
|
495
|
+
const builder = new XMLBuilder({
|
|
496
|
+
prettyPrint: true,
|
|
497
|
+
xmlDeclaration: true,
|
|
498
|
+
});
|
|
499
|
+
const xml = builder.build(result.data, 'OrderDetailResponse');
|
|
500
|
+
|
|
501
|
+
console.log('Generated XML:', xml);
|
|
502
|
+
|
|
503
|
+
// Save or send to external system
|
|
504
|
+
await s3.uploadFile('order-detail.xml', xml);
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### Generated XML Output
|
|
509
|
+
|
|
510
|
+
```xml
|
|
511
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
512
|
+
<OrderDetailResponse xmlns="http://api.gsicommerce.com/schema/checkout/1.0">
|
|
513
|
+
<Customer customerId="232">
|
|
514
|
+
<Name>
|
|
515
|
+
<FirstName>Justin</FirstName>
|
|
516
|
+
<LastName>Kerr</LastName>
|
|
517
|
+
</Name>
|
|
518
|
+
</Customer>
|
|
519
|
+
<OrderLines>
|
|
520
|
+
<OrderLine itemId="ITEM-1">
|
|
521
|
+
<ProductRef>SKU-WM-001</ProductRef>
|
|
522
|
+
<Color id="9101">MULTI-COLOR</Color>
|
|
523
|
+
<Quantity>2</Quantity>
|
|
524
|
+
</OrderLine>
|
|
525
|
+
</OrderLines>
|
|
526
|
+
</OrderDetailResponse>
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
### Key Points
|
|
530
|
+
|
|
531
|
+
- **No GraphQL Execution:** `UniversalMapper` only transforms data
|
|
532
|
+
- **XML Attributes:** Use `@` prefix for attributes
|
|
533
|
+
- **XML Text Content:** Use `#text` when element has both attributes and text
|
|
534
|
+
- **Arrays:** Use `isArray: true` to map array elements
|
|
535
|
+
- **XMLBuilder:** Handles formatting, namespaces, and declarations
|
|
536
|
+
|
|
537
|
+
📖 **For detailed XML patterns**, see [XML Parser Guide](../../parsers/modules/parsers-04-xml-parser.md)
|
|
538
|
+
|
|
539
|
+
---
|
|
540
|
+
|
|
541
|
+
## Use Case 4: Fluent GraphQL → Parquet Extraction
|
|
542
|
+
|
|
543
|
+
**Scenario:** Export inventory positions to data lake in Parquet format
|
|
544
|
+
|
|
545
|
+
### Source Data
|
|
546
|
+
|
|
547
|
+
**GraphQL Query:**
|
|
548
|
+
|
|
549
|
+
```graphql
|
|
550
|
+
query ExtractInventoryPositions($after: String, $first: Int!) {
|
|
551
|
+
inventoryPositions(after: $after, first: $first) {
|
|
552
|
+
pageInfo {
|
|
553
|
+
hasNextPage
|
|
554
|
+
}
|
|
555
|
+
edges {
|
|
556
|
+
cursor
|
|
557
|
+
node {
|
|
558
|
+
id
|
|
559
|
+
ref
|
|
560
|
+
productRef
|
|
561
|
+
locationRef
|
|
562
|
+
qty
|
|
563
|
+
updatedOn
|
|
564
|
+
product {
|
|
565
|
+
name
|
|
566
|
+
gtin
|
|
567
|
+
catalogue {
|
|
568
|
+
ref
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
location {
|
|
572
|
+
name
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
**GraphQL Response:**
|
|
581
|
+
|
|
582
|
+
```json
|
|
583
|
+
{
|
|
584
|
+
"inventoryPositions": {
|
|
585
|
+
"edges": [
|
|
586
|
+
{
|
|
587
|
+
"node": {
|
|
588
|
+
"id": "POS-1",
|
|
589
|
+
"ref": "WH-001:PROD-001",
|
|
590
|
+
"productRef": "PROD-001",
|
|
591
|
+
"locationRef": "WH-001",
|
|
592
|
+
"qty": 50,
|
|
593
|
+
"updatedOn": "2024-01-15T10:30:00Z",
|
|
594
|
+
"product": {
|
|
595
|
+
"name": "Widget Master 3000",
|
|
596
|
+
"gtin": "1234567890123",
|
|
597
|
+
"catalogue": {
|
|
598
|
+
"ref": "MAIN"
|
|
599
|
+
}
|
|
600
|
+
},
|
|
601
|
+
"location": {
|
|
602
|
+
"name": "Springfield Distribution Center"
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
]
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
### Mapping Configuration
|
|
612
|
+
|
|
613
|
+
**File: `config/extraction-mappings.json`**
|
|
614
|
+
|
|
615
|
+
```json
|
|
616
|
+
{
|
|
617
|
+
"direction": "extract",
|
|
618
|
+
"sourceFormat": "graphql",
|
|
619
|
+
"targetFormat": "parquet",
|
|
620
|
+
"comment": "✅ Extract inventory from Fluent query response to Parquet format",
|
|
621
|
+
|
|
622
|
+
"fields": {
|
|
623
|
+
"position_id": {
|
|
624
|
+
"source": "id",
|
|
625
|
+
"comment": "✅ From InventoryPosition.id (ID!)"
|
|
626
|
+
},
|
|
627
|
+
"position_ref": {
|
|
628
|
+
"source": "ref",
|
|
629
|
+
"comment": "✅ From InventoryPosition.ref (String!)"
|
|
630
|
+
},
|
|
631
|
+
"sku": {
|
|
632
|
+
"source": "productRef",
|
|
633
|
+
"comment": "✅ From InventoryPosition.productRef (String!)"
|
|
634
|
+
},
|
|
635
|
+
"warehouse": {
|
|
636
|
+
"source": "locationRef",
|
|
637
|
+
"comment": "✅ From InventoryPosition.locationRef (String!)"
|
|
638
|
+
},
|
|
639
|
+
"available_qty": {
|
|
640
|
+
"source": "qty",
|
|
641
|
+
"comment": "✅ From InventoryPosition.qty (Int!)"
|
|
642
|
+
},
|
|
643
|
+
"product_name": {
|
|
644
|
+
"source": "product.name",
|
|
645
|
+
"comment": "✅ From InventoryPosition.product.name (String) - nested"
|
|
646
|
+
},
|
|
647
|
+
"product_gtin": {
|
|
648
|
+
"source": "product.gtin",
|
|
649
|
+
"comment": "✅ From InventoryPosition.product.gtin (String) - nested"
|
|
650
|
+
},
|
|
651
|
+
"catalogue": {
|
|
652
|
+
"source": "product.catalogue.ref",
|
|
653
|
+
"comment": "✅ From InventoryPosition.product.catalogue.ref (String!) - deeply nested"
|
|
654
|
+
},
|
|
655
|
+
"warehouse_name": {
|
|
656
|
+
"source": "location.name",
|
|
657
|
+
"comment": "✅ From InventoryPosition.location.name (String!) - nested"
|
|
658
|
+
},
|
|
659
|
+
"updated_at": {
|
|
660
|
+
"source": "updatedOn",
|
|
661
|
+
"comment": "✅ From InventoryPosition.updatedOn (DateTime)"
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
### Implementation
|
|
668
|
+
|
|
669
|
+
```typescript
|
|
670
|
+
import { UniversalMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
671
|
+
import { writeParquetFile } from './utils/parquet-writer';
|
|
672
|
+
|
|
673
|
+
// Load mapping configuration
|
|
674
|
+
const mappingConfig = JSON.parse(fs.readFileSync('./config/extraction-mappings.json', 'utf-8'));
|
|
675
|
+
|
|
676
|
+
// Create mapper
|
|
677
|
+
const mapper = new UniversalMapper(mappingConfig);
|
|
678
|
+
|
|
679
|
+
// Query Fluent Commerce (with pagination)
|
|
680
|
+
const allRecords = [];
|
|
681
|
+
let hasNextPage = true;
|
|
682
|
+
let cursor = null;
|
|
683
|
+
|
|
684
|
+
while (hasNextPage) {
|
|
685
|
+
const result = await client.graphql({
|
|
686
|
+
query: extractionQuery,
|
|
687
|
+
variables: { after: cursor, first: 100 },
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
const edges = result.data.inventoryPositions.edges;
|
|
691
|
+
|
|
692
|
+
// Process each GraphQL node
|
|
693
|
+
for (const edge of edges) {
|
|
694
|
+
const mapResult = await mapper.map(edge.node);
|
|
695
|
+
|
|
696
|
+
if (mapResult.success) {
|
|
697
|
+
allRecords.push(mapResult.data);
|
|
698
|
+
} else {
|
|
699
|
+
console.error('Mapping failed for node:', edge.node.id);
|
|
700
|
+
console.error('Errors:', mapResult.errors);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// Check pagination
|
|
705
|
+
hasNextPage = result.data.inventoryPositions.pageInfo.hasNextPage;
|
|
706
|
+
cursor = edges[edges.length - 1]?.cursor;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// Write to Parquet file
|
|
710
|
+
await writeParquetFile('inventory-positions.parquet', allRecords, {
|
|
711
|
+
schema: {
|
|
712
|
+
position_id: { type: 'UTF8' },
|
|
713
|
+
position_ref: { type: 'UTF8' },
|
|
714
|
+
sku: { type: 'UTF8' },
|
|
715
|
+
warehouse: { type: 'UTF8' },
|
|
716
|
+
available_qty: { type: 'INT32' },
|
|
717
|
+
product_name: { type: 'UTF8' },
|
|
718
|
+
product_gtin: { type: 'UTF8' },
|
|
719
|
+
catalogue: { type: 'UTF8' },
|
|
720
|
+
warehouse_name: { type: 'UTF8' },
|
|
721
|
+
updated_at: { type: 'TIMESTAMP_MILLIS' },
|
|
722
|
+
},
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
console.log(`✅ Extracted ${allRecords.length} inventory positions to Parquet`);
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
### Parquet Output
|
|
729
|
+
|
|
730
|
+
The Parquet file will contain columnar data optimized for analytics:
|
|
731
|
+
|
|
732
|
+
| position_id | sku | warehouse | available_qty | product_name | warehouse_name |
|
|
733
|
+
| ----------- | -------- | --------- | ------------- | ------------------ | ------------------------------- |
|
|
734
|
+
| POS-1 | PROD-001 | WH-001 | 50 | Widget Master 3000 | Springfield Distribution Center |
|
|
735
|
+
| POS-2 | PROD-002 | WH-001 | 150 | Keyboard Elite | Springfield Distribution Center |
|
|
736
|
+
|
|
737
|
+
### Key Points
|
|
738
|
+
|
|
739
|
+
- **Nested Field Access:** Use dot notation for nested GraphQL fields
|
|
740
|
+
- **GraphQL Pagination:** Handle `edges` and `nodes` structure
|
|
741
|
+
- **No GraphQL Execution:** Mapper only transforms pre-fetched data
|
|
742
|
+
- **Parquet Schema:** Define column types for efficient storage
|
|
743
|
+
- **Data Lake Ready:** Columnar format for analytics and BI tools
|
|
744
|
+
|
|
745
|
+
**Schema Reference:**
|
|
746
|
+
|
|
747
|
+
- Query: `inventoryPositions(first: Int, after: String): InventoryPositionConnection!`
|
|
748
|
+
- See [`docs/schema/fluent-commerce-schema.json`](../../../04-REFERENCE/schema/fluent-commerce-schema.json) → `types.InventoryPosition`
|
|
749
|
+
|
|
750
|
+
---
|
|
751
|
+
|
|
752
|
+
## Comparison Matrix
|
|
753
|
+
|
|
754
|
+
| Use Case | Direction | Source Format | Target Format | GraphQL Execution | Component | Platform |
|
|
755
|
+
| -------------------- | --------- | ------------- | ------------- | ----------------- | ---------------------------------- | -------- |
|
|
756
|
+
| **CSV → Fluent** | `ingest` | CSV | N/A | ❌ No (generates payload) | `UniversalMapper` + Batch API | Standalone |
|
|
757
|
+
| **XML → Fluent** | `ingest` | XML | N/A | ❌ No (generates payload) | `GraphQLMutationMapper` | Standalone |
|
|
758
|
+
| **Fluent → XML** | `extract` | GraphQL | XML | ❌ No | `UniversalMapper` + `XMLBuilder` | Standalone |
|
|
759
|
+
| **Fluent → Parquet** | `extract` | GraphQL | Parquet | ❌ No | `UniversalMapper` + Parquet writer | Standalone |
|
|
760
|
+
|
|
761
|
+
**Note:** For `ingest` direction, mappers generate GraphQL payloads but do NOT execute them. You must call `client.graphql(payload)` separately.
|
|
762
|
+
|
|
763
|
+
---
|
|
764
|
+
|
|
765
|
+
## Key Takeaways
|
|
766
|
+
|
|
767
|
+
1. **Same Pattern Everywhere:** All use cases use the same `fields` mapping structure
|
|
768
|
+
2. **Direction Matters:** `ingest` executes mutations, `extract` only transforms
|
|
769
|
+
3. **Resolvers Are Universal:** SDK resolvers work across all formats
|
|
770
|
+
4. **Custom Logic:** Use custom resolvers for business-specific transformations
|
|
771
|
+
5. **Validation First:** Always validate against schema before deployment
|
|
772
|
+
|
|
773
|
+
---
|
|
774
|
+
|
|
775
|
+
## Practice Exercise
|
|
776
|
+
|
|
777
|
+
**Task:** Create a mapping for extracting Fluent orders to JSON for a data warehouse.
|
|
778
|
+
|
|
779
|
+
**Requirements:**
|
|
780
|
+
|
|
781
|
+
1. Query orders with customer and items
|
|
782
|
+
2. Flatten nested customer data
|
|
783
|
+
3. Map items array
|
|
784
|
+
4. Include calculated fields (item totals)
|
|
785
|
+
5. Format dates as ISO8601
|
|
786
|
+
|
|
787
|
+
<details>
|
|
788
|
+
<summary>Click to see solution</summary>
|
|
789
|
+
|
|
790
|
+
**Mapping Configuration:**
|
|
791
|
+
|
|
792
|
+
```json
|
|
793
|
+
{
|
|
794
|
+
"direction": "extract",
|
|
795
|
+
"sourceFormat": "graphql",
|
|
796
|
+
"targetFormat": "json",
|
|
797
|
+
|
|
798
|
+
"fields": {
|
|
799
|
+
"order_id": {
|
|
800
|
+
"source": "id"
|
|
801
|
+
},
|
|
802
|
+
"order_ref": {
|
|
803
|
+
"source": "ref"
|
|
804
|
+
},
|
|
805
|
+
"customer_id": {
|
|
806
|
+
"source": "customer.id"
|
|
807
|
+
},
|
|
808
|
+
"customer_email": {
|
|
809
|
+
"source": "customer.email",
|
|
810
|
+
"resolver": "sdk.lowercase"
|
|
811
|
+
},
|
|
812
|
+
"customer_name": {
|
|
813
|
+
"resolver": "custom.fullName"
|
|
814
|
+
},
|
|
815
|
+
"total_price": {
|
|
816
|
+
"source": "totalPrice",
|
|
817
|
+
"resolver": "sdk.parseFloat"
|
|
818
|
+
},
|
|
819
|
+
"created_at": {
|
|
820
|
+
"source": "createdOn",
|
|
821
|
+
"resolver": "sdk.formatDate"
|
|
822
|
+
},
|
|
823
|
+
"items": {
|
|
824
|
+
"source": "items",
|
|
825
|
+
"isArray": true,
|
|
826
|
+
"fields": {
|
|
827
|
+
"item_ref": {
|
|
828
|
+
"source": "ref"
|
|
829
|
+
},
|
|
830
|
+
"product_ref": {
|
|
831
|
+
"source": "productRef"
|
|
832
|
+
},
|
|
833
|
+
"quantity": {
|
|
834
|
+
"source": "quantity",
|
|
835
|
+
"resolver": "sdk.parseInt"
|
|
836
|
+
},
|
|
837
|
+
"unit_price": {
|
|
838
|
+
"source": "price",
|
|
839
|
+
"resolver": "sdk.parseFloat"
|
|
840
|
+
},
|
|
841
|
+
"total_price": {
|
|
842
|
+
"resolver": "custom.calculateItemTotal"
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
**Custom Resolvers:**
|
|
851
|
+
|
|
852
|
+
```typescript
|
|
853
|
+
const customResolvers = {
|
|
854
|
+
'custom.fullName': (value: any, sourceData: any, config: any, helpers: any) => {
|
|
855
|
+
const firstName = helpers.get(sourceData, 'customer.firstName', '');
|
|
856
|
+
const lastName = helpers.get(sourceData, 'customer.lastName', '');
|
|
857
|
+
return `${firstName} ${lastName}`.trim();
|
|
858
|
+
},
|
|
859
|
+
|
|
860
|
+
'custom.calculateItemTotal': (value: any, sourceData: any, config: any, helpers: any) => {
|
|
861
|
+
const qty = helpers.parseIntSafe(sourceData.quantity, 0);
|
|
862
|
+
const price = helpers.parseFloatSafe(sourceData.price, 0);
|
|
863
|
+
return qty * price;
|
|
864
|
+
},
|
|
865
|
+
};
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
</details>
|
|
869
|
+
|
|
870
|
+
---
|
|
871
|
+
|
|
872
|
+
## Next Steps
|
|
873
|
+
|
|
874
|
+
Now that you've seen real-world use cases, you're ready for advanced patterns:
|
|
875
|
+
|
|
876
|
+
→ Continue to [Module 5: Advanced Patterns](./mapping-05-advanced-patterns.md)
|
|
877
|
+
|
|
878
|
+
**Alternative paths:**
|
|
879
|
+
|
|
880
|
+
- Review [Helpers & Resolvers](./mapping-06-helpers-resolvers.md) for complete helper documentation
|
|
881
|
+
- Check [API Reference](../api-reference/readme.md) for TypeScript usage
|
|
882
|
+
|
|
883
|
+
---
|
|
884
|
+
|
|
885
|
+
[← Back to Schema Validation](./mapping-03-schema-validation.md) | [Next: Advanced Patterns →](./mapping-05-advanced-patterns.md)
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
|