@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,925 +1,925 @@
|
|
|
1
|
-
# Module 4: GraphQL Mutation Mapping
|
|
2
|
-
|
|
3
|
-
**Level:** Advanced
|
|
4
|
-
**Category:** Data Transformation
|
|
5
|
-
|
|
6
|
-
## Overview
|
|
7
|
-
|
|
8
|
-
The GraphQL Mutation Mapping system provides schema-driven transformation of XML/JSON data into GraphQL mutation inputs with full validation and type safety.
|
|
9
|
-
|
|
10
|
-
## Table of Contents
|
|
11
|
-
|
|
12
|
-
- [GraphQLMutationMapper](#graphqlmutationmapper)
|
|
13
|
-
- [Path Resolvers](#path-resolvers)
|
|
14
|
-
- [GraphQL Introspection Service](#graphql-introspection-service)
|
|
15
|
-
- [Mapping Configuration](#mapping-configuration)
|
|
16
|
-
- [Complete Examples](#complete-examples)
|
|
17
|
-
- [See Also](#see-also)
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## GraphQLMutationMapper
|
|
22
|
-
|
|
23
|
-
Main class for mapping source data to GraphQL mutations.
|
|
24
|
-
|
|
25
|
-
### Constructor
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
import { GraphQLMutationMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
29
|
-
|
|
30
|
-
const mapper = new GraphQLMutationMapper(
|
|
31
|
-
config: MappingConfig,
|
|
32
|
-
logger?: StructuredLogger,
|
|
33
|
-
options?: MappingOptions
|
|
34
|
-
);
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
**Parameters:**
|
|
38
|
-
- `config: MappingConfig` - Mapping configuration object
|
|
39
|
-
- `logger?: StructuredLogger` - Optional logger instance
|
|
40
|
-
- `options?: MappingOptions` - Optional configuration (customResolvers, fluentClient, context)
|
|
41
|
-
|
|
42
|
-
**MappingOptions Interface:**
|
|
43
|
-
```typescript
|
|
44
|
-
interface MappingOptions {
|
|
45
|
-
/** Custom resolver functions (stored and used by mapWithNodes) */
|
|
46
|
-
customResolvers?: ResolversMap;
|
|
47
|
-
|
|
48
|
-
/** Custom transform functions (for map() method) */
|
|
49
|
-
customTransforms?: Record<string, TransformFunction>;
|
|
50
|
-
|
|
51
|
-
/** Schema cache TTL in milliseconds (default: 3600000) */
|
|
52
|
-
schemaCacheTTL?: number;
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
**Usage:** `customResolvers` should be passed in the constructor (consistent with `UniversalMapper`). Method call resolvers can override constructor resolvers for per-call customization. Constructor resolvers are merged with method call resolvers, with method call resolvers taking precedence.
|
|
57
|
-
|
|
58
|
-
### map Method
|
|
59
|
-
|
|
60
|
-
Transform source data into a GraphQL mutation payload.
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
async map(
|
|
64
|
-
sourceData: unknown,
|
|
65
|
-
hooks?: MappingHooks
|
|
66
|
-
): Promise<GraphQLPayload>
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
**Parameters:**
|
|
70
|
-
- `sourceData: unknown` - XML or JSON source data (already parsed)
|
|
71
|
-
- `hooks?: MappingHooks` - Optional lifecycle hooks
|
|
72
|
-
|
|
73
|
-
**Returns:**
|
|
74
|
-
- `GraphQLPayload` - Object with `query` and `variables` properties
|
|
75
|
-
|
|
76
|
-
**Example:**
|
|
77
|
-
```typescript
|
|
78
|
-
import { GraphQLMutationMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
79
|
-
import mappingConfig from './mappings/sfcc-order-to-fluent.json';
|
|
80
|
-
|
|
81
|
-
const mapper = new GraphQLMutationMapper(mappingConfig, logger);
|
|
82
|
-
|
|
83
|
-
// Map XML data to createOrder mutation
|
|
84
|
-
const payload = await mapper.map(parsedXmlData, {
|
|
85
|
-
beforeMapping: async (data, context) => {
|
|
86
|
-
// Preprocess data before mapping
|
|
87
|
-
return data;
|
|
88
|
-
},
|
|
89
|
-
afterMapping: async (variables, context) => {
|
|
90
|
-
// Post-process mapped variables
|
|
91
|
-
variables.input.totalPrice = calculateTotal(variables.input.items);
|
|
92
|
-
return variables;
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// Execute mutation
|
|
97
|
-
const result = await fluentClient.graphql(payload);
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### mapWithNodes Method
|
|
101
|
-
|
|
102
|
-
Transform source data with custom resolvers and XML node extraction support.
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
async mapWithNodes(
|
|
106
|
-
rootData: unknown,
|
|
107
|
-
resolvers?: ResolversMap,
|
|
108
|
-
context?: ResolverContext
|
|
109
|
-
): Promise<MapWithNodesResult>
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
**Parameters:**
|
|
113
|
-
- `rootData: unknown` - Source data (XML/JSON, already parsed)
|
|
114
|
-
- `resolvers?: ResolversMap` - Optional custom resolver functions (overrides constructor resolvers)
|
|
115
|
-
- `context?: ResolverContext` - Optional context with fluentClient, config, helpers
|
|
116
|
-
|
|
117
|
-
**Returns:**
|
|
118
|
-
- `MapWithNodesResult` - Object with `success`, `data`, `variables`, `query`, `context`, and `errors`
|
|
119
|
-
|
|
120
|
-
**MapWithNodesResult Interface:**
|
|
121
|
-
```typescript
|
|
122
|
-
interface MapWithNodesResult {
|
|
123
|
-
/** Whether mapping succeeded */
|
|
124
|
-
success: boolean;
|
|
125
|
-
|
|
126
|
-
/** Unwrapped mapped data (for direct field access: result.data.orderNo) */
|
|
127
|
-
data: Record<string, any>;
|
|
128
|
-
|
|
129
|
-
/** Wrapped variables for GraphQL execution (use this in client.graphql())
|
|
130
|
-
* - Fields pattern: { input: { ... } }
|
|
131
|
-
* - Arguments pattern: { ... } (unwrapped)
|
|
132
|
-
*/
|
|
133
|
-
variables: Record<string, any>;
|
|
134
|
-
|
|
135
|
-
/** GraphQL mutation query string (auto-generated) */
|
|
136
|
-
query: string;
|
|
137
|
-
|
|
138
|
-
/** Extracted nodes context */
|
|
139
|
-
context: NodesContext;
|
|
140
|
-
|
|
141
|
-
/** Error messages (if any) */
|
|
142
|
-
errors: string[];
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
**Example:**
|
|
147
|
-
```typescript
|
|
148
|
-
import { GraphQLMutationMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
149
|
-
|
|
150
|
-
const mapper = new GraphQLMutationMapper(mappingConfig, logger, {
|
|
151
|
-
customResolvers: baseResolvers, // Constructor resolvers
|
|
152
|
-
fluentClient: fluentClient // Available as helpers.fluentClient in resolvers
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
// Map with custom resolvers and XML nodes
|
|
156
|
-
// Pass resolverContext - resolvers can access config via helpers.context.config
|
|
157
|
-
const resolverContext = {
|
|
158
|
-
fluentClient,
|
|
159
|
-
config: { retailerId: '1', defaultOrderType: 'HD' },
|
|
160
|
-
helpers: { fluentClient }
|
|
161
|
-
};
|
|
162
|
-
const result = await mapper.mapWithNodes(xmlData, overrideResolvers, resolverContext);
|
|
163
|
-
|
|
164
|
-
// In your resolver, access config:
|
|
165
|
-
// const retailerId = helpers.context?.config?.retailerId;
|
|
166
|
-
// OR use the config parameter directly:
|
|
167
|
-
// const retailerId = config?.retailerId;
|
|
168
|
-
|
|
169
|
-
// Check success (errors are returned, not thrown)
|
|
170
|
-
if (!result.success) {
|
|
171
|
-
console.error('Mapping failed:', result.errors);
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Execute mutation (use result.variables for GraphQL, result.data for field access)
|
|
176
|
-
await fluentClient.graphql({
|
|
177
|
-
query: result.query,
|
|
178
|
-
variables: result.variables // ✅ Use variables (wrapped if fields pattern)
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
// Access mapped fields directly (unwrapped)
|
|
182
|
-
const orderRef = result.data.ref; // ✅ Use data for direct field access
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
**Key Features:**
|
|
186
|
-
- ✅ **Custom resolvers** - Full access to source data and helpers
|
|
187
|
-
- ✅ **XML node extraction** - Extract nested/escaped XML segments
|
|
188
|
-
- ✅ **Context passing** - FluentClient, config, helpers available to resolvers
|
|
189
|
-
- ✅ **Auto-generated query** - No need to call `buildMutation()` separately
|
|
190
|
-
- ✅ **Error handling** - Returns error result instead of throwing
|
|
191
|
-
|
|
192
|
-
### GraphQLPayload Interface
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
interface GraphQLPayload<T = Record<string, JsonValue>> {
|
|
196
|
-
query: string; // GraphQL mutation string with operation name
|
|
197
|
-
variables?: T; // Mutation variables (optional)
|
|
198
|
-
operationName?: string; // Optional operation name
|
|
199
|
-
pagination?: PaginationConfig; // Optional pagination configuration for queries
|
|
200
|
-
}
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
**Example Output:**
|
|
204
|
-
```typescript
|
|
205
|
-
{
|
|
206
|
-
query: `
|
|
207
|
-
mutation CreateOrderFromSFCC($input: CreateOrderInput!) {
|
|
208
|
-
createOrder(input: $input) {
|
|
209
|
-
id
|
|
210
|
-
ref
|
|
211
|
-
status
|
|
212
|
-
createdOn
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
`,
|
|
216
|
-
variables: {
|
|
217
|
-
input: {
|
|
218
|
-
ref: '0017326966182',
|
|
219
|
-
type: 'STANDARD',
|
|
220
|
-
retailer: '1',
|
|
221
|
-
customer: 'CUST-001',
|
|
222
|
-
items: [
|
|
223
|
-
{ ref: 'PROD-001', productRef: 'PROD-001', quantity: 2 }
|
|
224
|
-
]
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
## Path Resolvers
|
|
231
|
-
|
|
232
|
-
Path resolvers extract data from XML or JSON structures using path expressions.
|
|
233
|
-
|
|
234
|
-
### XMLPathResolver
|
|
235
|
-
|
|
236
|
-
Resolves XML paths with attribute support and graceful null/undefined handling.
|
|
237
|
-
|
|
238
|
-
```typescript
|
|
239
|
-
import { XMLPathResolver } from '@fluentcommerce/fc-connect-sdk';
|
|
240
|
-
|
|
241
|
-
const resolver = new XMLPathResolver();
|
|
242
|
-
|
|
243
|
-
// Element access
|
|
244
|
-
const orderNo = resolver.resolve(xmlData, 'order.order-no');
|
|
245
|
-
|
|
246
|
-
// Attribute access (using @)
|
|
247
|
-
const orderId = resolver.resolve(xmlData, 'order@order-no');
|
|
248
|
-
|
|
249
|
-
// Array indexing
|
|
250
|
-
const firstItem = resolver.resolve(xmlData, 'items.item[0].sku');
|
|
251
|
-
|
|
252
|
-
// Wildcard iteration
|
|
253
|
-
const allSkus = resolver.resolve(xmlData, 'items.item.*.sku');
|
|
254
|
-
|
|
255
|
-
// Graceful handling of undefined/null data
|
|
256
|
-
const value = resolver.resolve(undefined, 'any.path'); // Returns: undefined (no error)
|
|
257
|
-
const value2 = resolver.resolve(null, 'any.path'); // Returns: undefined (no error)
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
**Path Syntax:**
|
|
261
|
-
- `element.child` - Element traversal
|
|
262
|
-
- `element@attribute` - Attribute access
|
|
263
|
-
- `array[0]` - Array indexing
|
|
264
|
-
- `array.*` - Wildcard (all array items)
|
|
265
|
-
- `element[attr=value]` - Filter by attribute value
|
|
266
|
-
|
|
267
|
-
**Input Formats Supported:**
|
|
268
|
-
- Raw XML strings (auto-parsed using `parseSync()`)
|
|
269
|
-
- Pre-parsed objects with @-prefix attributes: `{ order: { "@id": "123" } }`
|
|
270
|
-
- Pre-parsed objects with $-object attributes: `{ order: { $: { id: "123" } } }`
|
|
271
|
-
- `undefined` or `null` (returns `undefined` gracefully without errors)
|
|
272
|
-
|
|
273
|
-
**Methods:**
|
|
274
|
-
- `resolve(data: any, path: string): any` - Resolve path to value (returns undefined for null/undefined data)
|
|
275
|
-
- `exists(data: any, path: string): boolean` - Check if path exists
|
|
276
|
-
- `getType(data: any, path: string): string` - Get value type
|
|
277
|
-
|
|
278
|
-
**Error Handling:**
|
|
279
|
-
- Gracefully handles `undefined` and `null` input data (returns `undefined`)
|
|
280
|
-
- Throws `PathResolutionError` only for invalid paths or data structure mismatches
|
|
281
|
-
- Safe to use in optional chaining scenarios
|
|
282
|
-
|
|
283
|
-
### JSONPathResolver
|
|
284
|
-
|
|
285
|
-
Resolves JSON paths with property access.
|
|
286
|
-
|
|
287
|
-
```typescript
|
|
288
|
-
import { JSONPathResolver } from '@fluentcommerce/fc-connect-sdk';
|
|
289
|
-
|
|
290
|
-
const resolver = new JSONPathResolver();
|
|
291
|
-
|
|
292
|
-
// Property access
|
|
293
|
-
const orderNo = resolver.resolve(jsonData, 'order.orderNo');
|
|
294
|
-
|
|
295
|
-
// Nested properties
|
|
296
|
-
const email = resolver.resolve(jsonData, 'customer.email');
|
|
297
|
-
|
|
298
|
-
// Array indexing
|
|
299
|
-
const firstItem = resolver.resolve(jsonData, 'items[0].sku');
|
|
300
|
-
|
|
301
|
-
// Wildcard iteration
|
|
302
|
-
const allSkus = resolver.resolve(jsonData, 'items.*.sku');
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
**Path Syntax:**
|
|
306
|
-
- `property.nested` - Property traversal
|
|
307
|
-
- `array[0]` - Array indexing
|
|
308
|
-
- `array.*` - Wildcard (all array items)
|
|
309
|
-
|
|
310
|
-
**Methods:**
|
|
311
|
-
- `resolve(data: any, path: string): any` - Resolve path to value
|
|
312
|
-
- `exists(data: any, path: string): boolean` - Check if path exists
|
|
313
|
-
- `getType(data: any, path: string): string` - Get value type
|
|
314
|
-
|
|
315
|
-
## GraphQL Introspection Service
|
|
316
|
-
|
|
317
|
-
Fetches and caches GraphQL schema information for validation.
|
|
318
|
-
|
|
319
|
-
```typescript
|
|
320
|
-
import { GraphQLIntrospectionService } from '@fluentcommerce/fc-connect-sdk';
|
|
321
|
-
|
|
322
|
-
const introspection = new GraphQLIntrospectionService(
|
|
323
|
-
client: FluentClient,
|
|
324
|
-
logger?: StructuredLogger,
|
|
325
|
-
cacheTTL?: number // Default: 3600000ms (1 hour)
|
|
326
|
-
);
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
### Methods
|
|
330
|
-
|
|
331
|
-
#### getSchema
|
|
332
|
-
|
|
333
|
-
Fetch complete GraphQL schema (cached).
|
|
334
|
-
|
|
335
|
-
```typescript
|
|
336
|
-
async getSchema(): Promise<GraphQLSchema>
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
**Returns:**
|
|
340
|
-
- `GraphQLSchema` - Complete schema object with types and mutations
|
|
341
|
-
|
|
342
|
-
#### getMutation
|
|
343
|
-
|
|
344
|
-
Get specific mutation definition from schema.
|
|
345
|
-
|
|
346
|
-
```typescript
|
|
347
|
-
async getMutation(name: string): Promise<GraphQLMutation | null>
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
**Parameters:**
|
|
351
|
-
- `name: string` - Mutation name (e.g., 'createOrder')
|
|
352
|
-
|
|
353
|
-
**Returns:**
|
|
354
|
-
- `GraphQLMutation` - Mutation definition with arguments and return type
|
|
355
|
-
- `null` - If mutation not found
|
|
356
|
-
|
|
357
|
-
**Example:**
|
|
358
|
-
```typescript
|
|
359
|
-
const mutation = await introspection.getMutation('createOrder');
|
|
360
|
-
console.log('Arguments:', mutation.args);
|
|
361
|
-
console.log('Return type:', mutation.type);
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
#### getInputType
|
|
365
|
-
|
|
366
|
-
Get input type definition from schema.
|
|
367
|
-
|
|
368
|
-
```typescript
|
|
369
|
-
async getInputType(typeName: string): Promise<GraphQLInputType | null>
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
**Parameters:**
|
|
373
|
-
- `typeName: string` - Input type name (e.g., 'CreateOrderInput')
|
|
374
|
-
|
|
375
|
-
**Returns:**
|
|
376
|
-
- `GraphQLInputType` - Input type definition with fields
|
|
377
|
-
- `null` - If type not found
|
|
378
|
-
|
|
379
|
-
**Example:**
|
|
380
|
-
```typescript
|
|
381
|
-
const inputType = await introspection.getInputType('CreateOrderInput');
|
|
382
|
-
console.log('Fields:', inputType.inputFields);
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
#### clearCache
|
|
386
|
-
|
|
387
|
-
Clear cached schema.
|
|
388
|
-
|
|
389
|
-
```typescript
|
|
390
|
-
clearCache(): void
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
## Mapping Configuration
|
|
394
|
-
|
|
395
|
-
Mapping configurations define how source data maps to GraphQL mutation arguments.
|
|
396
|
-
|
|
397
|
-
### MappingConfig Interface
|
|
398
|
-
|
|
399
|
-
```typescript
|
|
400
|
-
interface MappingConfig {
|
|
401
|
-
// Core Configuration
|
|
402
|
-
version: string; // Config version (e.g., '1.0')
|
|
403
|
-
name?: string; // Mapping name
|
|
404
|
-
description?: string; // Description
|
|
405
|
-
|
|
406
|
-
// GraphQL Mutation Configuration
|
|
407
|
-
mutation: string; // GraphQL mutation name (e.g., 'createOrder')
|
|
408
|
-
operationName?: string; // Operation name for debugging
|
|
409
|
-
sourceFormat: 'xml' | 'json' | 'jsonl'; // Source data format (determines path resolver)
|
|
410
|
-
|
|
411
|
-
// Validation & Processing
|
|
412
|
-
schemaValidation?: boolean; // Enable validation (default: true)
|
|
413
|
-
|
|
414
|
-
// Field Mappings (choose one pattern)
|
|
415
|
-
arguments?: Record<string, FieldConfig>; // Mutation arguments (Pattern 1 - older approach)
|
|
416
|
-
fields?: Record<string, FieldConfig>; // Universal field mappings (Pattern 2 - preferred)
|
|
417
|
-
|
|
418
|
-
// Return Configuration
|
|
419
|
-
returnFields?: string[]; // Fields to return from mutation (defaults to ['id', 'ref'])
|
|
420
|
-
|
|
421
|
-
// Optional: Alias batching configuration
|
|
422
|
-
aliasBatching?: {
|
|
423
|
-
enabled?: boolean;
|
|
424
|
-
mutationsPerBatch?: number;
|
|
425
|
-
maxMutationsPerBatch?: number;
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
**Key Fields:**
|
|
431
|
-
|
|
432
|
-
- **`mutation`** (required): GraphQL mutation name (e.g., `'createOrder'`). Used by `buildMutationQuery()` to generate the GraphQL mutation string.
|
|
433
|
-
|
|
434
|
-
- **`sourceFormat`** (required): Determines which path resolver to use:
|
|
435
|
-
- `'xml'` → Uses `XMLPathResolver` (handles XML paths like `order.order-no`, `order@id`)
|
|
436
|
-
- `'json'` → Uses `JSONPathResolver` (handles JSON paths like `order.orderNo`, `order.id`)
|
|
437
|
-
- `'jsonl'` → Uses `JSONPathResolver` (same as JSON)
|
|
438
|
-
|
|
439
|
-
**Example Configuration:**
|
|
440
|
-
```typescript
|
|
441
|
-
const mappingConfig: MappingConfig = {
|
|
442
|
-
version: '1.0',
|
|
443
|
-
mutation: 'createOrder',
|
|
444
|
-
sourceFormat: 'xml', // ← Determines XMLPathResolver vs JSONPathResolver
|
|
445
|
-
fields: {
|
|
446
|
-
ref: { source: 'order@order-no', required: true }, // ← XML attribute syntax
|
|
447
|
-
totalPrice: { source: 'order.total', resolver: 'sdk.parseFloat' }
|
|
448
|
-
}
|
|
449
|
-
};
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
**Note:** `direction` is NOT part of `MappingConfig`. It's only used in `MappingTemplate` (for template generation metadata) and is not used by `GraphQLMutationMapper`.
|
|
453
|
-
|
|
454
|
-
### FieldConfig Interface
|
|
455
|
-
|
|
456
|
-
```typescript
|
|
457
|
-
interface FieldConfig {
|
|
458
|
-
// Value source
|
|
459
|
-
source?: string; // Path to source data (supports wildcards like "items[*].node")
|
|
460
|
-
value?: any; // Static value
|
|
461
|
-
|
|
462
|
-
// Validation
|
|
463
|
-
required?: boolean; // Field is required. See note below about validation timing with resolvers.
|
|
464
|
-
_type?: string; // GraphQL type (for validation)
|
|
465
|
-
|
|
466
|
-
// Transformation
|
|
467
|
-
transform?: string; // Transformation function name
|
|
468
|
-
resolver?: string; // Resolver function (sdk.* or custom.*)
|
|
469
|
-
defaultValue?: any; // Default value if missing
|
|
470
|
-
|
|
471
|
-
// Array handling
|
|
472
|
-
_array?: boolean; // Field is array (GraphQL mutation mapper)
|
|
473
|
-
isArray?: boolean; // Treat source as array and map each element (UniversalMapper)
|
|
474
|
-
_autoWrap?: boolean; // Wrap single value in array
|
|
475
|
-
_validation?: {
|
|
476
|
-
minItems?: number;
|
|
477
|
-
maxItems?: number;
|
|
478
|
-
};
|
|
479
|
-
|
|
480
|
-
// Nested objects/arrays
|
|
481
|
-
_nested?: boolean; // Field is nested object (GraphQL mutation mapper)
|
|
482
|
-
fields?: Record<string, FieldConfig>; // Nested field mappings (UniversalMapper)
|
|
483
|
-
|
|
484
|
-
// Metadata
|
|
485
|
-
description?: string; // Field description
|
|
486
|
-
_comment?: string; // Comment for documentation
|
|
487
|
-
|
|
488
|
-
// Nested fields (for objects and arrays - GraphQL mutation mapper)
|
|
489
|
-
[key: string]: any; // Child field configurations
|
|
490
|
-
}
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
**Array Field Mapping (`isArray` option):**
|
|
494
|
-
|
|
495
|
-
When `isArray: true` is set along with `fields`, the mapper treats the source as an array and maps each element using the nested field mappings:
|
|
496
|
-
|
|
497
|
-
```json
|
|
498
|
-
{
|
|
499
|
-
"items": {
|
|
500
|
-
"source": "orderItems",
|
|
501
|
-
"isArray": true,
|
|
502
|
-
"fields": {
|
|
503
|
-
"id": { "source": "id" },
|
|
504
|
-
"name": { "source": "name" },
|
|
505
|
-
"quantity": { "source": "qty", "resolver": "sdk.parseInt" }
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
This configuration:
|
|
512
|
-
1. Extracts array from `orderItems`
|
|
513
|
-
2. Maps each array element using the nested `fields` configuration
|
|
514
|
-
3. Uses each array item as the context for nested field mapping
|
|
515
|
-
|
|
516
|
-
**GraphQL Pagination Pattern:**
|
|
517
|
-
|
|
518
|
-
Handle GraphQL edges/nodes with three equivalent patterns:
|
|
519
|
-
|
|
520
|
-
**Option 1: Wildcard (extracts nodes)**
|
|
521
|
-
```json
|
|
522
|
-
{
|
|
523
|
-
"products": {
|
|
524
|
-
"source": "products.edges[*].node",
|
|
525
|
-
"isArray": true,
|
|
526
|
-
"fields": {
|
|
527
|
-
"id": { "source": "id" }, // Direct access
|
|
528
|
-
"ref": { "source": "ref" }
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
```
|
|
533
|
-
|
|
534
|
-
**Option 2: Direct (extracts edges)**
|
|
535
|
-
```json
|
|
536
|
-
{
|
|
537
|
-
"products": {
|
|
538
|
-
"source": "products.edges",
|
|
539
|
-
"isArray": true,
|
|
540
|
-
"fields": {
|
|
541
|
-
"id": { "source": "node.id" }, // Need "node." prefix
|
|
542
|
-
"ref": { "source": "node.ref" }
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
**Option 3: Auto-detection**
|
|
549
|
-
```json
|
|
550
|
-
{
|
|
551
|
-
"products": {
|
|
552
|
-
"source": "products", // SDK detects { edges: [...] }
|
|
553
|
-
"isArray": true,
|
|
554
|
-
"fields": {
|
|
555
|
-
"id": { "source": "id" }, // Nodes auto-extracted
|
|
556
|
-
"ref": { "source": "ref" }
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
```
|
|
561
|
-
|
|
562
|
-
The `[*]` wildcard is **optional** - all three patterns produce the same result.
|
|
563
|
-
|
|
564
|
-
### Complete Configuration Example
|
|
565
|
-
|
|
566
|
-
```json
|
|
567
|
-
{
|
|
568
|
-
"version": "1.0",
|
|
569
|
-
"name": "SFCC Order to Fluent",
|
|
570
|
-
"description": "Maps SFCC order XML to Fluent createOrder mutation",
|
|
571
|
-
"mutation": "createOrder",
|
|
572
|
-
"operationName": "CreateOrderFromSFCC",
|
|
573
|
-
"sourceFormat": "xml",
|
|
574
|
-
"schemaValidation": true,
|
|
575
|
-
|
|
576
|
-
"arguments": {
|
|
577
|
-
"input": {
|
|
578
|
-
"_type": "CreateOrderInput!",
|
|
579
|
-
|
|
580
|
-
"ref": {
|
|
581
|
-
"source": "orders.order@order-no",
|
|
582
|
-
"required": true,
|
|
583
|
-
"description": "Order reference from SFCC"
|
|
584
|
-
},
|
|
585
|
-
|
|
586
|
-
"type": {
|
|
587
|
-
"value": "STANDARD",
|
|
588
|
-
"required": true
|
|
589
|
-
},
|
|
590
|
-
|
|
591
|
-
"retailer": {
|
|
592
|
-
"value": "${FLUENT_RETAILER_ID}",
|
|
593
|
-
"required": true
|
|
594
|
-
},
|
|
595
|
-
|
|
596
|
-
"items": {
|
|
597
|
-
"_type": "[CreateOrderItemInput]!",
|
|
598
|
-
"_array": true,
|
|
599
|
-
"source": "orders.order.product-lineitems.product-lineitem",
|
|
600
|
-
"_validation": {
|
|
601
|
-
"minItems": 1,
|
|
602
|
-
"maxItems": 100
|
|
603
|
-
},
|
|
604
|
-
|
|
605
|
-
"ref": {
|
|
606
|
-
"source": "product-id",
|
|
607
|
-
"required": true
|
|
608
|
-
},
|
|
609
|
-
|
|
610
|
-
"quantity": {
|
|
611
|
-
"source": "quantity",
|
|
612
|
-
"transform": "parseInt",
|
|
613
|
-
"required": true,
|
|
614
|
-
"defaultValue": 1
|
|
615
|
-
},
|
|
616
|
-
|
|
617
|
-
"paidPrice": {
|
|
618
|
-
"source": "net-price",
|
|
619
|
-
"transform": "parseFloat"
|
|
620
|
-
}
|
|
621
|
-
},
|
|
622
|
-
|
|
623
|
-
"fulfilmentChoice": {
|
|
624
|
-
"_type": "CreateFulfilmentChoiceInput",
|
|
625
|
-
"_nested": true,
|
|
626
|
-
|
|
627
|
-
"deliveryAddress": {
|
|
628
|
-
"_type": "CreateCustomerAddressInput",
|
|
629
|
-
"_nested": true,
|
|
630
|
-
"source": "orders.order.shipments.shipment.shipping-address",
|
|
631
|
-
|
|
632
|
-
"city": {
|
|
633
|
-
"source": "city",
|
|
634
|
-
"required": true
|
|
635
|
-
},
|
|
636
|
-
|
|
637
|
-
"country": {
|
|
638
|
-
"source": "country-code",
|
|
639
|
-
"required": true,
|
|
640
|
-
"transform": "toUpperCase"
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
},
|
|
646
|
-
|
|
647
|
-
"returnFields": ["id", "ref", "status", "createdOn"]
|
|
648
|
-
}
|
|
649
|
-
```
|
|
650
|
-
|
|
651
|
-
### MappingHooks Interface
|
|
652
|
-
|
|
653
|
-
Lifecycle hooks for custom preprocessing and postprocessing.
|
|
654
|
-
|
|
655
|
-
```typescript
|
|
656
|
-
interface MappingHooks {
|
|
657
|
-
beforeMapping?: (
|
|
658
|
-
sourceData: any,
|
|
659
|
-
context: MappingContext
|
|
660
|
-
) => Promise<any> | any;
|
|
661
|
-
|
|
662
|
-
afterMapping?: (
|
|
663
|
-
variables: Record<string, any>,
|
|
664
|
-
context: MappingContext
|
|
665
|
-
) => Promise<Record<string, any>> | Record<string, any>;
|
|
666
|
-
}
|
|
667
|
-
```
|
|
668
|
-
|
|
669
|
-
**MappingContext Interface:**
|
|
670
|
-
```typescript
|
|
671
|
-
interface MappingContext {
|
|
672
|
-
mutation: string;
|
|
673
|
-
sourceFormat: 'xml' | 'json';
|
|
674
|
-
logger?: StructuredLogger;
|
|
675
|
-
metadata?: Record<string, any>;
|
|
676
|
-
}
|
|
677
|
-
```
|
|
678
|
-
|
|
679
|
-
**Example Hooks:**
|
|
680
|
-
```typescript
|
|
681
|
-
const hooks: MappingHooks = {
|
|
682
|
-
beforeMapping: async (sourceData, context) => {
|
|
683
|
-
// Parse custom attributes
|
|
684
|
-
if (sourceData.customAttributes) {
|
|
685
|
-
sourceData.parsed = parseCustomAttributes(sourceData.customAttributes);
|
|
686
|
-
}
|
|
687
|
-
return sourceData;
|
|
688
|
-
},
|
|
689
|
-
|
|
690
|
-
afterMapping: async (variables, context) => {
|
|
691
|
-
// Calculate order total
|
|
692
|
-
variables.input.totalPrice = variables.input.items.reduce(
|
|
693
|
-
(sum, item) => sum + (item.paidPrice * item.quantity),
|
|
694
|
-
0
|
|
695
|
-
);
|
|
696
|
-
|
|
697
|
-
// Add metadata
|
|
698
|
-
variables.input.attributes = variables.input.attributes || [];
|
|
699
|
-
variables.input.attributes.push({
|
|
700
|
-
name: 'integration_source',
|
|
701
|
-
type: 'STRING',
|
|
702
|
-
value: JSON.stringify('SFCC')
|
|
703
|
-
});
|
|
704
|
-
|
|
705
|
-
return variables;
|
|
706
|
-
}
|
|
707
|
-
};
|
|
708
|
-
|
|
709
|
-
const payload = await mapper.map(sourceData, hooks);
|
|
710
|
-
```
|
|
711
|
-
|
|
712
|
-
### Built-in Transformations
|
|
713
|
-
|
|
714
|
-
The mapper supports these built-in transformation functions:
|
|
715
|
-
|
|
716
|
-
| Transform | Description | Example |
|
|
717
|
-
|-----------|-------------|---------|
|
|
718
|
-
| `parseInt` | Parse integer | `"42"` → `42` |
|
|
719
|
-
| `parseFloat` | Parse float | `"3.14"` → `3.14` |
|
|
720
|
-
| `toString` | Convert to string | `42` → `"42"` |
|
|
721
|
-
| `toUpperCase` | Uppercase string | `"usa"` → `"USA"` |
|
|
722
|
-
| `toLowerCase` | Lowercase string | `"USA"` → `"usa"` |
|
|
723
|
-
| `trim` | Trim whitespace | `" text "` → `"text"` |
|
|
724
|
-
| `toBoolean` | Parse boolean | `"true"` → `true` |
|
|
725
|
-
| `toISO8601` | Format date | `Date` → `"2025-01-01T00:00:00Z"` |
|
|
726
|
-
| `toDate` | Parse date | `"2025-01-01"` → `Date` |
|
|
727
|
-
|
|
728
|
-
**Usage in Configuration:**
|
|
729
|
-
```json
|
|
730
|
-
{
|
|
731
|
-
"quantity": {
|
|
732
|
-
"source": "qty",
|
|
733
|
-
"transform": "parseInt"
|
|
734
|
-
},
|
|
735
|
-
"country": {
|
|
736
|
-
"source": "country_code",
|
|
737
|
-
"transform": "toUpperCase"
|
|
738
|
-
},
|
|
739
|
-
"updatedAt": {
|
|
740
|
-
"source": "last_modified",
|
|
741
|
-
"transform": "toISO8601"
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
```
|
|
745
|
-
|
|
746
|
-
### Custom Transformations
|
|
747
|
-
|
|
748
|
-
Add custom transformation functions during mapper initialization.
|
|
749
|
-
|
|
750
|
-
```typescript
|
|
751
|
-
const mapper = new GraphQLMutationMapper(
|
|
752
|
-
mappingConfig,
|
|
753
|
-
logger,
|
|
754
|
-
{
|
|
755
|
-
fluentClient: client,
|
|
756
|
-
customTransforms: {
|
|
757
|
-
toPhoneNumber: (value: string) => {
|
|
758
|
-
return value.replace(/\D/g, '').slice(0, 10);
|
|
759
|
-
},
|
|
760
|
-
|
|
761
|
-
calculateTotal: (items: any[]) => {
|
|
762
|
-
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
|
|
763
|
-
},
|
|
764
|
-
|
|
765
|
-
formatAddress: (address: any) => {
|
|
766
|
-
return `${address.street}, ${address.city}, ${address.state} ${address.zip}`;
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
);
|
|
771
|
-
```
|
|
772
|
-
|
|
773
|
-
**Use in Configuration:**
|
|
774
|
-
```json
|
|
775
|
-
{
|
|
776
|
-
"phone": {
|
|
777
|
-
"source": "customer.phone",
|
|
778
|
-
"transform": "toPhoneNumber"
|
|
779
|
-
},
|
|
780
|
-
"total": {
|
|
781
|
-
"source": "orderItems",
|
|
782
|
-
"transform": "calculateTotal"
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
```
|
|
786
|
-
|
|
787
|
-
## Complete Examples
|
|
788
|
-
|
|
789
|
-
### Complete Mapping Example
|
|
790
|
-
|
|
791
|
-
```typescript
|
|
792
|
-
import {
|
|
793
|
-
createClient,
|
|
794
|
-
GraphQLMutationMapper,
|
|
795
|
-
XMLParserService,
|
|
796
|
-
MappingHooks
|
|
797
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
798
|
-
import mappingConfig from './mappings/sfcc-order-to-fluent.json';
|
|
799
|
-
import { readFileSync } from 'fs';
|
|
800
|
-
|
|
801
|
-
// 1. Initialize client
|
|
802
|
-
const client = await createClient({
|
|
803
|
-
config: {
|
|
804
|
-
baseUrl: 'https://api.fluentcommerce.com',
|
|
805
|
-
clientId: process.env.FLUENT_CLIENT_ID,
|
|
806
|
-
clientSecret: process.env.FLUENT_CLIENT_SECRET,
|
|
807
|
-
username: process.env.FLUENT_USERNAME,
|
|
808
|
-
password: process.env.FLUENT_PASSWORD,
|
|
809
|
-
retailerId: '1'
|
|
810
|
-
}
|
|
811
|
-
});
|
|
812
|
-
|
|
813
|
-
// 2. Parse XML
|
|
814
|
-
const xmlParser = new XMLParserService();
|
|
815
|
-
const xmlContent = readFileSync('order.xml', 'utf-8');
|
|
816
|
-
const parsedXml = await xmlParser.parse(xmlContent, {
|
|
817
|
-
includeAttributes: true,
|
|
818
|
-
attributePrefix: '@'
|
|
819
|
-
});
|
|
820
|
-
|
|
821
|
-
// 3. Configure hooks
|
|
822
|
-
const hooks: MappingHooks = {
|
|
823
|
-
beforeMapping: async (data, context) => {
|
|
824
|
-
context.logger?.info('Preprocessing order data');
|
|
825
|
-
return data;
|
|
826
|
-
},
|
|
827
|
-
|
|
828
|
-
afterMapping: async (variables, context) => {
|
|
829
|
-
// Calculate total
|
|
830
|
-
variables.input.totalPrice = variables.input.items.reduce(
|
|
831
|
-
(sum, item) => sum + (item.paidPrice * item.quantity),
|
|
832
|
-
0
|
|
833
|
-
);
|
|
834
|
-
|
|
835
|
-
// Add audit metadata
|
|
836
|
-
variables.input.attributes = variables.input.attributes || [];
|
|
837
|
-
variables.input.attributes.push({
|
|
838
|
-
name: 'integration_source',
|
|
839
|
-
type: 'STRING',
|
|
840
|
-
value: JSON.stringify('SFCC')
|
|
841
|
-
});
|
|
842
|
-
|
|
843
|
-
context.logger?.info('Order total calculated', {
|
|
844
|
-
total: variables.input.totalPrice
|
|
845
|
-
});
|
|
846
|
-
|
|
847
|
-
return variables;
|
|
848
|
-
}
|
|
849
|
-
};
|
|
850
|
-
|
|
851
|
-
// 4. Initialize mapper
|
|
852
|
-
const mapper = new GraphQLMutationMapper(
|
|
853
|
-
mappingConfig as any,
|
|
854
|
-
console,
|
|
855
|
-
{ fluentClient: client }
|
|
856
|
-
);
|
|
857
|
-
|
|
858
|
-
// 5. Map data
|
|
859
|
-
const payload = await mapper.map(parsedXml, hooks);
|
|
860
|
-
|
|
861
|
-
// 6. Execute mutation
|
|
862
|
-
const result = await client.graphql(payload);
|
|
863
|
-
|
|
864
|
-
console.log('Order created:', result.data.createOrder);
|
|
865
|
-
```
|
|
866
|
-
|
|
867
|
-
### Environment Variables in Mappings
|
|
868
|
-
|
|
869
|
-
Use environment variables for dynamic values:
|
|
870
|
-
|
|
871
|
-
```json
|
|
872
|
-
{
|
|
873
|
-
"retailer": {
|
|
874
|
-
"value": "${FLUENT_RETAILER_ID}",
|
|
875
|
-
"required": true
|
|
876
|
-
},
|
|
877
|
-
"createdBy": {
|
|
878
|
-
"value": "${INTEGRATION_NAME}"
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
```
|
|
882
|
-
|
|
883
|
-
**Runtime Resolution:**
|
|
884
|
-
- `"${FLUENT_RETAILER_ID}"` resolves to `process.env.FLUENT_RETAILER_ID`
|
|
885
|
-
- Non-env strings pass through unchanged
|
|
886
|
-
|
|
887
|
-
### Error Handling
|
|
888
|
-
|
|
889
|
-
The mapper throws `MappingError` for validation failures:
|
|
890
|
-
|
|
891
|
-
```typescript
|
|
892
|
-
import { MappingError } from '@fluentcommerce/fc-connect-sdk';
|
|
893
|
-
|
|
894
|
-
try {
|
|
895
|
-
const payload = await mapper.map(sourceData);
|
|
896
|
-
} catch (error) {
|
|
897
|
-
if (error instanceof MappingError) {
|
|
898
|
-
console.error('Mapping failed:', {
|
|
899
|
-
field: error.field,
|
|
900
|
-
sourcePath: error.sourcePath,
|
|
901
|
-
message: error.message,
|
|
902
|
-
expectedType: error.expectedType,
|
|
903
|
-
actualType: error.actualType
|
|
904
|
-
});
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
```
|
|
908
|
-
|
|
909
|
-
**Common Errors:**
|
|
910
|
-
- `Required field 'ref' is missing or empty`
|
|
911
|
-
- `Expected array but got object at path 'items'`
|
|
912
|
-
- `Type mismatch: expected Int! but got String`
|
|
913
|
-
- `Cannot resolve path 'order.missing'`
|
|
914
|
-
|
|
915
|
-
## See Also
|
|
916
|
-
|
|
917
|
-
- [GraphQL Mutation Mapping Guide](../../mapping/graphql-mutation-mapping/graphql-mutation-mapping-readme.md) - Detailed guide
|
|
918
|
-
- [Module 7: Parsers](./api-reference-07-parsers.md) - XML and JSON parsers
|
|
919
|
-
- [Module 5: Services](./api-reference-05-services.md) - UniversalMapper service
|
|
920
|
-
- [Module 9: Error Handling](./api-reference-09-error-handling.md) - Error types and handling
|
|
921
|
-
- [Examples: GraphQL Operations](../examples/) - See examples directory
|
|
922
|
-
|
|
923
|
-
---
|
|
924
|
-
|
|
925
|
-
**[← Previous: Authentication](./api-reference-03-authentication.md)** | **[API Reference Home](../api-reference-readme.md)** | **[Next: Services →](./api-reference-05-services.md)**
|
|
1
|
+
# Module 4: GraphQL Mutation Mapping
|
|
2
|
+
|
|
3
|
+
**Level:** Advanced
|
|
4
|
+
**Category:** Data Transformation
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
The GraphQL Mutation Mapping system provides schema-driven transformation of XML/JSON data into GraphQL mutation inputs with full validation and type safety.
|
|
9
|
+
|
|
10
|
+
## Table of Contents
|
|
11
|
+
|
|
12
|
+
- [GraphQLMutationMapper](#graphqlmutationmapper)
|
|
13
|
+
- [Path Resolvers](#path-resolvers)
|
|
14
|
+
- [GraphQL Introspection Service](#graphql-introspection-service)
|
|
15
|
+
- [Mapping Configuration](#mapping-configuration)
|
|
16
|
+
- [Complete Examples](#complete-examples)
|
|
17
|
+
- [See Also](#see-also)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## GraphQLMutationMapper
|
|
22
|
+
|
|
23
|
+
Main class for mapping source data to GraphQL mutations.
|
|
24
|
+
|
|
25
|
+
### Constructor
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { GraphQLMutationMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
29
|
+
|
|
30
|
+
const mapper = new GraphQLMutationMapper(
|
|
31
|
+
config: MappingConfig,
|
|
32
|
+
logger?: StructuredLogger,
|
|
33
|
+
options?: MappingOptions
|
|
34
|
+
);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Parameters:**
|
|
38
|
+
- `config: MappingConfig` - Mapping configuration object
|
|
39
|
+
- `logger?: StructuredLogger` - Optional logger instance
|
|
40
|
+
- `options?: MappingOptions` - Optional configuration (customResolvers, fluentClient, context)
|
|
41
|
+
|
|
42
|
+
**MappingOptions Interface:**
|
|
43
|
+
```typescript
|
|
44
|
+
interface MappingOptions {
|
|
45
|
+
/** Custom resolver functions (stored and used by mapWithNodes) */
|
|
46
|
+
customResolvers?: ResolversMap;
|
|
47
|
+
|
|
48
|
+
/** Custom transform functions (for map() method) */
|
|
49
|
+
customTransforms?: Record<string, TransformFunction>;
|
|
50
|
+
|
|
51
|
+
/** Schema cache TTL in milliseconds (default: 3600000) */
|
|
52
|
+
schemaCacheTTL?: number;
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Usage:** `customResolvers` should be passed in the constructor (consistent with `UniversalMapper`). Method call resolvers can override constructor resolvers for per-call customization. Constructor resolvers are merged with method call resolvers, with method call resolvers taking precedence.
|
|
57
|
+
|
|
58
|
+
### map Method
|
|
59
|
+
|
|
60
|
+
Transform source data into a GraphQL mutation payload.
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
async map(
|
|
64
|
+
sourceData: unknown,
|
|
65
|
+
hooks?: MappingHooks
|
|
66
|
+
): Promise<GraphQLPayload>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Parameters:**
|
|
70
|
+
- `sourceData: unknown` - XML or JSON source data (already parsed)
|
|
71
|
+
- `hooks?: MappingHooks` - Optional lifecycle hooks
|
|
72
|
+
|
|
73
|
+
**Returns:**
|
|
74
|
+
- `GraphQLPayload` - Object with `query` and `variables` properties
|
|
75
|
+
|
|
76
|
+
**Example:**
|
|
77
|
+
```typescript
|
|
78
|
+
import { GraphQLMutationMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
79
|
+
import mappingConfig from './mappings/sfcc-order-to-fluent.json';
|
|
80
|
+
|
|
81
|
+
const mapper = new GraphQLMutationMapper(mappingConfig, logger);
|
|
82
|
+
|
|
83
|
+
// Map XML data to createOrder mutation
|
|
84
|
+
const payload = await mapper.map(parsedXmlData, {
|
|
85
|
+
beforeMapping: async (data, context) => {
|
|
86
|
+
// Preprocess data before mapping
|
|
87
|
+
return data;
|
|
88
|
+
},
|
|
89
|
+
afterMapping: async (variables, context) => {
|
|
90
|
+
// Post-process mapped variables
|
|
91
|
+
variables.input.totalPrice = calculateTotal(variables.input.items);
|
|
92
|
+
return variables;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Execute mutation
|
|
97
|
+
const result = await fluentClient.graphql(payload);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### mapWithNodes Method
|
|
101
|
+
|
|
102
|
+
Transform source data with custom resolvers and XML node extraction support.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
async mapWithNodes(
|
|
106
|
+
rootData: unknown,
|
|
107
|
+
resolvers?: ResolversMap,
|
|
108
|
+
context?: ResolverContext
|
|
109
|
+
): Promise<MapWithNodesResult>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Parameters:**
|
|
113
|
+
- `rootData: unknown` - Source data (XML/JSON, already parsed)
|
|
114
|
+
- `resolvers?: ResolversMap` - Optional custom resolver functions (overrides constructor resolvers)
|
|
115
|
+
- `context?: ResolverContext` - Optional context with fluentClient, config, helpers
|
|
116
|
+
|
|
117
|
+
**Returns:**
|
|
118
|
+
- `MapWithNodesResult` - Object with `success`, `data`, `variables`, `query`, `context`, and `errors`
|
|
119
|
+
|
|
120
|
+
**MapWithNodesResult Interface:**
|
|
121
|
+
```typescript
|
|
122
|
+
interface MapWithNodesResult {
|
|
123
|
+
/** Whether mapping succeeded */
|
|
124
|
+
success: boolean;
|
|
125
|
+
|
|
126
|
+
/** Unwrapped mapped data (for direct field access: result.data.orderNo) */
|
|
127
|
+
data: Record<string, any>;
|
|
128
|
+
|
|
129
|
+
/** Wrapped variables for GraphQL execution (use this in client.graphql())
|
|
130
|
+
* - Fields pattern: { input: { ... } }
|
|
131
|
+
* - Arguments pattern: { ... } (unwrapped)
|
|
132
|
+
*/
|
|
133
|
+
variables: Record<string, any>;
|
|
134
|
+
|
|
135
|
+
/** GraphQL mutation query string (auto-generated) */
|
|
136
|
+
query: string;
|
|
137
|
+
|
|
138
|
+
/** Extracted nodes context */
|
|
139
|
+
context: NodesContext;
|
|
140
|
+
|
|
141
|
+
/** Error messages (if any) */
|
|
142
|
+
errors: string[];
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Example:**
|
|
147
|
+
```typescript
|
|
148
|
+
import { GraphQLMutationMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
149
|
+
|
|
150
|
+
const mapper = new GraphQLMutationMapper(mappingConfig, logger, {
|
|
151
|
+
customResolvers: baseResolvers, // Constructor resolvers
|
|
152
|
+
fluentClient: fluentClient // Available as helpers.fluentClient in resolvers
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Map with custom resolvers and XML nodes
|
|
156
|
+
// Pass resolverContext - resolvers can access config via helpers.context.config
|
|
157
|
+
const resolverContext = {
|
|
158
|
+
fluentClient,
|
|
159
|
+
config: { retailerId: '1', defaultOrderType: 'HD' },
|
|
160
|
+
helpers: { fluentClient }
|
|
161
|
+
};
|
|
162
|
+
const result = await mapper.mapWithNodes(xmlData, overrideResolvers, resolverContext);
|
|
163
|
+
|
|
164
|
+
// In your resolver, access config:
|
|
165
|
+
// const retailerId = helpers.context?.config?.retailerId;
|
|
166
|
+
// OR use the config parameter directly:
|
|
167
|
+
// const retailerId = config?.retailerId;
|
|
168
|
+
|
|
169
|
+
// Check success (errors are returned, not thrown)
|
|
170
|
+
if (!result.success) {
|
|
171
|
+
console.error('Mapping failed:', result.errors);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Execute mutation (use result.variables for GraphQL, result.data for field access)
|
|
176
|
+
await fluentClient.graphql({
|
|
177
|
+
query: result.query,
|
|
178
|
+
variables: result.variables // ✅ Use variables (wrapped if fields pattern)
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// Access mapped fields directly (unwrapped)
|
|
182
|
+
const orderRef = result.data.ref; // ✅ Use data for direct field access
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Key Features:**
|
|
186
|
+
- ✅ **Custom resolvers** - Full access to source data and helpers
|
|
187
|
+
- ✅ **XML node extraction** - Extract nested/escaped XML segments
|
|
188
|
+
- ✅ **Context passing** - FluentClient, config, helpers available to resolvers
|
|
189
|
+
- ✅ **Auto-generated query** - No need to call `buildMutation()` separately
|
|
190
|
+
- ✅ **Error handling** - Returns error result instead of throwing
|
|
191
|
+
|
|
192
|
+
### GraphQLPayload Interface
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
interface GraphQLPayload<T = Record<string, JsonValue>> {
|
|
196
|
+
query: string; // GraphQL mutation string with operation name
|
|
197
|
+
variables?: T; // Mutation variables (optional)
|
|
198
|
+
operationName?: string; // Optional operation name
|
|
199
|
+
pagination?: PaginationConfig; // Optional pagination configuration for queries
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Example Output:**
|
|
204
|
+
```typescript
|
|
205
|
+
{
|
|
206
|
+
query: `
|
|
207
|
+
mutation CreateOrderFromSFCC($input: CreateOrderInput!) {
|
|
208
|
+
createOrder(input: $input) {
|
|
209
|
+
id
|
|
210
|
+
ref
|
|
211
|
+
status
|
|
212
|
+
createdOn
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
`,
|
|
216
|
+
variables: {
|
|
217
|
+
input: {
|
|
218
|
+
ref: '0017326966182',
|
|
219
|
+
type: 'STANDARD',
|
|
220
|
+
retailer: '1',
|
|
221
|
+
customer: 'CUST-001',
|
|
222
|
+
items: [
|
|
223
|
+
{ ref: 'PROD-001', productRef: 'PROD-001', quantity: 2 }
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Path Resolvers
|
|
231
|
+
|
|
232
|
+
Path resolvers extract data from XML or JSON structures using path expressions.
|
|
233
|
+
|
|
234
|
+
### XMLPathResolver
|
|
235
|
+
|
|
236
|
+
Resolves XML paths with attribute support and graceful null/undefined handling.
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import { XMLPathResolver } from '@fluentcommerce/fc-connect-sdk';
|
|
240
|
+
|
|
241
|
+
const resolver = new XMLPathResolver();
|
|
242
|
+
|
|
243
|
+
// Element access
|
|
244
|
+
const orderNo = resolver.resolve(xmlData, 'order.order-no');
|
|
245
|
+
|
|
246
|
+
// Attribute access (using @)
|
|
247
|
+
const orderId = resolver.resolve(xmlData, 'order@order-no');
|
|
248
|
+
|
|
249
|
+
// Array indexing
|
|
250
|
+
const firstItem = resolver.resolve(xmlData, 'items.item[0].sku');
|
|
251
|
+
|
|
252
|
+
// Wildcard iteration
|
|
253
|
+
const allSkus = resolver.resolve(xmlData, 'items.item.*.sku');
|
|
254
|
+
|
|
255
|
+
// Graceful handling of undefined/null data
|
|
256
|
+
const value = resolver.resolve(undefined, 'any.path'); // Returns: undefined (no error)
|
|
257
|
+
const value2 = resolver.resolve(null, 'any.path'); // Returns: undefined (no error)
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**Path Syntax:**
|
|
261
|
+
- `element.child` - Element traversal
|
|
262
|
+
- `element@attribute` - Attribute access
|
|
263
|
+
- `array[0]` - Array indexing
|
|
264
|
+
- `array.*` - Wildcard (all array items)
|
|
265
|
+
- `element[attr=value]` - Filter by attribute value
|
|
266
|
+
|
|
267
|
+
**Input Formats Supported:**
|
|
268
|
+
- Raw XML strings (auto-parsed using `parseSync()`)
|
|
269
|
+
- Pre-parsed objects with @-prefix attributes: `{ order: { "@id": "123" } }`
|
|
270
|
+
- Pre-parsed objects with $-object attributes: `{ order: { $: { id: "123" } } }`
|
|
271
|
+
- `undefined` or `null` (returns `undefined` gracefully without errors)
|
|
272
|
+
|
|
273
|
+
**Methods:**
|
|
274
|
+
- `resolve(data: any, path: string): any` - Resolve path to value (returns undefined for null/undefined data)
|
|
275
|
+
- `exists(data: any, path: string): boolean` - Check if path exists
|
|
276
|
+
- `getType(data: any, path: string): string` - Get value type
|
|
277
|
+
|
|
278
|
+
**Error Handling:**
|
|
279
|
+
- Gracefully handles `undefined` and `null` input data (returns `undefined`)
|
|
280
|
+
- Throws `PathResolutionError` only for invalid paths or data structure mismatches
|
|
281
|
+
- Safe to use in optional chaining scenarios
|
|
282
|
+
|
|
283
|
+
### JSONPathResolver
|
|
284
|
+
|
|
285
|
+
Resolves JSON paths with property access.
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
import { JSONPathResolver } from '@fluentcommerce/fc-connect-sdk';
|
|
289
|
+
|
|
290
|
+
const resolver = new JSONPathResolver();
|
|
291
|
+
|
|
292
|
+
// Property access
|
|
293
|
+
const orderNo = resolver.resolve(jsonData, 'order.orderNo');
|
|
294
|
+
|
|
295
|
+
// Nested properties
|
|
296
|
+
const email = resolver.resolve(jsonData, 'customer.email');
|
|
297
|
+
|
|
298
|
+
// Array indexing
|
|
299
|
+
const firstItem = resolver.resolve(jsonData, 'items[0].sku');
|
|
300
|
+
|
|
301
|
+
// Wildcard iteration
|
|
302
|
+
const allSkus = resolver.resolve(jsonData, 'items.*.sku');
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Path Syntax:**
|
|
306
|
+
- `property.nested` - Property traversal
|
|
307
|
+
- `array[0]` - Array indexing
|
|
308
|
+
- `array.*` - Wildcard (all array items)
|
|
309
|
+
|
|
310
|
+
**Methods:**
|
|
311
|
+
- `resolve(data: any, path: string): any` - Resolve path to value
|
|
312
|
+
- `exists(data: any, path: string): boolean` - Check if path exists
|
|
313
|
+
- `getType(data: any, path: string): string` - Get value type
|
|
314
|
+
|
|
315
|
+
## GraphQL Introspection Service
|
|
316
|
+
|
|
317
|
+
Fetches and caches GraphQL schema information for validation.
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
import { GraphQLIntrospectionService } from '@fluentcommerce/fc-connect-sdk';
|
|
321
|
+
|
|
322
|
+
const introspection = new GraphQLIntrospectionService(
|
|
323
|
+
client: FluentClient,
|
|
324
|
+
logger?: StructuredLogger,
|
|
325
|
+
cacheTTL?: number // Default: 3600000ms (1 hour)
|
|
326
|
+
);
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Methods
|
|
330
|
+
|
|
331
|
+
#### getSchema
|
|
332
|
+
|
|
333
|
+
Fetch complete GraphQL schema (cached).
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
async getSchema(): Promise<GraphQLSchema>
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
**Returns:**
|
|
340
|
+
- `GraphQLSchema` - Complete schema object with types and mutations
|
|
341
|
+
|
|
342
|
+
#### getMutation
|
|
343
|
+
|
|
344
|
+
Get specific mutation definition from schema.
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
async getMutation(name: string): Promise<GraphQLMutation | null>
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Parameters:**
|
|
351
|
+
- `name: string` - Mutation name (e.g., 'createOrder')
|
|
352
|
+
|
|
353
|
+
**Returns:**
|
|
354
|
+
- `GraphQLMutation` - Mutation definition with arguments and return type
|
|
355
|
+
- `null` - If mutation not found
|
|
356
|
+
|
|
357
|
+
**Example:**
|
|
358
|
+
```typescript
|
|
359
|
+
const mutation = await introspection.getMutation('createOrder');
|
|
360
|
+
console.log('Arguments:', mutation.args);
|
|
361
|
+
console.log('Return type:', mutation.type);
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
#### getInputType
|
|
365
|
+
|
|
366
|
+
Get input type definition from schema.
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
async getInputType(typeName: string): Promise<GraphQLInputType | null>
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
**Parameters:**
|
|
373
|
+
- `typeName: string` - Input type name (e.g., 'CreateOrderInput')
|
|
374
|
+
|
|
375
|
+
**Returns:**
|
|
376
|
+
- `GraphQLInputType` - Input type definition with fields
|
|
377
|
+
- `null` - If type not found
|
|
378
|
+
|
|
379
|
+
**Example:**
|
|
380
|
+
```typescript
|
|
381
|
+
const inputType = await introspection.getInputType('CreateOrderInput');
|
|
382
|
+
console.log('Fields:', inputType.inputFields);
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
#### clearCache
|
|
386
|
+
|
|
387
|
+
Clear cached schema.
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
clearCache(): void
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
## Mapping Configuration
|
|
394
|
+
|
|
395
|
+
Mapping configurations define how source data maps to GraphQL mutation arguments.
|
|
396
|
+
|
|
397
|
+
### MappingConfig Interface
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
interface MappingConfig {
|
|
401
|
+
// Core Configuration
|
|
402
|
+
version: string; // Config version (e.g., '1.0')
|
|
403
|
+
name?: string; // Mapping name
|
|
404
|
+
description?: string; // Description
|
|
405
|
+
|
|
406
|
+
// GraphQL Mutation Configuration
|
|
407
|
+
mutation: string; // GraphQL mutation name (e.g., 'createOrder')
|
|
408
|
+
operationName?: string; // Operation name for debugging
|
|
409
|
+
sourceFormat: 'xml' | 'json' | 'jsonl'; // Source data format (determines path resolver)
|
|
410
|
+
|
|
411
|
+
// Validation & Processing
|
|
412
|
+
schemaValidation?: boolean; // Enable validation (default: true)
|
|
413
|
+
|
|
414
|
+
// Field Mappings (choose one pattern)
|
|
415
|
+
arguments?: Record<string, FieldConfig>; // Mutation arguments (Pattern 1 - older approach)
|
|
416
|
+
fields?: Record<string, FieldConfig>; // Universal field mappings (Pattern 2 - preferred)
|
|
417
|
+
|
|
418
|
+
// Return Configuration
|
|
419
|
+
returnFields?: string[]; // Fields to return from mutation (defaults to ['id', 'ref'])
|
|
420
|
+
|
|
421
|
+
// Optional: Alias batching configuration
|
|
422
|
+
aliasBatching?: {
|
|
423
|
+
enabled?: boolean;
|
|
424
|
+
mutationsPerBatch?: number;
|
|
425
|
+
maxMutationsPerBatch?: number;
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**Key Fields:**
|
|
431
|
+
|
|
432
|
+
- **`mutation`** (required): GraphQL mutation name (e.g., `'createOrder'`). Used by `buildMutationQuery()` to generate the GraphQL mutation string.
|
|
433
|
+
|
|
434
|
+
- **`sourceFormat`** (required): Determines which path resolver to use:
|
|
435
|
+
- `'xml'` → Uses `XMLPathResolver` (handles XML paths like `order.order-no`, `order@id`)
|
|
436
|
+
- `'json'` → Uses `JSONPathResolver` (handles JSON paths like `order.orderNo`, `order.id`)
|
|
437
|
+
- `'jsonl'` → Uses `JSONPathResolver` (same as JSON)
|
|
438
|
+
|
|
439
|
+
**Example Configuration:**
|
|
440
|
+
```typescript
|
|
441
|
+
const mappingConfig: MappingConfig = {
|
|
442
|
+
version: '1.0',
|
|
443
|
+
mutation: 'createOrder',
|
|
444
|
+
sourceFormat: 'xml', // ← Determines XMLPathResolver vs JSONPathResolver
|
|
445
|
+
fields: {
|
|
446
|
+
ref: { source: 'order@order-no', required: true }, // ← XML attribute syntax
|
|
447
|
+
totalPrice: { source: 'order.total', resolver: 'sdk.parseFloat' }
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
**Note:** `direction` is NOT part of `MappingConfig`. It's only used in `MappingTemplate` (for template generation metadata) and is not used by `GraphQLMutationMapper`.
|
|
453
|
+
|
|
454
|
+
### FieldConfig Interface
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
interface FieldConfig {
|
|
458
|
+
// Value source
|
|
459
|
+
source?: string; // Path to source data (supports wildcards like "items[*].node")
|
|
460
|
+
value?: any; // Static value
|
|
461
|
+
|
|
462
|
+
// Validation
|
|
463
|
+
required?: boolean; // Field is required. See note below about validation timing with resolvers.
|
|
464
|
+
_type?: string; // GraphQL type (for validation)
|
|
465
|
+
|
|
466
|
+
// Transformation
|
|
467
|
+
transform?: string; // Transformation function name
|
|
468
|
+
resolver?: string; // Resolver function (sdk.* or custom.*)
|
|
469
|
+
defaultValue?: any; // Default value if missing
|
|
470
|
+
|
|
471
|
+
// Array handling
|
|
472
|
+
_array?: boolean; // Field is array (GraphQL mutation mapper)
|
|
473
|
+
isArray?: boolean; // Treat source as array and map each element (UniversalMapper)
|
|
474
|
+
_autoWrap?: boolean; // Wrap single value in array
|
|
475
|
+
_validation?: {
|
|
476
|
+
minItems?: number;
|
|
477
|
+
maxItems?: number;
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
// Nested objects/arrays
|
|
481
|
+
_nested?: boolean; // Field is nested object (GraphQL mutation mapper)
|
|
482
|
+
fields?: Record<string, FieldConfig>; // Nested field mappings (UniversalMapper)
|
|
483
|
+
|
|
484
|
+
// Metadata
|
|
485
|
+
description?: string; // Field description
|
|
486
|
+
_comment?: string; // Comment for documentation
|
|
487
|
+
|
|
488
|
+
// Nested fields (for objects and arrays - GraphQL mutation mapper)
|
|
489
|
+
[key: string]: any; // Child field configurations
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
**Array Field Mapping (`isArray` option):**
|
|
494
|
+
|
|
495
|
+
When `isArray: true` is set along with `fields`, the mapper treats the source as an array and maps each element using the nested field mappings:
|
|
496
|
+
|
|
497
|
+
```json
|
|
498
|
+
{
|
|
499
|
+
"items": {
|
|
500
|
+
"source": "orderItems",
|
|
501
|
+
"isArray": true,
|
|
502
|
+
"fields": {
|
|
503
|
+
"id": { "source": "id" },
|
|
504
|
+
"name": { "source": "name" },
|
|
505
|
+
"quantity": { "source": "qty", "resolver": "sdk.parseInt" }
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
This configuration:
|
|
512
|
+
1. Extracts array from `orderItems`
|
|
513
|
+
2. Maps each array element using the nested `fields` configuration
|
|
514
|
+
3. Uses each array item as the context for nested field mapping
|
|
515
|
+
|
|
516
|
+
**GraphQL Pagination Pattern:**
|
|
517
|
+
|
|
518
|
+
Handle GraphQL edges/nodes with three equivalent patterns:
|
|
519
|
+
|
|
520
|
+
**Option 1: Wildcard (extracts nodes)**
|
|
521
|
+
```json
|
|
522
|
+
{
|
|
523
|
+
"products": {
|
|
524
|
+
"source": "products.edges[*].node",
|
|
525
|
+
"isArray": true,
|
|
526
|
+
"fields": {
|
|
527
|
+
"id": { "source": "id" }, // Direct access
|
|
528
|
+
"ref": { "source": "ref" }
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
**Option 2: Direct (extracts edges)**
|
|
535
|
+
```json
|
|
536
|
+
{
|
|
537
|
+
"products": {
|
|
538
|
+
"source": "products.edges",
|
|
539
|
+
"isArray": true,
|
|
540
|
+
"fields": {
|
|
541
|
+
"id": { "source": "node.id" }, // Need "node." prefix
|
|
542
|
+
"ref": { "source": "node.ref" }
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
**Option 3: Auto-detection**
|
|
549
|
+
```json
|
|
550
|
+
{
|
|
551
|
+
"products": {
|
|
552
|
+
"source": "products", // SDK detects { edges: [...] }
|
|
553
|
+
"isArray": true,
|
|
554
|
+
"fields": {
|
|
555
|
+
"id": { "source": "id" }, // Nodes auto-extracted
|
|
556
|
+
"ref": { "source": "ref" }
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
The `[*]` wildcard is **optional** - all three patterns produce the same result.
|
|
563
|
+
|
|
564
|
+
### Complete Configuration Example
|
|
565
|
+
|
|
566
|
+
```json
|
|
567
|
+
{
|
|
568
|
+
"version": "1.0",
|
|
569
|
+
"name": "SFCC Order to Fluent",
|
|
570
|
+
"description": "Maps SFCC order XML to Fluent createOrder mutation",
|
|
571
|
+
"mutation": "createOrder",
|
|
572
|
+
"operationName": "CreateOrderFromSFCC",
|
|
573
|
+
"sourceFormat": "xml",
|
|
574
|
+
"schemaValidation": true,
|
|
575
|
+
|
|
576
|
+
"arguments": {
|
|
577
|
+
"input": {
|
|
578
|
+
"_type": "CreateOrderInput!",
|
|
579
|
+
|
|
580
|
+
"ref": {
|
|
581
|
+
"source": "orders.order@order-no",
|
|
582
|
+
"required": true,
|
|
583
|
+
"description": "Order reference from SFCC"
|
|
584
|
+
},
|
|
585
|
+
|
|
586
|
+
"type": {
|
|
587
|
+
"value": "STANDARD",
|
|
588
|
+
"required": true
|
|
589
|
+
},
|
|
590
|
+
|
|
591
|
+
"retailer": {
|
|
592
|
+
"value": "${FLUENT_RETAILER_ID}",
|
|
593
|
+
"required": true
|
|
594
|
+
},
|
|
595
|
+
|
|
596
|
+
"items": {
|
|
597
|
+
"_type": "[CreateOrderItemInput]!",
|
|
598
|
+
"_array": true,
|
|
599
|
+
"source": "orders.order.product-lineitems.product-lineitem",
|
|
600
|
+
"_validation": {
|
|
601
|
+
"minItems": 1,
|
|
602
|
+
"maxItems": 100
|
|
603
|
+
},
|
|
604
|
+
|
|
605
|
+
"ref": {
|
|
606
|
+
"source": "product-id",
|
|
607
|
+
"required": true
|
|
608
|
+
},
|
|
609
|
+
|
|
610
|
+
"quantity": {
|
|
611
|
+
"source": "quantity",
|
|
612
|
+
"transform": "parseInt",
|
|
613
|
+
"required": true,
|
|
614
|
+
"defaultValue": 1
|
|
615
|
+
},
|
|
616
|
+
|
|
617
|
+
"paidPrice": {
|
|
618
|
+
"source": "net-price",
|
|
619
|
+
"transform": "parseFloat"
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
|
|
623
|
+
"fulfilmentChoice": {
|
|
624
|
+
"_type": "CreateFulfilmentChoiceInput",
|
|
625
|
+
"_nested": true,
|
|
626
|
+
|
|
627
|
+
"deliveryAddress": {
|
|
628
|
+
"_type": "CreateCustomerAddressInput",
|
|
629
|
+
"_nested": true,
|
|
630
|
+
"source": "orders.order.shipments.shipment.shipping-address",
|
|
631
|
+
|
|
632
|
+
"city": {
|
|
633
|
+
"source": "city",
|
|
634
|
+
"required": true
|
|
635
|
+
},
|
|
636
|
+
|
|
637
|
+
"country": {
|
|
638
|
+
"source": "country-code",
|
|
639
|
+
"required": true,
|
|
640
|
+
"transform": "toUpperCase"
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
},
|
|
646
|
+
|
|
647
|
+
"returnFields": ["id", "ref", "status", "createdOn"]
|
|
648
|
+
}
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
### MappingHooks Interface
|
|
652
|
+
|
|
653
|
+
Lifecycle hooks for custom preprocessing and postprocessing.
|
|
654
|
+
|
|
655
|
+
```typescript
|
|
656
|
+
interface MappingHooks {
|
|
657
|
+
beforeMapping?: (
|
|
658
|
+
sourceData: any,
|
|
659
|
+
context: MappingContext
|
|
660
|
+
) => Promise<any> | any;
|
|
661
|
+
|
|
662
|
+
afterMapping?: (
|
|
663
|
+
variables: Record<string, any>,
|
|
664
|
+
context: MappingContext
|
|
665
|
+
) => Promise<Record<string, any>> | Record<string, any>;
|
|
666
|
+
}
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
**MappingContext Interface:**
|
|
670
|
+
```typescript
|
|
671
|
+
interface MappingContext {
|
|
672
|
+
mutation: string;
|
|
673
|
+
sourceFormat: 'xml' | 'json';
|
|
674
|
+
logger?: StructuredLogger;
|
|
675
|
+
metadata?: Record<string, any>;
|
|
676
|
+
}
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
**Example Hooks:**
|
|
680
|
+
```typescript
|
|
681
|
+
const hooks: MappingHooks = {
|
|
682
|
+
beforeMapping: async (sourceData, context) => {
|
|
683
|
+
// Parse custom attributes
|
|
684
|
+
if (sourceData.customAttributes) {
|
|
685
|
+
sourceData.parsed = parseCustomAttributes(sourceData.customAttributes);
|
|
686
|
+
}
|
|
687
|
+
return sourceData;
|
|
688
|
+
},
|
|
689
|
+
|
|
690
|
+
afterMapping: async (variables, context) => {
|
|
691
|
+
// Calculate order total
|
|
692
|
+
variables.input.totalPrice = variables.input.items.reduce(
|
|
693
|
+
(sum, item) => sum + (item.paidPrice * item.quantity),
|
|
694
|
+
0
|
|
695
|
+
);
|
|
696
|
+
|
|
697
|
+
// Add metadata
|
|
698
|
+
variables.input.attributes = variables.input.attributes || [];
|
|
699
|
+
variables.input.attributes.push({
|
|
700
|
+
name: 'integration_source',
|
|
701
|
+
type: 'STRING',
|
|
702
|
+
value: JSON.stringify('SFCC')
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
return variables;
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
const payload = await mapper.map(sourceData, hooks);
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
### Built-in Transformations
|
|
713
|
+
|
|
714
|
+
The mapper supports these built-in transformation functions:
|
|
715
|
+
|
|
716
|
+
| Transform | Description | Example |
|
|
717
|
+
|-----------|-------------|---------|
|
|
718
|
+
| `parseInt` | Parse integer | `"42"` → `42` |
|
|
719
|
+
| `parseFloat` | Parse float | `"3.14"` → `3.14` |
|
|
720
|
+
| `toString` | Convert to string | `42` → `"42"` |
|
|
721
|
+
| `toUpperCase` | Uppercase string | `"usa"` → `"USA"` |
|
|
722
|
+
| `toLowerCase` | Lowercase string | `"USA"` → `"usa"` |
|
|
723
|
+
| `trim` | Trim whitespace | `" text "` → `"text"` |
|
|
724
|
+
| `toBoolean` | Parse boolean | `"true"` → `true` |
|
|
725
|
+
| `toISO8601` | Format date | `Date` → `"2025-01-01T00:00:00Z"` |
|
|
726
|
+
| `toDate` | Parse date | `"2025-01-01"` → `Date` |
|
|
727
|
+
|
|
728
|
+
**Usage in Configuration:**
|
|
729
|
+
```json
|
|
730
|
+
{
|
|
731
|
+
"quantity": {
|
|
732
|
+
"source": "qty",
|
|
733
|
+
"transform": "parseInt"
|
|
734
|
+
},
|
|
735
|
+
"country": {
|
|
736
|
+
"source": "country_code",
|
|
737
|
+
"transform": "toUpperCase"
|
|
738
|
+
},
|
|
739
|
+
"updatedAt": {
|
|
740
|
+
"source": "last_modified",
|
|
741
|
+
"transform": "toISO8601"
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
### Custom Transformations
|
|
747
|
+
|
|
748
|
+
Add custom transformation functions during mapper initialization.
|
|
749
|
+
|
|
750
|
+
```typescript
|
|
751
|
+
const mapper = new GraphQLMutationMapper(
|
|
752
|
+
mappingConfig,
|
|
753
|
+
logger,
|
|
754
|
+
{
|
|
755
|
+
fluentClient: client,
|
|
756
|
+
customTransforms: {
|
|
757
|
+
toPhoneNumber: (value: string) => {
|
|
758
|
+
return value.replace(/\D/g, '').slice(0, 10);
|
|
759
|
+
},
|
|
760
|
+
|
|
761
|
+
calculateTotal: (items: any[]) => {
|
|
762
|
+
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
|
|
763
|
+
},
|
|
764
|
+
|
|
765
|
+
formatAddress: (address: any) => {
|
|
766
|
+
return `${address.street}, ${address.city}, ${address.state} ${address.zip}`;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
);
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
**Use in Configuration:**
|
|
774
|
+
```json
|
|
775
|
+
{
|
|
776
|
+
"phone": {
|
|
777
|
+
"source": "customer.phone",
|
|
778
|
+
"transform": "toPhoneNumber"
|
|
779
|
+
},
|
|
780
|
+
"total": {
|
|
781
|
+
"source": "orderItems",
|
|
782
|
+
"transform": "calculateTotal"
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
## Complete Examples
|
|
788
|
+
|
|
789
|
+
### Complete Mapping Example
|
|
790
|
+
|
|
791
|
+
```typescript
|
|
792
|
+
import {
|
|
793
|
+
createClient,
|
|
794
|
+
GraphQLMutationMapper,
|
|
795
|
+
XMLParserService,
|
|
796
|
+
MappingHooks
|
|
797
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
798
|
+
import mappingConfig from './mappings/sfcc-order-to-fluent.json';
|
|
799
|
+
import { readFileSync } from 'fs';
|
|
800
|
+
|
|
801
|
+
// 1. Initialize client
|
|
802
|
+
const client = await createClient({
|
|
803
|
+
config: {
|
|
804
|
+
baseUrl: 'https://api.fluentcommerce.com',
|
|
805
|
+
clientId: process.env.FLUENT_CLIENT_ID,
|
|
806
|
+
clientSecret: process.env.FLUENT_CLIENT_SECRET,
|
|
807
|
+
username: process.env.FLUENT_USERNAME,
|
|
808
|
+
password: process.env.FLUENT_PASSWORD,
|
|
809
|
+
retailerId: '1'
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
// 2. Parse XML
|
|
814
|
+
const xmlParser = new XMLParserService();
|
|
815
|
+
const xmlContent = readFileSync('order.xml', 'utf-8');
|
|
816
|
+
const parsedXml = await xmlParser.parse(xmlContent, {
|
|
817
|
+
includeAttributes: true,
|
|
818
|
+
attributePrefix: '@'
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
// 3. Configure hooks
|
|
822
|
+
const hooks: MappingHooks = {
|
|
823
|
+
beforeMapping: async (data, context) => {
|
|
824
|
+
context.logger?.info('Preprocessing order data');
|
|
825
|
+
return data;
|
|
826
|
+
},
|
|
827
|
+
|
|
828
|
+
afterMapping: async (variables, context) => {
|
|
829
|
+
// Calculate total
|
|
830
|
+
variables.input.totalPrice = variables.input.items.reduce(
|
|
831
|
+
(sum, item) => sum + (item.paidPrice * item.quantity),
|
|
832
|
+
0
|
|
833
|
+
);
|
|
834
|
+
|
|
835
|
+
// Add audit metadata
|
|
836
|
+
variables.input.attributes = variables.input.attributes || [];
|
|
837
|
+
variables.input.attributes.push({
|
|
838
|
+
name: 'integration_source',
|
|
839
|
+
type: 'STRING',
|
|
840
|
+
value: JSON.stringify('SFCC')
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
context.logger?.info('Order total calculated', {
|
|
844
|
+
total: variables.input.totalPrice
|
|
845
|
+
});
|
|
846
|
+
|
|
847
|
+
return variables;
|
|
848
|
+
}
|
|
849
|
+
};
|
|
850
|
+
|
|
851
|
+
// 4. Initialize mapper
|
|
852
|
+
const mapper = new GraphQLMutationMapper(
|
|
853
|
+
mappingConfig as any,
|
|
854
|
+
console,
|
|
855
|
+
{ fluentClient: client }
|
|
856
|
+
);
|
|
857
|
+
|
|
858
|
+
// 5. Map data
|
|
859
|
+
const payload = await mapper.map(parsedXml, hooks);
|
|
860
|
+
|
|
861
|
+
// 6. Execute mutation
|
|
862
|
+
const result = await client.graphql(payload);
|
|
863
|
+
|
|
864
|
+
console.log('Order created:', result.data.createOrder);
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
### Environment Variables in Mappings
|
|
868
|
+
|
|
869
|
+
Use environment variables for dynamic values:
|
|
870
|
+
|
|
871
|
+
```json
|
|
872
|
+
{
|
|
873
|
+
"retailer": {
|
|
874
|
+
"value": "${FLUENT_RETAILER_ID}",
|
|
875
|
+
"required": true
|
|
876
|
+
},
|
|
877
|
+
"createdBy": {
|
|
878
|
+
"value": "${INTEGRATION_NAME}"
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
**Runtime Resolution:**
|
|
884
|
+
- `"${FLUENT_RETAILER_ID}"` resolves to `process.env.FLUENT_RETAILER_ID`
|
|
885
|
+
- Non-env strings pass through unchanged
|
|
886
|
+
|
|
887
|
+
### Error Handling
|
|
888
|
+
|
|
889
|
+
The mapper throws `MappingError` for validation failures:
|
|
890
|
+
|
|
891
|
+
```typescript
|
|
892
|
+
import { MappingError } from '@fluentcommerce/fc-connect-sdk';
|
|
893
|
+
|
|
894
|
+
try {
|
|
895
|
+
const payload = await mapper.map(sourceData);
|
|
896
|
+
} catch (error) {
|
|
897
|
+
if (error instanceof MappingError) {
|
|
898
|
+
console.error('Mapping failed:', {
|
|
899
|
+
field: error.field,
|
|
900
|
+
sourcePath: error.sourcePath,
|
|
901
|
+
message: error.message,
|
|
902
|
+
expectedType: error.expectedType,
|
|
903
|
+
actualType: error.actualType
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
**Common Errors:**
|
|
910
|
+
- `Required field 'ref' is missing or empty`
|
|
911
|
+
- `Expected array but got object at path 'items'`
|
|
912
|
+
- `Type mismatch: expected Int! but got String`
|
|
913
|
+
- `Cannot resolve path 'order.missing'`
|
|
914
|
+
|
|
915
|
+
## See Also
|
|
916
|
+
|
|
917
|
+
- [GraphQL Mutation Mapping Guide](../../mapping/graphql-mutation-mapping/graphql-mutation-mapping-readme.md) - Detailed guide
|
|
918
|
+
- [Module 7: Parsers](./api-reference-07-parsers.md) - XML and JSON parsers
|
|
919
|
+
- [Module 5: Services](./api-reference-05-services.md) - UniversalMapper service
|
|
920
|
+
- [Module 9: Error Handling](./api-reference-09-error-handling.md) - Error types and handling
|
|
921
|
+
- [Examples: GraphQL Operations](../examples/) - See examples directory
|
|
922
|
+
|
|
923
|
+
---
|
|
924
|
+
|
|
925
|
+
**[← Previous: Authentication](./api-reference-03-authentication.md)** | **[API Reference Home](../api-reference-readme.md)** | **[Next: Services →](./api-reference-05-services.md)**
|