@fluentcommerce/fc-connect-sdk 0.1.54 → 0.1.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +11 -0
- package/dist/cjs/clients/fluent-client.js +13 -6
- package/dist/cjs/utils/pagination-helpers.js +38 -2
- package/dist/cjs/versori/fluent-versori-client.js +11 -5
- package/dist/esm/clients/fluent-client.js +13 -6
- package/dist/esm/utils/pagination-helpers.js +38 -2
- package/dist/esm/versori/fluent-versori-client.js +11 -5
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/tsconfig.types.tsbuildinfo +1 -1
- package/docs/00-START-HERE/EXPORT-VALIDATION.md +158 -158
- package/docs/00-START-HERE/cli-analyze-source-structure-guide.md +655 -655
- package/docs/00-START-HERE/cli-documentation-index.md +202 -202
- package/docs/00-START-HERE/cli-quick-reference.md +252 -252
- package/docs/00-START-HERE/decision-tree.md +552 -552
- package/docs/00-START-HERE/getting-started.md +1070 -1070
- package/docs/00-START-HERE/mapper-quick-decision-guide.md +235 -235
- package/docs/00-START-HERE/readme.md +237 -237
- package/docs/00-START-HERE/retailerid-configuration.md +404 -404
- package/docs/00-START-HERE/sdk-philosophy.md +794 -794
- package/docs/00-START-HERE/troubleshooting-quick-reference.md +1086 -1086
- package/docs/01-TEMPLATES/faq.md +686 -686
- package/docs/01-TEMPLATES/patterns/pattern-templates-guide.md +68 -68
- package/docs/01-TEMPLATES/patterns/patterns-csv-schema-validation-and-rejection-report.md +233 -233
- package/docs/01-TEMPLATES/patterns/patterns-custom-resolvers.md +407 -407
- package/docs/01-TEMPLATES/patterns/patterns-error-handling-retry.md +511 -511
- package/docs/01-TEMPLATES/patterns/patterns-field-mapping-universal.md +701 -701
- package/docs/01-TEMPLATES/patterns/patterns-large-file-splitting.md +1430 -1430
- package/docs/01-TEMPLATES/patterns/patterns-master-data-etl.md +2399 -2399
- package/docs/01-TEMPLATES/patterns/patterns-pagination-streaming.md +447 -447
- package/docs/01-TEMPLATES/patterns/patterns-state-duplicate-prevention.md +385 -385
- package/docs/01-TEMPLATES/readme.md +957 -957
- package/docs/01-TEMPLATES/standalone/standalone-asn-inbound-processing.md +1209 -1209
- package/docs/01-TEMPLATES/standalone/standalone-graphql-query-export.md +1140 -1140
- package/docs/01-TEMPLATES/standalone/standalone-graphql-to-parquet-partitioned-s3.md +432 -432
- package/docs/01-TEMPLATES/standalone/standalone-multi-channel-inventory-sync.md +1185 -1185
- package/docs/01-TEMPLATES/standalone/standalone-multi-source-aggregation.md +1462 -1462
- package/docs/01-TEMPLATES/standalone/standalone-s3-csv-batch-api.md +1390 -1390
- package/docs/01-TEMPLATES/standalone/standalone-s3-csv-inventory-to-batch.md +330 -330
- package/docs/01-TEMPLATES/standalone/standalone-scripts-guide.md +87 -87
- package/docs/01-TEMPLATES/standalone/standalone-sftp-xml-graphql.md +1444 -1444
- package/docs/01-TEMPLATES/standalone/standalone-webhook-payload-processing.md +688 -688
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-dropship-order-routing.md +193 -193
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-graphql-parquet-extraction.md +518 -518
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-inter-location-transfers.md +2162 -2162
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-pre-order-allocation.md +2226 -2226
- package/docs/01-TEMPLATES/versori/business-examples/business-scenarios-guide.md +87 -87
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-connection-validation-pattern.md +656 -656
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-dual-workflow-connector.md +835 -835
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-guide.md +108 -108
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-kv-state-management.md +1533 -1533
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-xml-response-patterns.md +1160 -1160
- package/docs/01-TEMPLATES/versori/versori-platform-guide.md +201 -201
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-asn-purchase-order.md +1906 -1906
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-dropship-routing.md +1074 -1074
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-flash-sale-reserve.md +1395 -1395
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-generic-xml-order.md +888 -888
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-payment-gateway-integration.md +2478 -2478
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-rma-returns-comprehensive.md +2240 -2240
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-xml-order-ingestion.md +2029 -2029
- package/docs/01-TEMPLATES/versori/webhooks/webhook-templates-guide.md +140 -140
- package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/inventory-mapping.json +20 -20
- package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/products_2025-01-22.csv +11 -11
- package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/sample-data-guide.md +34 -34
- package/docs/01-TEMPLATES/versori/workflows/_examples/workflow-examples-guide.md +36 -36
- package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-modes-guide.md +1038 -1038
- package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-workflows-guide.md +138 -138
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/graphql-extraction-guide.md +63 -63
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-csv.md +2062 -2062
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-xml.md +2294 -2294
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-s3-csv.md +2461 -2461
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-sftp-xml.md +2529 -2529
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-csv.md +2464 -2464
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-json.md +1959 -1959
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-s3-csv.md +1953 -1953
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-sftp-xml.md +2541 -2541
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-s3-json.md +2384 -2384
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-sftp-xml.md +2445 -2445
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-csv.md +2355 -2355
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-json.md +2042 -2042
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-sftp-xml.md +2726 -2726
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/batch-api-guide.md +206 -206
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-cycle-count-reconciliation.md +2030 -2030
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-multi-channel-inventory-sync.md +1882 -1882
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-csv-inventory-batch.md +2827 -2827
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-json-inventory-batch.md +1952 -1952
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-xml-inventory-batch.md +3289 -3289
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-csv-inventory-batch.md +3064 -3064
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-json-inventory-batch.md +3238 -3238
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-xml-inventory-batch.md +2977 -2977
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/event-api-guide.md +321 -321
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-json-order-cancel-event.md +959 -959
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-xml-order-cancel-event.md +1170 -1170
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-csv-product-event.md +2312 -2312
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-json-product-event.md +2999 -2999
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-parquet-product-event.md +2836 -2836
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-xml-product-event.md +2395 -2395
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-csv-product-event.md +2295 -2295
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-json-product-event.md +2602 -2602
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-parquet-product-event.md +2589 -2589
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-xml-product-event.md +3578 -3578
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/graphql-mutations-guide.md +93 -93
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-json-order-update-graphql.md +1260 -1260
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-xml-order-update-graphql.md +1472 -1472
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-control-graphql.md +2417 -2417
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-location-graphql.md +2811 -2811
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-price-graphql.md +2619 -2619
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-json-location-graphql.md +2807 -2807
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-xml-location-graphql.md +2373 -2373
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-control-graphql.md +2740 -2740
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-location-graphql.md +2760 -2760
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-json-location-graphql.md +1710 -1710
- package/docs/01-TEMPLATES/versori/workflows/ingestion/ingestion-workflows-guide.md +136 -136
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/rubix-webhooks-guide.md +520 -520
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-inline.md +1418 -1418
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-universal-mapper.md +1785 -1785
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-order-attribute-update.md +824 -824
- package/docs/01-TEMPLATES/versori/workflows/workflows-overview-guide.md +646 -646
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-batch-archival.md +724 -724
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-job-tracker.md +627 -627
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-partial-batch-recovery.md +561 -561
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-quick-reference.md +367 -367
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-readme.md +407 -407
- package/docs/02-CORE-GUIDES/advanced-services/readme.md +49 -49
- package/docs/02-CORE-GUIDES/api-reference/api-reference-quick-reference.md +548 -548
- package/docs/02-CORE-GUIDES/api-reference/event-api-input-output-reference.md +702 -1171
- package/docs/02-CORE-GUIDES/api-reference/examples/client-initialization.ts +286 -286
- package/docs/02-CORE-GUIDES/api-reference/graphql-error-classification.md +337 -337
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-01-client-api.md +399 -520
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-03-authentication.md +199 -199
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-04-graphql-mapping.md +925 -925
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-05-services.md +1198 -1198
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-06-data-sources.md +1083 -1083
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-07-parsers.md +1097 -1097
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-pagination.md +513 -513
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-types.md +545 -597
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-error-handling.md +527 -527
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-webhook-validation.md +514 -514
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-extraction.md +557 -557
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-utilities.md +412 -412
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-cli-tools.md +423 -423
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-error-handling.md +716 -716
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-analyze-source-structure.md +518 -518
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-partial-responses.md +212 -212
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-testing.md +300 -300
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-13-resolver-builder.md +322 -322
- package/docs/02-CORE-GUIDES/api-reference/readme.md +279 -279
- package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-quick-reference.md +351 -351
- package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-readme.md +277 -277
- package/docs/02-CORE-GUIDES/auto-pagination/examples/auto-pagination-readme.md +178 -178
- package/docs/02-CORE-GUIDES/auto-pagination/examples/common-patterns.ts +351 -351
- package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-products.ts +384 -384
- package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-virtual-positions.ts +308 -308
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-01-foundations.md +470 -470
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-02-quick-start.md +713 -713
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-03-configuration.md +754 -754
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-04-advanced-patterns.md +732 -732
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-05-sdk-integration.md +847 -847
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-06-troubleshooting.md +359 -359
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-07-api-reference.md +462 -462
- package/docs/02-CORE-GUIDES/auto-pagination/readme.md +54 -54
- package/docs/02-CORE-GUIDES/data-sources/data-sources-file-operations-error-handling.md +1487 -1487
- package/docs/02-CORE-GUIDES/data-sources/data-sources-quick-reference.md +836 -836
- package/docs/02-CORE-GUIDES/data-sources/data-sources-readme.md +276 -276
- package/docs/02-CORE-GUIDES/data-sources/data-sources-sftp-credential-access-security.md +553 -553
- package/docs/02-CORE-GUIDES/data-sources/examples/common-patterns.ts +409 -409
- package/docs/02-CORE-GUIDES/data-sources/examples/data-sources-readme.md +178 -178
- package/docs/02-CORE-GUIDES/data-sources/examples/s3-operations.ts +308 -308
- package/docs/02-CORE-GUIDES/data-sources/examples/sftp-operations.ts +371 -371
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-01-foundations.md +735 -735
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-02-s3-operations.md +1302 -1302
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-03-sftp-operations.md +1379 -1379
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-04-file-patterns.md +941 -941
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-05-advanced-topics.md +813 -813
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-06-integration-patterns.md +486 -486
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-07-troubleshooting.md +387 -387
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-08-api-reference.md +417 -417
- package/docs/02-CORE-GUIDES/data-sources/readme.md +77 -77
- package/docs/02-CORE-GUIDES/error-handling-guide.md +936 -936
- package/docs/02-CORE-GUIDES/extraction/examples/02-core-guides-extraction-readme.md +116 -116
- package/docs/02-CORE-GUIDES/extraction/examples/common-patterns.ts +428 -428
- package/docs/02-CORE-GUIDES/extraction/examples/extract-inventory-basic.ts +187 -187
- package/docs/02-CORE-GUIDES/extraction/extraction-quick-reference.md +596 -596
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-01-foundations.md +514 -514
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-02-basic-extraction.md +823 -823
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-03-parquet-processing.md +507 -507
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-04-data-enrichment.md +546 -546
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-05-transformation.md +494 -494
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-export-formats.md +458 -458
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-performance.md +138 -138
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-api-reference.md +148 -148
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-optimization.md +692 -692
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-08-extraction-orchestrator.md +1008 -1008
- package/docs/02-CORE-GUIDES/extraction/readme.md +151 -151
- package/docs/02-CORE-GUIDES/ingestion/examples/_simple-kv-store.ts +40 -40
- package/docs/02-CORE-GUIDES/ingestion/examples/error-recovery.ts +728 -728
- package/docs/02-CORE-GUIDES/ingestion/examples/event-driven.ts +501 -501
- package/docs/02-CORE-GUIDES/ingestion/examples/local-file-ingestion.ts +88 -88
- package/docs/02-CORE-GUIDES/ingestion/examples/parquet-ingestion.ts +117 -117
- package/docs/02-CORE-GUIDES/ingestion/examples/performance-optimized.ts +647 -647
- package/docs/02-CORE-GUIDES/ingestion/examples/s3-csv-ingestion.ts +169 -169
- package/docs/02-CORE-GUIDES/ingestion/examples/sftp-csv-ingestion.ts +134 -134
- package/docs/02-CORE-GUIDES/ingestion/ingestion-quick-reference.md +546 -546
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-01-introduction.md +626 -626
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-02-quick-start.md +658 -658
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-03-data-sources.md +1052 -1052
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-04-field-mapping.md +763 -763
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-05-advanced-parsers.md +676 -676
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-06-batch-api.md +1295 -1295
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-api-reference.md +138 -138
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-state-management.md +1037 -1037
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-08-performance-optimization.md +1349 -1349
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-09-best-practices.md +1893 -1893
- package/docs/02-CORE-GUIDES/ingestion/readme.md +160 -160
- package/docs/02-CORE-GUIDES/logging-guide.md +585 -585
- package/docs/02-CORE-GUIDES/mapping/error-handling-patterns.md +401 -401
- package/docs/02-CORE-GUIDES/mapping/examples/02-core-guides-mapping-readme.md +128 -128
- package/docs/02-CORE-GUIDES/mapping/examples/common-patterns.ts +273 -273
- package/docs/02-CORE-GUIDES/mapping/examples/csv-location-ingestion.json +36 -36
- package/docs/02-CORE-GUIDES/mapping/examples/csv-mapping.ts +242 -242
- package/docs/02-CORE-GUIDES/mapping/examples/graphql-to-parquet-extraction.json +36 -36
- package/docs/02-CORE-GUIDES/mapping/examples/json-mapping.ts +213 -213
- package/docs/02-CORE-GUIDES/mapping/examples/json-product-to-mutation.json +48 -48
- package/docs/02-CORE-GUIDES/mapping/examples/xml-mapping.ts +291 -291
- package/docs/02-CORE-GUIDES/mapping/examples/xml-order-to-mutation.json +45 -45
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-quick-reference.md +463 -463
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-readme.md +227 -227
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-01-introduction.md +222 -222
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-02-quick-start.md +351 -351
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-03-schema-validation.md +569 -569
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-04-mapping-patterns.md +471 -471
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-05-configuration-reference.md +611 -611
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-advanced-xpath.md +148 -148
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-path-syntax.md +464 -464
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-api-reference.md +94 -94
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-array-handling.md +307 -307
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-08-custom-resolvers.md +544 -544
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-09-advanced-patterns.md +427 -427
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-10-hooks-and-variables.md +336 -336
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-11-error-handling.md +488 -488
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-12-arguments-vs-nodes.md +383 -383
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-13-best-practices.md +477 -477
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/readme.md +62 -62
- package/docs/02-CORE-GUIDES/mapping/mapping-format-decision-tree.md +480 -480
- package/docs/02-CORE-GUIDES/mapping/mapping-graphql-alias-batching-guide.md +820 -820
- package/docs/02-CORE-GUIDES/mapping/mapping-javascript-objects.md +2369 -2369
- package/docs/02-CORE-GUIDES/mapping/mapping-mapper-comparison-guide.md +682 -682
- package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-07-api-reference.md +1327 -1327
- package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-08-error-handling.md +1142 -1142
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-04-use-cases.md +891 -891
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-helpers-resolvers.md +1126 -1126
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-sdk-resolvers.md +199 -199
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-07-api-reference.md +1319 -1319
- package/docs/02-CORE-GUIDES/mapping/readme.md +178 -178
- package/docs/02-CORE-GUIDES/mapping/resolver-registration.md +410 -410
- package/docs/02-CORE-GUIDES/mapping/resolvers/examples/common-patterns.ts +226 -226
- package/docs/02-CORE-GUIDES/mapping/resolvers/examples/custom-resolvers.ts +227 -227
- package/docs/02-CORE-GUIDES/mapping/resolvers/examples/sdk-resolvers-usage.ts +203 -203
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-readme.md +274 -274
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-api-reference.md +679 -679
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-cookbook.md +826 -826
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-guide.md +1330 -1330
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-helpers-reference.md +1437 -1437
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-parameters-reference.md +553 -553
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-troubleshooting.md +854 -854
- package/docs/02-CORE-GUIDES/mapping/resolvers/readme.md +75 -75
- package/docs/02-CORE-GUIDES/parsers/examples/02-core-guides-parsers-readme.md +161 -161
- package/docs/02-CORE-GUIDES/parsers/examples/csv-parser-examples.ts +110 -110
- package/docs/02-CORE-GUIDES/parsers/examples/json-parser-examples.ts +33 -33
- package/docs/02-CORE-GUIDES/parsers/examples/parquet-parser-examples.ts +47 -47
- package/docs/02-CORE-GUIDES/parsers/examples/xml-parser-examples.ts +38 -38
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-01-foundations.md +355 -355
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-02-csv-parser.md +772 -772
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-03-json-parser.md +789 -789
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-04-xml-parser.md +857 -857
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-05-parquet-parser.md +603 -603
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-integration-patterns.md +702 -702
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-streaming.md +121 -121
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-api-reference.md +89 -89
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-troubleshooting.md +727 -727
- package/docs/02-CORE-GUIDES/parsers/parsers-quick-reference.md +482 -482
- package/docs/02-CORE-GUIDES/parsers/parsers-readme.md +258 -258
- package/docs/02-CORE-GUIDES/parsers/readme.md +65 -65
- package/docs/02-CORE-GUIDES/readme.md +194 -194
- package/docs/02-CORE-GUIDES/webhook-validation/examples/basic-validation.ts +108 -108
- package/docs/02-CORE-GUIDES/webhook-validation/examples/common-patterns.ts +316 -316
- package/docs/02-CORE-GUIDES/webhook-validation/examples/webhook-validation-readme.md +61 -61
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-01-foundations.md +440 -440
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-02-quick-start.md +525 -525
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-03-versori-integration.md +741 -741
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-04-platform-integration.md +629 -629
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-05-configuration.md +535 -535
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-error-handling.md +611 -611
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-troubleshooting.md +124 -124
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-07-api-reference.md +511 -511
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-08-rubix-webhooks.md +590 -590
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-09-rubix-event-vs-http-call.md +432 -432
- package/docs/02-CORE-GUIDES/webhook-validation/readme.md +239 -239
- package/docs/02-CORE-GUIDES/webhook-validation/webhook-validation-quick-reference.md +392 -392
- package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-quick-reference.md +498 -498
- package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-readme.md +313 -313
- package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/common-patterns.ts +612 -612
- package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/connector-scenarios-readme.md +253 -253
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-01-foundations.md +452 -452
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-02-simple-scenarios.md +681 -681
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-03-intermediate-scenarios.md +637 -637
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-04-advanced-scenarios.md +650 -650
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-05-bidirectional-sync.md +233 -233
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-06-production-patterns.md +442 -442
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-07-reference.md +445 -445
- package/docs/03-PATTERN-GUIDES/connector-scenarios/readme.md +31 -31
- package/docs/03-PATTERN-GUIDES/enterprise-integration-patterns.md +1528 -1528
- package/docs/03-PATTERN-GUIDES/error-handling/comprehensive-error-handling-guide.md +1437 -1437
- package/docs/03-PATTERN-GUIDES/error-handling/error-handling-quick-reference.md +390 -390
- package/docs/03-PATTERN-GUIDES/error-handling/examples/common-patterns.ts +438 -438
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-01-foundations.md +362 -362
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-02-error-types.md +850 -850
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-03-utf8-handling.md +456 -456
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-04-error-scenarios.md +658 -658
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-05-calling-patterns.md +671 -671
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-06-retry-strategies.md +1034 -1034
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-07-monitoring.md +653 -653
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-08-api-reference.md +847 -847
- package/docs/03-PATTERN-GUIDES/error-handling/readme.md +36 -36
- package/docs/03-PATTERN-GUIDES/examples/__tests__/readme.md +40 -40
- package/docs/03-PATTERN-GUIDES/examples/__tests__/resolver-examples.test.js +282 -282
- package/docs/03-PATTERN-GUIDES/examples/test-data/03-pattern-guides-readme.md +110 -110
- package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-inventory.json +123 -123
- package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-order.json +171 -171
- package/docs/03-PATTERN-GUIDES/examples/test-data/readme.md +28 -28
- package/docs/03-PATTERN-GUIDES/extraction/extraction-readme.md +15 -15
- package/docs/03-PATTERN-GUIDES/extraction/readme.md +25 -25
- package/docs/03-PATTERN-GUIDES/file-operations/examples/common-patterns.ts +407 -407
- package/docs/03-PATTERN-GUIDES/file-operations/examples/file-operations-readme.md +142 -142
- package/docs/03-PATTERN-GUIDES/file-operations/file-operations-quick-reference.md +462 -462
- package/docs/03-PATTERN-GUIDES/file-operations/file-operations-readme.md +379 -379
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-01-foundations.md +430 -430
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-02-quick-start.md +484 -484
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-03-s3-operations.md +507 -507
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-04-sftp-operations.md +963 -963
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-05-streaming-performance.md +503 -503
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-archive-patterns.md +386 -386
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-error-handling.md +117 -117
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-api-reference.md +78 -78
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-testing-troubleshooting.md +567 -567
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-08-api-reference.md +1055 -1055
- package/docs/03-PATTERN-GUIDES/file-operations/readme.md +32 -32
- package/docs/03-PATTERN-GUIDES/ingestion/ingestion-readme.md +15 -15
- package/docs/03-PATTERN-GUIDES/ingestion/readme.md +25 -25
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/batch-processing.ts +130 -130
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/common-patterns.ts +360 -360
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/delta-sync.ts +130 -130
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/integration-patterns-readme.md +100 -100
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/real-time-webhook.ts +398 -398
- package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-quick-reference.md +962 -962
- package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-readme.md +134 -134
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-01-real-time-processing.md +991 -991
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-02-batch-processing.md +1547 -1547
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-03-delta-sync.md +1108 -1108
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-04-webhook-patterns.md +1181 -1181
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-05-error-handling.md +1061 -1061
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-advanced-integration-services.md +1547 -1547
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-performance.md +109 -109
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-07-api-reference.md +34 -34
- package/docs/03-PATTERN-GUIDES/integration-patterns/readme.md +30 -30
- package/docs/03-PATTERN-GUIDES/logging-minimal-mode.md +128 -128
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/common-patterns.ts +380 -380
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/multiple-connections-readme.md +139 -139
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/parallel-root-connections.ts +149 -149
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/real-world-scenarios.ts +405 -405
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-01-foundations.md +378 -378
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-02-quick-start.md +566 -566
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-03-targeting-connections.md +659 -659
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-04-parallel-queries.md +656 -656
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-05-best-practices.md +624 -624
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-api-reference.md +824 -824
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-versori.md +119 -119
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-07-api-reference.md +87 -87
- package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-quick-reference.md +353 -353
- package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-readme.md +270 -270
- package/docs/03-PATTERN-GUIDES/multiple-connections/readme.md +30 -30
- package/docs/03-PATTERN-GUIDES/pagination/pagination-readme.md +14 -14
- package/docs/03-PATTERN-GUIDES/pagination/readme.md +24 -24
- package/docs/03-PATTERN-GUIDES/parquet/examples/common-patterns.ts +180 -180
- package/docs/03-PATTERN-GUIDES/parquet/examples/read-parquet.ts +48 -48
- package/docs/03-PATTERN-GUIDES/parquet/examples/write-parquet.ts +65 -65
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-01-introduction.md +393 -393
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-02-quick-start.md +572 -572
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-03-reading-parquet.md +525 -525
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-04-writing-parquet.md +554 -554
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-05-graphql-extraction.md +405 -405
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-performance.md +104 -104
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-s3-integration.md +511 -511
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-api-reference.md +90 -90
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-performance-optimization.md +525 -525
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-08-best-practices.md +712 -712
- package/docs/03-PATTERN-GUIDES/parquet/parquet-quick-reference.md +683 -683
- package/docs/03-PATTERN-GUIDES/parquet/parquet-readme.md +248 -248
- package/docs/03-PATTERN-GUIDES/parquet/readme.md +32 -32
- package/docs/03-PATTERN-GUIDES/parsers/parsers-readme.md +12 -12
- package/docs/03-PATTERN-GUIDES/parsers/readme.md +24 -24
- package/docs/03-PATTERN-GUIDES/readme.md +159 -159
- package/docs/03-PATTERN-GUIDES/webhooks/readme.md +24 -24
- package/docs/03-PATTERN-GUIDES/webhooks/webhooks-readme.md +8 -8
- package/docs/04-REFERENCE/architecture/architecture-01-overview.md +427 -427
- package/docs/04-REFERENCE/architecture/architecture-02-client-architecture.md +424 -424
- package/docs/04-REFERENCE/architecture/architecture-03-data-flow.md +690 -690
- package/docs/04-REFERENCE/architecture/architecture-04-service-layer.md +834 -834
- package/docs/04-REFERENCE/architecture/architecture-05-integration-architecture.md +655 -655
- package/docs/04-REFERENCE/architecture/architecture-06-state-management.md +653 -653
- package/docs/04-REFERENCE/architecture/architecture-adding-new-data-sources.md +686 -686
- package/docs/04-REFERENCE/architecture/readme.md +279 -279
- package/docs/04-REFERENCE/platforms/deno/readme.md +117 -117
- package/docs/04-REFERENCE/platforms/nodejs/readme.md +146 -146
- package/docs/04-REFERENCE/platforms/readme.md +135 -135
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-01-introduction.md +398 -398
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-02-quick-start.md +560 -560
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-03-authentication.md +757 -757
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-04-workflows.md +2476 -2476
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-05-connections.md +1167 -1167
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-kv-storage.md +990 -990
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-state-management.md +121 -121
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-api-reference.md +68 -68
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-deployment.md +731 -731
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-08-best-practices.md +1111 -1111
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-09-signature-reference.md +766 -766
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-readme.md +299 -299
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-s3-sftp-configuration-guide.md +1425 -1425
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-api-key-security.md +816 -816
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-connection-security.md +681 -681
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-workflow-task-types.md +708 -708
- package/docs/04-REFERENCE/platforms/versori/readme.md +108 -108
- package/docs/04-REFERENCE/readme.md +148 -148
- package/docs/04-REFERENCE/resolver-signature/examples/advanced-resolvers.ts +482 -482
- package/docs/04-REFERENCE/resolver-signature/examples/async-resolvers.ts +496 -496
- package/docs/04-REFERENCE/resolver-signature/examples/basic-resolvers.ts +343 -343
- package/docs/04-REFERENCE/resolver-signature/examples/resolver-signature-readme.md +188 -188
- package/docs/04-REFERENCE/resolver-signature/examples/testing-resolvers.ts +463 -463
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-01-foundations.md +286 -286
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-02-parameter-reference.md +643 -643
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-03-basic-examples.md +521 -521
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-04-advanced-patterns.md +739 -739
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-05-sdk-resolvers.md +531 -531
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-migration-guide.md +650 -650
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-testing.md +125 -125
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-07-api-reference.md +794 -794
- package/docs/04-REFERENCE/resolver-signature/readme.md +64 -64
- package/docs/04-REFERENCE/resolver-signature/resolver-signature-quick-reference.md +270 -270
- package/docs/04-REFERENCE/resolver-signature/resolver-signature-readme.md +351 -351
- package/docs/04-REFERENCE/schema/fluent-commerce-schema.json +764 -764
- package/docs/04-REFERENCE/schema/readme.md +141 -141
- package/docs/04-REFERENCE/testing/examples/04-reference-testing-readme.md +158 -158
- package/docs/04-REFERENCE/testing/examples/fluent-testing.ts +62 -62
- package/docs/04-REFERENCE/testing/examples/health-check.ts +155 -155
- package/docs/04-REFERENCE/testing/examples/integration-test.ts +119 -119
- package/docs/04-REFERENCE/testing/examples/performance-test.ts +183 -183
- package/docs/04-REFERENCE/testing/examples/s3-testing.ts +127 -127
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-01-foundations.md +267 -267
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-02-s3-testing.md +599 -599
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-03-fluent-testing.md +589 -589
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-04-integration-testing.md +699 -699
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-05-debugging.md +478 -478
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-cicd-integration.md +463 -463
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-preflight-validation.md +131 -131
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-best-practices.md +499 -499
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-coverage-ci.md +165 -165
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-08-api-reference.md +634 -634
- package/docs/04-REFERENCE/testing/readme.md +86 -86
- package/docs/04-REFERENCE/testing/testing-quick-reference.md +667 -667
- package/docs/04-REFERENCE/testing/testing-readme.md +286 -286
- package/docs/04-REFERENCE/troubleshooting/readme.md +144 -144
- package/docs/04-REFERENCE/troubleshooting/troubleshooting-deno-sftp-compatibility.md +392 -392
- package/docs/template-loading-matrix.md +242 -242
- package/package.json +5 -3
- package/docs/02-CORE-GUIDES/api-reference/cli-profile-integration.md +0 -377
|
@@ -1,763 +1,763 @@
|
|
|
1
|
-
# Module 4: Field Mapping
|
|
2
|
-
|
|
3
|
-
**Level:** Intermediate
|
|
4
|
-
**Estimated Time:** 25 minutes
|
|
5
|
-
|
|
6
|
-
## Overview
|
|
7
|
-
|
|
8
|
-
This module teaches you how to transform source data (CSV, Parquet, JSON) into the exact format required by Fluent Commerce's Batch API using the UniversalMapper service with schema-validated field mappings.
|
|
9
|
-
|
|
10
|
-
## Learning Objectives
|
|
11
|
-
|
|
12
|
-
By the end of this module, you will:
|
|
13
|
-
- ✅ Understand InventoryPositionInput schema requirements
|
|
14
|
-
- ✅ Configure UniversalMapper with field mappings
|
|
15
|
-
- ✅ Use SDK resolvers for data transformation
|
|
16
|
-
- ✅ Create custom resolvers for business logic
|
|
17
|
-
- ✅ Validate mappings against GraphQL schema
|
|
18
|
-
- ✅ Handle mapping errors gracefully
|
|
19
|
-
|
|
20
|
-
## Inventory Position Schema
|
|
21
|
-
|
|
22
|
-
### Required Fields
|
|
23
|
-
|
|
24
|
-
The Batch API requires specific fields for `InventoryPositionInput`:
|
|
25
|
-
|
|
26
|
-
```typescript
|
|
27
|
-
{
|
|
28
|
-
"ref": "SKU-WM-001", // String! - Position reference (required)
|
|
29
|
-
"productRef": "SKU-WM-001", // String! - Product SKU (required)
|
|
30
|
-
"locationRef": "WH-001", // String! - Warehouse code (required)
|
|
31
|
-
"qty": 500 // Int! - Available quantity (required)
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Optional Fields
|
|
36
|
-
|
|
37
|
-
```typescript
|
|
38
|
-
{
|
|
39
|
-
"status": "AVAILABLE", // String - Position status
|
|
40
|
-
"type": "ADJUSTMENT" // String - Position type
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Valid Status Values
|
|
45
|
-
|
|
46
|
-
| Status | Description |
|
|
47
|
-
|--------|-------------|
|
|
48
|
-
| `AVAILABLE` | Stock available for sale |
|
|
49
|
-
| `RESERVED` | Stock reserved for orders |
|
|
50
|
-
| `ON_HOLD` | Stock on hold (damaged, quarantine, etc.) |
|
|
51
|
-
| `DISCONTINUED` | Product no longer carried |
|
|
52
|
-
|
|
53
|
-
## UniversalMapper Basics
|
|
54
|
-
|
|
55
|
-
### Simple Mapping
|
|
56
|
-
|
|
57
|
-
```typescript
|
|
58
|
-
import { UniversalMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
59
|
-
|
|
60
|
-
const mapper = new UniversalMapper({
|
|
61
|
-
fields: {
|
|
62
|
-
// Map source field to target field
|
|
63
|
-
ref: {
|
|
64
|
-
source: 'sku', // Source CSV column
|
|
65
|
-
required: true // Must be present
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
productRef: {
|
|
69
|
-
source: 'sku',
|
|
70
|
-
required: true
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
locationRef: {
|
|
74
|
-
source: 'warehouse',
|
|
75
|
-
required: true
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
qty: {
|
|
79
|
-
source: 'quantity',
|
|
80
|
-
resolver: 'sdk.parseInt', // Convert to integer
|
|
81
|
-
required: true
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
// Transform CSV data
|
|
87
|
-
const csvData = [
|
|
88
|
-
{ sku: 'SKU-001', warehouse: 'WH-001', quantity: '500' }
|
|
89
|
-
];
|
|
90
|
-
|
|
91
|
-
const result = await mapper.map(csvData);
|
|
92
|
-
|
|
93
|
-
if (result.success) {
|
|
94
|
-
console.log(result.data);
|
|
95
|
-
// [{
|
|
96
|
-
// ref: 'SKU-001',
|
|
97
|
-
// productRef: 'SKU-001',
|
|
98
|
-
// locationRef: 'WH-001',
|
|
99
|
-
// qty: 500
|
|
100
|
-
// }]
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### Mapping Result
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
interface MappingResult {
|
|
108
|
-
success: boolean;
|
|
109
|
-
data: any[]; // Mapped records (if success)
|
|
110
|
-
errors?: string[]; // Validation errors (if failed)
|
|
111
|
-
skippedFields?: string[]; // Fields that were skipped because they were undefined (field names only)
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## SDK Resolvers
|
|
116
|
-
|
|
117
|
-
The SDK provides built-in resolvers for common transformations:
|
|
118
|
-
|
|
119
|
-
### String Resolvers
|
|
120
|
-
|
|
121
|
-
```typescript
|
|
122
|
-
const mapping = {
|
|
123
|
-
fields: {
|
|
124
|
-
ref: {
|
|
125
|
-
source: 'sku',
|
|
126
|
-
resolver: 'sdk.uppercase' // Convert to UPPERCASE
|
|
127
|
-
},
|
|
128
|
-
|
|
129
|
-
status: {
|
|
130
|
-
source: 'status',
|
|
131
|
-
resolver: 'sdk.lowercase' // Convert to lowercase
|
|
132
|
-
},
|
|
133
|
-
|
|
134
|
-
locationRef: {
|
|
135
|
-
source: ' warehouse ',
|
|
136
|
-
resolver: 'sdk.trim' // Remove whitespace
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### Number Resolvers
|
|
143
|
-
|
|
144
|
-
```typescript
|
|
145
|
-
const mapping = {
|
|
146
|
-
fields: {
|
|
147
|
-
qty: {
|
|
148
|
-
source: 'quantity',
|
|
149
|
-
resolver: 'sdk.parseInt' // String → Int
|
|
150
|
-
},
|
|
151
|
-
|
|
152
|
-
price: {
|
|
153
|
-
source: 'cost',
|
|
154
|
-
resolver: 'sdk.parseFloat' // String → Float
|
|
155
|
-
},
|
|
156
|
-
|
|
157
|
-
count: {
|
|
158
|
-
source: 'total',
|
|
159
|
-
resolver: 'sdk.number' // Force to number
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### Date Resolvers
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
const mapping = {
|
|
169
|
-
fields: {
|
|
170
|
-
expectedOn: {
|
|
171
|
-
source: 'ship_date',
|
|
172
|
-
resolver: 'sdk.formatDate' // Format as ISO date
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
lastUpdated: {
|
|
176
|
-
source: 'updated',
|
|
177
|
-
resolver: 'sdk.formatDateShort' // Format as YYYY-MM-DD
|
|
178
|
-
},
|
|
179
|
-
|
|
180
|
-
createdAt: {
|
|
181
|
-
source: 'created_timestamp',
|
|
182
|
-
resolver: 'sdk.parseDate' // Parse various date formats
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
### Utility Resolvers
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
const mapping = {
|
|
192
|
-
fields: {
|
|
193
|
-
isActive: {
|
|
194
|
-
source: 'active',
|
|
195
|
-
resolver: 'sdk.boolean' // Convert to boolean
|
|
196
|
-
},
|
|
197
|
-
|
|
198
|
-
metadata: {
|
|
199
|
-
source: 'meta_json',
|
|
200
|
-
resolver: 'sdk.parseJson' // Parse JSON string
|
|
201
|
-
},
|
|
202
|
-
|
|
203
|
-
config: {
|
|
204
|
-
source: 'settings',
|
|
205
|
-
resolver: 'sdk.toJson' // Convert to JSON string
|
|
206
|
-
},
|
|
207
|
-
|
|
208
|
-
value: {
|
|
209
|
-
source: 'original',
|
|
210
|
-
resolver: 'sdk.identity' // Pass through unchanged
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
## Custom Resolvers
|
|
217
|
-
|
|
218
|
-
### Basic Custom Resolver
|
|
219
|
-
|
|
220
|
-
```typescript
|
|
221
|
-
const mapper = new UniversalMapper(mappingConfig, {
|
|
222
|
-
customResolvers: {
|
|
223
|
-
'custom.mapStatus': (value, sourceData, config, helpers) => {
|
|
224
|
-
const statusMap = {
|
|
225
|
-
'in_stock': 'AVAILABLE',
|
|
226
|
-
'out_of_stock': 'ON_HOLD',
|
|
227
|
-
'discontinued': 'DISCONTINUED',
|
|
228
|
-
'reserved': 'RESERVED'
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
const mapped = statusMap[String(value).toLowerCase()];
|
|
232
|
-
|
|
233
|
-
if (!mapped) {
|
|
234
|
-
throw new Error(`Unknown status: ${value}`);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return mapped;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
### Resolver with Helper Functions
|
|
244
|
-
|
|
245
|
-
```typescript
|
|
246
|
-
const customResolvers = {
|
|
247
|
-
'custom.calculateQty': (value, sourceData, config, helpers) => {
|
|
248
|
-
// Use helper functions for safe conversions
|
|
249
|
-
const onHand = helpers.parseIntSafe(sourceData.on_hand, 0);
|
|
250
|
-
const reserved = helpers.parseIntSafe(sourceData.reserved, 0);
|
|
251
|
-
|
|
252
|
-
return onHand - reserved;
|
|
253
|
-
},
|
|
254
|
-
|
|
255
|
-
'custom.formatLocation': (value, sourceData, config, helpers) => {
|
|
256
|
-
// Combine multiple source fields
|
|
257
|
-
const region = helpers.toString(sourceData.region);
|
|
258
|
-
const warehouse = helpers.toString(sourceData.warehouse);
|
|
259
|
-
|
|
260
|
-
return `${region}-${warehouse}`;
|
|
261
|
-
}
|
|
262
|
-
};
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
### Validation Resolver
|
|
266
|
-
|
|
267
|
-
```typescript
|
|
268
|
-
const customResolvers = {
|
|
269
|
-
'custom.validateSKU': (value, sourceData, config, helpers) => {
|
|
270
|
-
const sku = helpers.toString(value).trim();
|
|
271
|
-
|
|
272
|
-
// Must be alphanumeric and at least 3 characters
|
|
273
|
-
if (!/^[A-Z0-9-]{3,}$/i.test(sku)) {
|
|
274
|
-
throw new Error(`Invalid SKU format: ${sku}`);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
return sku.toUpperCase();
|
|
278
|
-
},
|
|
279
|
-
|
|
280
|
-
'custom.ensurePositiveQty': (value, sourceData, config, helpers) => {
|
|
281
|
-
const qty = helpers.parseIntSafe(value, 0);
|
|
282
|
-
|
|
283
|
-
if (qty < 0) {
|
|
284
|
-
throw new Error(`Negative quantity not allowed: ${qty}`);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return qty;
|
|
288
|
-
}
|
|
289
|
-
};
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
## Required Fields with Resolvers
|
|
293
|
-
|
|
294
|
-
When using `required: true` with resolvers, understand how validation timing works:
|
|
295
|
-
|
|
296
|
-
**Fields with `source`**: Validation happens **before** resolver execution
|
|
297
|
-
```json
|
|
298
|
-
{
|
|
299
|
-
"qty": {
|
|
300
|
-
"source": "quantity",
|
|
301
|
-
"resolver": "sdk.parseInt",
|
|
302
|
-
"required": true
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
```
|
|
306
|
-
- ✅ Checks if `quantity` exists in source data first
|
|
307
|
-
- ✅ If missing → mapping fails immediately (resolver never runs)
|
|
308
|
-
- ✅ If present → resolver runs to transform the value
|
|
309
|
-
|
|
310
|
-
**Resolver-only fields** (no `source`): Validation happens **after** resolver execution
|
|
311
|
-
```json
|
|
312
|
-
{
|
|
313
|
-
"metadata.uuid": {
|
|
314
|
-
"resolver": "custom.generateUUID",
|
|
315
|
-
"required": true
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
```
|
|
319
|
-
- ✅ Resolver runs first to generate value
|
|
320
|
-
- ✅ Then validates that resolver produced a value
|
|
321
|
-
- ✅ If resolver returns `null`, `undefined`, or empty string → mapping fails
|
|
322
|
-
|
|
323
|
-
**Important:** Resolvers can return empty values. `required: true` ensures validation happens **after** the resolver runs to catch these cases. If your resolver has conditional logic that might return `undefined`, use `required: true` to ensure the field always has a value.
|
|
324
|
-
|
|
325
|
-
**Example: Conditional Resolver**
|
|
326
|
-
|
|
327
|
-
```typescript
|
|
328
|
-
const customResolvers = {
|
|
329
|
-
'custom.calculateDiscount': (value, sourceData, config, helpers) => {
|
|
330
|
-
const customerTier = helpers.get(sourceData, 'customer.tier');
|
|
331
|
-
|
|
332
|
-
// ⚠️ Can return undefined for BASIC tier!
|
|
333
|
-
if (customerTier === 'PREMIUM') {
|
|
334
|
-
return helpers.parseFloatSafe(value, 0) * 0.2;
|
|
335
|
-
} else if (customerTier === 'STANDARD') {
|
|
336
|
-
return helpers.parseFloatSafe(value, 0) * 0.1;
|
|
337
|
-
}
|
|
338
|
-
return undefined; // ❌ Returns undefined
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
// Mapping config
|
|
343
|
-
{
|
|
344
|
-
"fields": {
|
|
345
|
-
"discount": {
|
|
346
|
-
"source": "order.subtotal",
|
|
347
|
-
"resolver": "custom.calculateDiscount",
|
|
348
|
-
"required": true // ✅ Ensures discount is always calculated
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
Without `required: true`:
|
|
355
|
-
- Resolver returns `undefined` for BASIC tier → mapping succeeds → API call fails
|
|
356
|
-
|
|
357
|
-
With `required: true`:
|
|
358
|
-
- Resolver returns `undefined` → mapping fails immediately → No API call (saves quota)
|
|
359
|
-
|
|
360
|
-
## Complete Mapping Example
|
|
361
|
-
|
|
362
|
-
```typescript
|
|
363
|
-
import { UniversalMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
364
|
-
|
|
365
|
-
// Schema-validated mapping configuration
|
|
366
|
-
const mappingConfig = {
|
|
367
|
-
fields: {
|
|
368
|
-
// Required fields
|
|
369
|
-
ref: {
|
|
370
|
-
source: 'sku',
|
|
371
|
-
resolver: 'custom.validateSKU',
|
|
372
|
-
required: true,
|
|
373
|
-
comment: '✅ InventoryPositionInput.ref (String! required)'
|
|
374
|
-
},
|
|
375
|
-
|
|
376
|
-
productRef: {
|
|
377
|
-
source: 'sku',
|
|
378
|
-
resolver: 'custom.validateSKU',
|
|
379
|
-
required: true,
|
|
380
|
-
comment: '✅ InventoryPositionInput.productRef (String! required)'
|
|
381
|
-
},
|
|
382
|
-
|
|
383
|
-
locationRef: {
|
|
384
|
-
source: 'warehouse',
|
|
385
|
-
resolver: 'sdk.trim',
|
|
386
|
-
required: true,
|
|
387
|
-
comment: '✅ InventoryPositionInput.locationRef (String! required)'
|
|
388
|
-
},
|
|
389
|
-
|
|
390
|
-
qty: {
|
|
391
|
-
source: 'quantity',
|
|
392
|
-
resolver: 'custom.ensurePositiveQty',
|
|
393
|
-
required: true,
|
|
394
|
-
comment: '✅ InventoryPositionInput.qty (Int! required)'
|
|
395
|
-
},
|
|
396
|
-
|
|
397
|
-
// Optional fields with defaults
|
|
398
|
-
status: {
|
|
399
|
-
source: 'status',
|
|
400
|
-
resolver: 'custom.mapStatus',
|
|
401
|
-
defaultValue: 'AVAILABLE',
|
|
402
|
-
comment: '✅ InventoryPositionInput.status (String optional)'
|
|
403
|
-
},
|
|
404
|
-
|
|
405
|
-
type: {
|
|
406
|
-
value: 'ADJUSTMENT', // Static value for all records
|
|
407
|
-
comment: '✅ InventoryPositionInput.type (String optional)'
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
};
|
|
411
|
-
|
|
412
|
-
// Custom resolvers for business logic
|
|
413
|
-
const customResolvers = {
|
|
414
|
-
'custom.validateSKU': (value, sourceData, config, helpers) => {
|
|
415
|
-
const sku = helpers.toString(value).trim().toUpperCase();
|
|
416
|
-
|
|
417
|
-
if (!/^[A-Z0-9-]{3,}$/.test(sku)) {
|
|
418
|
-
throw new Error(`Invalid SKU: ${sku}`);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
return sku;
|
|
422
|
-
},
|
|
423
|
-
|
|
424
|
-
'custom.ensurePositiveQty': (value, sourceData, config, helpers) => {
|
|
425
|
-
const qty = helpers.parseIntSafe(value, 0);
|
|
426
|
-
|
|
427
|
-
if (qty < 0) {
|
|
428
|
-
throw new Error(`Negative quantity: ${qty}`);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
return qty;
|
|
432
|
-
},
|
|
433
|
-
|
|
434
|
-
'custom.mapStatus': (value, sourceData, config, helpers) => {
|
|
435
|
-
const statusMap = {
|
|
436
|
-
'in_stock': 'AVAILABLE',
|
|
437
|
-
'out_of_stock': 'ON_HOLD',
|
|
438
|
-
'discontinued': 'DISCONTINUED',
|
|
439
|
-
'reserved': 'RESERVED'
|
|
440
|
-
};
|
|
441
|
-
|
|
442
|
-
const status = helpers.toString(value).toLowerCase();
|
|
443
|
-
const mapped = statusMap[status];
|
|
444
|
-
|
|
445
|
-
if (!mapped) {
|
|
446
|
-
throw new Error(`Unknown status: ${value}`);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
return mapped;
|
|
450
|
-
}
|
|
451
|
-
};
|
|
452
|
-
|
|
453
|
-
// Create mapper with custom resolvers
|
|
454
|
-
const mapper = new UniversalMapper(mappingConfig, { customResolvers });
|
|
455
|
-
|
|
456
|
-
// Map CSV data
|
|
457
|
-
const csvData = [
|
|
458
|
-
{ sku: 'sku-wm-001', warehouse: 'WH-001', quantity: '500', status: 'in_stock' },
|
|
459
|
-
{ sku: 'sku-wm-002', warehouse: 'WH-001', quantity: '150', status: 'reserved' }
|
|
460
|
-
];
|
|
461
|
-
|
|
462
|
-
const result = await mapper.map(csvData);
|
|
463
|
-
|
|
464
|
-
if (!result.success) {
|
|
465
|
-
console.error('Mapping errors:', result.errors);
|
|
466
|
-
process.exit(1);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
console.log('Mapped records:', result.data);
|
|
470
|
-
// [
|
|
471
|
-
// { ref: 'SKU-WM-001', productRef: 'SKU-WM-001', locationRef: 'WH-001', qty: 500, status: 'AVAILABLE', type: 'ADJUSTMENT' },
|
|
472
|
-
// { ref: 'SKU-WM-002', productRef: 'SKU-WM-002', locationRef: 'WH-001', qty: 150, status: 'RESERVED', type: 'ADJUSTMENT' }
|
|
473
|
-
// ]
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
## Schema Validation
|
|
477
|
-
|
|
478
|
-
### Validate Before Deployment
|
|
479
|
-
|
|
480
|
-
```bash
|
|
481
|
-
# Step 1: Introspect your Fluent Commerce schema
|
|
482
|
-
npx @fluentcommerce/fc-connect-sdk introspect-schema \
|
|
483
|
-
--url https://YOUR_ACCOUNT.api.fluentcommerce.com/graphql \
|
|
484
|
-
--output schema.json
|
|
485
|
-
|
|
486
|
-
# Step 2: Save your mapping configuration
|
|
487
|
-
cat > field-mappings.json << 'EOF'
|
|
488
|
-
{
|
|
489
|
-
"fields": {
|
|
490
|
-
"ref": { "source": "sku", "required": true },
|
|
491
|
-
"productRef": { "source": "sku", "required": true },
|
|
492
|
-
"locationRef": { "source": "warehouse", "required": true },
|
|
493
|
-
"qty": { "source": "quantity", "resolver": "sdk.parseInt", "required": true },
|
|
494
|
-
"status": { "source": "status", "resolver": "custom.mapStatus", "defaultValue": "AVAILABLE" }
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
EOF
|
|
498
|
-
|
|
499
|
-
# Step 3: Validate mapping against schema
|
|
500
|
-
npx @fluentcommerce/fc-connect-sdk validate-schema \
|
|
501
|
-
--mapping field-mappings.json \
|
|
502
|
-
--schema schema.json
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
### Expected Output
|
|
506
|
-
|
|
507
|
-
```
|
|
508
|
-
✅ Mapping validation successful
|
|
509
|
-
✅ All required fields present: ref, productRef, locationRef, qty
|
|
510
|
-
✅ All field types compatible with InventoryPositionInput schema
|
|
511
|
-
✅ No unknown fields detected
|
|
512
|
-
|
|
513
|
-
Validation Summary:
|
|
514
|
-
Required fields: 4/4 ✓
|
|
515
|
-
Optional fields: 1
|
|
516
|
-
Custom resolvers: 1 (custom.mapStatus)
|
|
517
|
-
SDK resolvers: 1 (sdk.parseInt)
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
## Error Handling
|
|
521
|
-
|
|
522
|
-
### Mapping Errors
|
|
523
|
-
|
|
524
|
-
```typescript
|
|
525
|
-
const result = await mapper.map(csvData);
|
|
526
|
-
|
|
527
|
-
if (!result.success) {
|
|
528
|
-
// Log all errors
|
|
529
|
-
console.error('Mapping failed with errors:');
|
|
530
|
-
result.errors.forEach((error, index) => {
|
|
531
|
-
console.error(` ${index + 1}. ${error}`);
|
|
532
|
-
});
|
|
533
|
-
|
|
534
|
-
// Optionally: Write failed records to error file
|
|
535
|
-
const errorReport = {
|
|
536
|
-
timestamp: new Date().toISOString(),
|
|
537
|
-
totalRecords: csvData.length,
|
|
538
|
-
errors: result.errors,
|
|
539
|
-
failedRecords: csvData.filter((_, i) => result.errors.some(e => e.includes(`Row ${i}`)))
|
|
540
|
-
};
|
|
541
|
-
|
|
542
|
-
await fs.writeFile('mapping-errors.json', JSON.stringify(errorReport, null, 2));
|
|
543
|
-
|
|
544
|
-
throw new Error(`Mapping failed: ${result.errors.length} errors`);
|
|
545
|
-
}
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
### Partial Success Handling
|
|
549
|
-
|
|
550
|
-
```typescript
|
|
551
|
-
async function mapWithPartialSuccess(mapper: UniversalMapper, records: any[]) {
|
|
552
|
-
const successful = [];
|
|
553
|
-
const failed = [];
|
|
554
|
-
|
|
555
|
-
for (const [index, record] of records.entries()) {
|
|
556
|
-
try {
|
|
557
|
-
const result = await mapper.map([record]);
|
|
558
|
-
|
|
559
|
-
if (result.success) {
|
|
560
|
-
successful.push(result.data[0]);
|
|
561
|
-
} else {
|
|
562
|
-
failed.push({ record, errors: result.errors });
|
|
563
|
-
}
|
|
564
|
-
} catch (error) {
|
|
565
|
-
failed.push({ record, error: error.message });
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
return {
|
|
570
|
-
successful,
|
|
571
|
-
failed,
|
|
572
|
-
successRate: successful.length / records.length
|
|
573
|
-
};
|
|
574
|
-
}
|
|
575
|
-
```
|
|
576
|
-
|
|
577
|
-
## Advanced Patterns
|
|
578
|
-
|
|
579
|
-
### Conditional Mapping
|
|
580
|
-
|
|
581
|
-
```typescript
|
|
582
|
-
const conditionalMapper = {
|
|
583
|
-
'custom.conditionalStatus': (value, sourceData, config, helpers) => {
|
|
584
|
-
const qty = helpers.parseIntSafe(sourceData.quantity, 0);
|
|
585
|
-
const status = helpers.toString(value).toLowerCase();
|
|
586
|
-
|
|
587
|
-
// Override status based on quantity
|
|
588
|
-
if (qty === 0) {
|
|
589
|
-
return 'ON_HOLD';
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
if (qty > 1000) {
|
|
593
|
-
return 'AVAILABLE';
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
// Use source status
|
|
597
|
-
return status === 'available' ? 'AVAILABLE' : 'RESERVED';
|
|
598
|
-
}
|
|
599
|
-
};
|
|
600
|
-
```
|
|
601
|
-
|
|
602
|
-
### Multi-Field Transformation
|
|
603
|
-
|
|
604
|
-
```typescript
|
|
605
|
-
const multiFieldMapper = {
|
|
606
|
-
'custom.generateRef': (value, sourceData, config, helpers) => {
|
|
607
|
-
const sku = helpers.toString(sourceData.sku).trim();
|
|
608
|
-
const location = helpers.toString(sourceData.warehouse).trim();
|
|
609
|
-
const date = new Date().toISOString().split('T')[0];
|
|
610
|
-
|
|
611
|
-
return `${sku}-${location}-${date}`;
|
|
612
|
-
}
|
|
613
|
-
};
|
|
614
|
-
```
|
|
615
|
-
|
|
616
|
-
### Lookup Table Resolver
|
|
617
|
-
|
|
618
|
-
```typescript
|
|
619
|
-
const lookupTables = {
|
|
620
|
-
warehouseCodes: {
|
|
621
|
-
'California DC': 'CA-001',
|
|
622
|
-
'Texas DC': 'TX-001',
|
|
623
|
-
'New York DC': 'NY-001'
|
|
624
|
-
}
|
|
625
|
-
};
|
|
626
|
-
|
|
627
|
-
const lookupResolver = {
|
|
628
|
-
'custom.lookupWarehouse': (value, sourceData, config, helpers) => {
|
|
629
|
-
const warehouseName = helpers.toString(value);
|
|
630
|
-
const code = lookupTables.warehouseCodes[warehouseName];
|
|
631
|
-
|
|
632
|
-
if (!code) {
|
|
633
|
-
throw new Error(`Unknown warehouse: ${warehouseName}`);
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
return code;
|
|
637
|
-
}
|
|
638
|
-
};
|
|
639
|
-
```
|
|
640
|
-
|
|
641
|
-
## Practice Exercise
|
|
642
|
-
|
|
643
|
-
Create a field mapping that:
|
|
644
|
-
1. Validates SKU format (alphanumeric, min 3 chars)
|
|
645
|
-
2. Maps status from custom values to Fluent values
|
|
646
|
-
3. Calculates available quantity (on_hand - reserved)
|
|
647
|
-
4. Generates a unique position reference
|
|
648
|
-
|
|
649
|
-
<details>
|
|
650
|
-
<summary>Click to see solution</summary>
|
|
651
|
-
|
|
652
|
-
```typescript
|
|
653
|
-
import { UniversalMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
654
|
-
|
|
655
|
-
const mappingConfig = {
|
|
656
|
-
fields: {
|
|
657
|
-
ref: {
|
|
658
|
-
source: 'sku',
|
|
659
|
-
resolver: 'custom.generatePositionRef',
|
|
660
|
-
required: true
|
|
661
|
-
},
|
|
662
|
-
productRef: {
|
|
663
|
-
source: 'sku',
|
|
664
|
-
resolver: 'custom.validateSKU',
|
|
665
|
-
required: true
|
|
666
|
-
},
|
|
667
|
-
locationRef: {
|
|
668
|
-
source: 'warehouse',
|
|
669
|
-
required: true
|
|
670
|
-
},
|
|
671
|
-
qty: {
|
|
672
|
-
source: 'on_hand',
|
|
673
|
-
resolver: 'custom.calculateAvailable',
|
|
674
|
-
required: true
|
|
675
|
-
},
|
|
676
|
-
status: {
|
|
677
|
-
source: 'stock_status',
|
|
678
|
-
resolver: 'custom.mapStockStatus',
|
|
679
|
-
defaultValue: 'AVAILABLE'
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
};
|
|
683
|
-
|
|
684
|
-
const customResolvers = {
|
|
685
|
-
'custom.validateSKU': (value, sourceData, config, helpers) => {
|
|
686
|
-
const sku = helpers.toString(value).trim().toUpperCase();
|
|
687
|
-
|
|
688
|
-
if (!/^[A-Z0-9]{3,}$/.test(sku)) {
|
|
689
|
-
throw new Error(`Invalid SKU format: ${value}`);
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
return sku;
|
|
693
|
-
},
|
|
694
|
-
|
|
695
|
-
'custom.generatePositionRef': (value, sourceData, config, helpers) => {
|
|
696
|
-
const sku = helpers.toString(value).trim().toUpperCase();
|
|
697
|
-
const warehouse = helpers.toString(sourceData.warehouse).trim();
|
|
698
|
-
|
|
699
|
-
return `${sku}-${warehouse}`;
|
|
700
|
-
},
|
|
701
|
-
|
|
702
|
-
'custom.calculateAvailable': (value, sourceData, config, helpers) => {
|
|
703
|
-
const onHand = helpers.parseIntSafe(value, 0);
|
|
704
|
-
const reserved = helpers.parseIntSafe(sourceData.reserved, 0);
|
|
705
|
-
|
|
706
|
-
return Math.max(0, onHand - reserved);
|
|
707
|
-
},
|
|
708
|
-
|
|
709
|
-
'custom.mapStockStatus': (value, sourceData, config, helpers) => {
|
|
710
|
-
const statusMap = {
|
|
711
|
-
'active': 'AVAILABLE',
|
|
712
|
-
'low': 'RESERVED',
|
|
713
|
-
'out': 'ON_HOLD',
|
|
714
|
-
'discontinued': 'DISCONTINUED'
|
|
715
|
-
};
|
|
716
|
-
|
|
717
|
-
const status = helpers.toString(value).toLowerCase();
|
|
718
|
-
return statusMap[status] || 'AVAILABLE';
|
|
719
|
-
}
|
|
720
|
-
};
|
|
721
|
-
|
|
722
|
-
const mapper = new UniversalMapper(mappingConfig, { customResolvers });
|
|
723
|
-
|
|
724
|
-
// Test data
|
|
725
|
-
const csvData = [
|
|
726
|
-
{ sku: 'abc123', warehouse: 'WH-001', on_hand: '100', reserved: '20', stock_status: 'active' }
|
|
727
|
-
];
|
|
728
|
-
|
|
729
|
-
const result = await mapper.map(csvData);
|
|
730
|
-
console.log(result);
|
|
731
|
-
// {
|
|
732
|
-
// success: true,
|
|
733
|
-
// data: [{
|
|
734
|
-
// ref: 'ABC123-WH-001',
|
|
735
|
-
// productRef: 'ABC123',
|
|
736
|
-
// locationRef: 'WH-001',
|
|
737
|
-
// qty: 80,
|
|
738
|
-
// status: 'AVAILABLE'
|
|
739
|
-
// }]
|
|
740
|
-
// }
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
</details>
|
|
744
|
-
|
|
745
|
-
## Key Takeaways
|
|
746
|
-
|
|
747
|
-
- 🎯 **UniversalMapper** transforms source data to Fluent schema
|
|
748
|
-
- 🎯 **SDK resolvers** provide common transformations (uppercase, parseInt, etc.)
|
|
749
|
-
- 🎯 **Custom resolvers** implement business logic and validation
|
|
750
|
-
- 🎯 **Schema validation** ensures compatibility before deployment
|
|
751
|
-
- 🎯 **Error handling** provides clear feedback for mapping failures
|
|
752
|
-
- 🎯 **Resolver helpers** simplify safe type conversions
|
|
753
|
-
|
|
754
|
-
## Next Steps
|
|
755
|
-
|
|
756
|
-
Continue to [Module 5: Advanced Parsers →](./02-core-guides-ingestion-05-advanced-parsers.md) to learn about Parquet, XML, and JSON parsing with streaming support.
|
|
757
|
-
|
|
758
|
-
---
|
|
759
|
-
|
|
760
|
-
**Related Documentation:**
|
|
761
|
-
- [Universal Mapping Guide](../../mapping/mapping-readme.md) - Complete field mapping reference
|
|
762
|
-
- [Resolver Development Guide](../../mapping/resolvers/mapping-resolvers-readme.md) - Advanced custom resolver patterns
|
|
763
|
-
- [Schema Validation CLI](../../../../bin/readme.md#validate-04-REFERENCE/schema) - CLI tool documentation
|
|
1
|
+
# Module 4: Field Mapping
|
|
2
|
+
|
|
3
|
+
**Level:** Intermediate
|
|
4
|
+
**Estimated Time:** 25 minutes
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
This module teaches you how to transform source data (CSV, Parquet, JSON) into the exact format required by Fluent Commerce's Batch API using the UniversalMapper service with schema-validated field mappings.
|
|
9
|
+
|
|
10
|
+
## Learning Objectives
|
|
11
|
+
|
|
12
|
+
By the end of this module, you will:
|
|
13
|
+
- ✅ Understand InventoryPositionInput schema requirements
|
|
14
|
+
- ✅ Configure UniversalMapper with field mappings
|
|
15
|
+
- ✅ Use SDK resolvers for data transformation
|
|
16
|
+
- ✅ Create custom resolvers for business logic
|
|
17
|
+
- ✅ Validate mappings against GraphQL schema
|
|
18
|
+
- ✅ Handle mapping errors gracefully
|
|
19
|
+
|
|
20
|
+
## Inventory Position Schema
|
|
21
|
+
|
|
22
|
+
### Required Fields
|
|
23
|
+
|
|
24
|
+
The Batch API requires specific fields for `InventoryPositionInput`:
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
{
|
|
28
|
+
"ref": "SKU-WM-001", // String! - Position reference (required)
|
|
29
|
+
"productRef": "SKU-WM-001", // String! - Product SKU (required)
|
|
30
|
+
"locationRef": "WH-001", // String! - Warehouse code (required)
|
|
31
|
+
"qty": 500 // Int! - Available quantity (required)
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Optional Fields
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
{
|
|
39
|
+
"status": "AVAILABLE", // String - Position status
|
|
40
|
+
"type": "ADJUSTMENT" // String - Position type
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Valid Status Values
|
|
45
|
+
|
|
46
|
+
| Status | Description |
|
|
47
|
+
|--------|-------------|
|
|
48
|
+
| `AVAILABLE` | Stock available for sale |
|
|
49
|
+
| `RESERVED` | Stock reserved for orders |
|
|
50
|
+
| `ON_HOLD` | Stock on hold (damaged, quarantine, etc.) |
|
|
51
|
+
| `DISCONTINUED` | Product no longer carried |
|
|
52
|
+
|
|
53
|
+
## UniversalMapper Basics
|
|
54
|
+
|
|
55
|
+
### Simple Mapping
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { UniversalMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
59
|
+
|
|
60
|
+
const mapper = new UniversalMapper({
|
|
61
|
+
fields: {
|
|
62
|
+
// Map source field to target field
|
|
63
|
+
ref: {
|
|
64
|
+
source: 'sku', // Source CSV column
|
|
65
|
+
required: true // Must be present
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
productRef: {
|
|
69
|
+
source: 'sku',
|
|
70
|
+
required: true
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
locationRef: {
|
|
74
|
+
source: 'warehouse',
|
|
75
|
+
required: true
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
qty: {
|
|
79
|
+
source: 'quantity',
|
|
80
|
+
resolver: 'sdk.parseInt', // Convert to integer
|
|
81
|
+
required: true
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Transform CSV data
|
|
87
|
+
const csvData = [
|
|
88
|
+
{ sku: 'SKU-001', warehouse: 'WH-001', quantity: '500' }
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
const result = await mapper.map(csvData);
|
|
92
|
+
|
|
93
|
+
if (result.success) {
|
|
94
|
+
console.log(result.data);
|
|
95
|
+
// [{
|
|
96
|
+
// ref: 'SKU-001',
|
|
97
|
+
// productRef: 'SKU-001',
|
|
98
|
+
// locationRef: 'WH-001',
|
|
99
|
+
// qty: 500
|
|
100
|
+
// }]
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Mapping Result
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
interface MappingResult {
|
|
108
|
+
success: boolean;
|
|
109
|
+
data: any[]; // Mapped records (if success)
|
|
110
|
+
errors?: string[]; // Validation errors (if failed)
|
|
111
|
+
skippedFields?: string[]; // Fields that were skipped because they were undefined (field names only)
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## SDK Resolvers
|
|
116
|
+
|
|
117
|
+
The SDK provides built-in resolvers for common transformations:
|
|
118
|
+
|
|
119
|
+
### String Resolvers
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
const mapping = {
|
|
123
|
+
fields: {
|
|
124
|
+
ref: {
|
|
125
|
+
source: 'sku',
|
|
126
|
+
resolver: 'sdk.uppercase' // Convert to UPPERCASE
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
status: {
|
|
130
|
+
source: 'status',
|
|
131
|
+
resolver: 'sdk.lowercase' // Convert to lowercase
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
locationRef: {
|
|
135
|
+
source: ' warehouse ',
|
|
136
|
+
resolver: 'sdk.trim' // Remove whitespace
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Number Resolvers
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const mapping = {
|
|
146
|
+
fields: {
|
|
147
|
+
qty: {
|
|
148
|
+
source: 'quantity',
|
|
149
|
+
resolver: 'sdk.parseInt' // String → Int
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
price: {
|
|
153
|
+
source: 'cost',
|
|
154
|
+
resolver: 'sdk.parseFloat' // String → Float
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
count: {
|
|
158
|
+
source: 'total',
|
|
159
|
+
resolver: 'sdk.number' // Force to number
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Date Resolvers
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
const mapping = {
|
|
169
|
+
fields: {
|
|
170
|
+
expectedOn: {
|
|
171
|
+
source: 'ship_date',
|
|
172
|
+
resolver: 'sdk.formatDate' // Format as ISO date
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
lastUpdated: {
|
|
176
|
+
source: 'updated',
|
|
177
|
+
resolver: 'sdk.formatDateShort' // Format as YYYY-MM-DD
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
createdAt: {
|
|
181
|
+
source: 'created_timestamp',
|
|
182
|
+
resolver: 'sdk.parseDate' // Parse various date formats
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Utility Resolvers
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
const mapping = {
|
|
192
|
+
fields: {
|
|
193
|
+
isActive: {
|
|
194
|
+
source: 'active',
|
|
195
|
+
resolver: 'sdk.boolean' // Convert to boolean
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
metadata: {
|
|
199
|
+
source: 'meta_json',
|
|
200
|
+
resolver: 'sdk.parseJson' // Parse JSON string
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
config: {
|
|
204
|
+
source: 'settings',
|
|
205
|
+
resolver: 'sdk.toJson' // Convert to JSON string
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
value: {
|
|
209
|
+
source: 'original',
|
|
210
|
+
resolver: 'sdk.identity' // Pass through unchanged
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Custom Resolvers
|
|
217
|
+
|
|
218
|
+
### Basic Custom Resolver
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
const mapper = new UniversalMapper(mappingConfig, {
|
|
222
|
+
customResolvers: {
|
|
223
|
+
'custom.mapStatus': (value, sourceData, config, helpers) => {
|
|
224
|
+
const statusMap = {
|
|
225
|
+
'in_stock': 'AVAILABLE',
|
|
226
|
+
'out_of_stock': 'ON_HOLD',
|
|
227
|
+
'discontinued': 'DISCONTINUED',
|
|
228
|
+
'reserved': 'RESERVED'
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const mapped = statusMap[String(value).toLowerCase()];
|
|
232
|
+
|
|
233
|
+
if (!mapped) {
|
|
234
|
+
throw new Error(`Unknown status: ${value}`);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return mapped;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Resolver with Helper Functions
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
const customResolvers = {
|
|
247
|
+
'custom.calculateQty': (value, sourceData, config, helpers) => {
|
|
248
|
+
// Use helper functions for safe conversions
|
|
249
|
+
const onHand = helpers.parseIntSafe(sourceData.on_hand, 0);
|
|
250
|
+
const reserved = helpers.parseIntSafe(sourceData.reserved, 0);
|
|
251
|
+
|
|
252
|
+
return onHand - reserved;
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
'custom.formatLocation': (value, sourceData, config, helpers) => {
|
|
256
|
+
// Combine multiple source fields
|
|
257
|
+
const region = helpers.toString(sourceData.region);
|
|
258
|
+
const warehouse = helpers.toString(sourceData.warehouse);
|
|
259
|
+
|
|
260
|
+
return `${region}-${warehouse}`;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Validation Resolver
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
const customResolvers = {
|
|
269
|
+
'custom.validateSKU': (value, sourceData, config, helpers) => {
|
|
270
|
+
const sku = helpers.toString(value).trim();
|
|
271
|
+
|
|
272
|
+
// Must be alphanumeric and at least 3 characters
|
|
273
|
+
if (!/^[A-Z0-9-]{3,}$/i.test(sku)) {
|
|
274
|
+
throw new Error(`Invalid SKU format: ${sku}`);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return sku.toUpperCase();
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
'custom.ensurePositiveQty': (value, sourceData, config, helpers) => {
|
|
281
|
+
const qty = helpers.parseIntSafe(value, 0);
|
|
282
|
+
|
|
283
|
+
if (qty < 0) {
|
|
284
|
+
throw new Error(`Negative quantity not allowed: ${qty}`);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return qty;
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Required Fields with Resolvers
|
|
293
|
+
|
|
294
|
+
When using `required: true` with resolvers, understand how validation timing works:
|
|
295
|
+
|
|
296
|
+
**Fields with `source`**: Validation happens **before** resolver execution
|
|
297
|
+
```json
|
|
298
|
+
{
|
|
299
|
+
"qty": {
|
|
300
|
+
"source": "quantity",
|
|
301
|
+
"resolver": "sdk.parseInt",
|
|
302
|
+
"required": true
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
- ✅ Checks if `quantity` exists in source data first
|
|
307
|
+
- ✅ If missing → mapping fails immediately (resolver never runs)
|
|
308
|
+
- ✅ If present → resolver runs to transform the value
|
|
309
|
+
|
|
310
|
+
**Resolver-only fields** (no `source`): Validation happens **after** resolver execution
|
|
311
|
+
```json
|
|
312
|
+
{
|
|
313
|
+
"metadata.uuid": {
|
|
314
|
+
"resolver": "custom.generateUUID",
|
|
315
|
+
"required": true
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
- ✅ Resolver runs first to generate value
|
|
320
|
+
- ✅ Then validates that resolver produced a value
|
|
321
|
+
- ✅ If resolver returns `null`, `undefined`, or empty string → mapping fails
|
|
322
|
+
|
|
323
|
+
**Important:** Resolvers can return empty values. `required: true` ensures validation happens **after** the resolver runs to catch these cases. If your resolver has conditional logic that might return `undefined`, use `required: true` to ensure the field always has a value.
|
|
324
|
+
|
|
325
|
+
**Example: Conditional Resolver**
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
const customResolvers = {
|
|
329
|
+
'custom.calculateDiscount': (value, sourceData, config, helpers) => {
|
|
330
|
+
const customerTier = helpers.get(sourceData, 'customer.tier');
|
|
331
|
+
|
|
332
|
+
// ⚠️ Can return undefined for BASIC tier!
|
|
333
|
+
if (customerTier === 'PREMIUM') {
|
|
334
|
+
return helpers.parseFloatSafe(value, 0) * 0.2;
|
|
335
|
+
} else if (customerTier === 'STANDARD') {
|
|
336
|
+
return helpers.parseFloatSafe(value, 0) * 0.1;
|
|
337
|
+
}
|
|
338
|
+
return undefined; // ❌ Returns undefined
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
// Mapping config
|
|
343
|
+
{
|
|
344
|
+
"fields": {
|
|
345
|
+
"discount": {
|
|
346
|
+
"source": "order.subtotal",
|
|
347
|
+
"resolver": "custom.calculateDiscount",
|
|
348
|
+
"required": true // ✅ Ensures discount is always calculated
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Without `required: true`:
|
|
355
|
+
- Resolver returns `undefined` for BASIC tier → mapping succeeds → API call fails
|
|
356
|
+
|
|
357
|
+
With `required: true`:
|
|
358
|
+
- Resolver returns `undefined` → mapping fails immediately → No API call (saves quota)
|
|
359
|
+
|
|
360
|
+
## Complete Mapping Example
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
import { UniversalMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
364
|
+
|
|
365
|
+
// Schema-validated mapping configuration
|
|
366
|
+
const mappingConfig = {
|
|
367
|
+
fields: {
|
|
368
|
+
// Required fields
|
|
369
|
+
ref: {
|
|
370
|
+
source: 'sku',
|
|
371
|
+
resolver: 'custom.validateSKU',
|
|
372
|
+
required: true,
|
|
373
|
+
comment: '✅ InventoryPositionInput.ref (String! required)'
|
|
374
|
+
},
|
|
375
|
+
|
|
376
|
+
productRef: {
|
|
377
|
+
source: 'sku',
|
|
378
|
+
resolver: 'custom.validateSKU',
|
|
379
|
+
required: true,
|
|
380
|
+
comment: '✅ InventoryPositionInput.productRef (String! required)'
|
|
381
|
+
},
|
|
382
|
+
|
|
383
|
+
locationRef: {
|
|
384
|
+
source: 'warehouse',
|
|
385
|
+
resolver: 'sdk.trim',
|
|
386
|
+
required: true,
|
|
387
|
+
comment: '✅ InventoryPositionInput.locationRef (String! required)'
|
|
388
|
+
},
|
|
389
|
+
|
|
390
|
+
qty: {
|
|
391
|
+
source: 'quantity',
|
|
392
|
+
resolver: 'custom.ensurePositiveQty',
|
|
393
|
+
required: true,
|
|
394
|
+
comment: '✅ InventoryPositionInput.qty (Int! required)'
|
|
395
|
+
},
|
|
396
|
+
|
|
397
|
+
// Optional fields with defaults
|
|
398
|
+
status: {
|
|
399
|
+
source: 'status',
|
|
400
|
+
resolver: 'custom.mapStatus',
|
|
401
|
+
defaultValue: 'AVAILABLE',
|
|
402
|
+
comment: '✅ InventoryPositionInput.status (String optional)'
|
|
403
|
+
},
|
|
404
|
+
|
|
405
|
+
type: {
|
|
406
|
+
value: 'ADJUSTMENT', // Static value for all records
|
|
407
|
+
comment: '✅ InventoryPositionInput.type (String optional)'
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
// Custom resolvers for business logic
|
|
413
|
+
const customResolvers = {
|
|
414
|
+
'custom.validateSKU': (value, sourceData, config, helpers) => {
|
|
415
|
+
const sku = helpers.toString(value).trim().toUpperCase();
|
|
416
|
+
|
|
417
|
+
if (!/^[A-Z0-9-]{3,}$/.test(sku)) {
|
|
418
|
+
throw new Error(`Invalid SKU: ${sku}`);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
return sku;
|
|
422
|
+
},
|
|
423
|
+
|
|
424
|
+
'custom.ensurePositiveQty': (value, sourceData, config, helpers) => {
|
|
425
|
+
const qty = helpers.parseIntSafe(value, 0);
|
|
426
|
+
|
|
427
|
+
if (qty < 0) {
|
|
428
|
+
throw new Error(`Negative quantity: ${qty}`);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return qty;
|
|
432
|
+
},
|
|
433
|
+
|
|
434
|
+
'custom.mapStatus': (value, sourceData, config, helpers) => {
|
|
435
|
+
const statusMap = {
|
|
436
|
+
'in_stock': 'AVAILABLE',
|
|
437
|
+
'out_of_stock': 'ON_HOLD',
|
|
438
|
+
'discontinued': 'DISCONTINUED',
|
|
439
|
+
'reserved': 'RESERVED'
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
const status = helpers.toString(value).toLowerCase();
|
|
443
|
+
const mapped = statusMap[status];
|
|
444
|
+
|
|
445
|
+
if (!mapped) {
|
|
446
|
+
throw new Error(`Unknown status: ${value}`);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
return mapped;
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
// Create mapper with custom resolvers
|
|
454
|
+
const mapper = new UniversalMapper(mappingConfig, { customResolvers });
|
|
455
|
+
|
|
456
|
+
// Map CSV data
|
|
457
|
+
const csvData = [
|
|
458
|
+
{ sku: 'sku-wm-001', warehouse: 'WH-001', quantity: '500', status: 'in_stock' },
|
|
459
|
+
{ sku: 'sku-wm-002', warehouse: 'WH-001', quantity: '150', status: 'reserved' }
|
|
460
|
+
];
|
|
461
|
+
|
|
462
|
+
const result = await mapper.map(csvData);
|
|
463
|
+
|
|
464
|
+
if (!result.success) {
|
|
465
|
+
console.error('Mapping errors:', result.errors);
|
|
466
|
+
process.exit(1);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
console.log('Mapped records:', result.data);
|
|
470
|
+
// [
|
|
471
|
+
// { ref: 'SKU-WM-001', productRef: 'SKU-WM-001', locationRef: 'WH-001', qty: 500, status: 'AVAILABLE', type: 'ADJUSTMENT' },
|
|
472
|
+
// { ref: 'SKU-WM-002', productRef: 'SKU-WM-002', locationRef: 'WH-001', qty: 150, status: 'RESERVED', type: 'ADJUSTMENT' }
|
|
473
|
+
// ]
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
## Schema Validation
|
|
477
|
+
|
|
478
|
+
### Validate Before Deployment
|
|
479
|
+
|
|
480
|
+
```bash
|
|
481
|
+
# Step 1: Introspect your Fluent Commerce schema
|
|
482
|
+
npx @fluentcommerce/fc-connect-sdk introspect-schema \
|
|
483
|
+
--url https://YOUR_ACCOUNT.api.fluentcommerce.com/graphql \
|
|
484
|
+
--output schema.json
|
|
485
|
+
|
|
486
|
+
# Step 2: Save your mapping configuration
|
|
487
|
+
cat > field-mappings.json << 'EOF'
|
|
488
|
+
{
|
|
489
|
+
"fields": {
|
|
490
|
+
"ref": { "source": "sku", "required": true },
|
|
491
|
+
"productRef": { "source": "sku", "required": true },
|
|
492
|
+
"locationRef": { "source": "warehouse", "required": true },
|
|
493
|
+
"qty": { "source": "quantity", "resolver": "sdk.parseInt", "required": true },
|
|
494
|
+
"status": { "source": "status", "resolver": "custom.mapStatus", "defaultValue": "AVAILABLE" }
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
EOF
|
|
498
|
+
|
|
499
|
+
# Step 3: Validate mapping against schema
|
|
500
|
+
npx @fluentcommerce/fc-connect-sdk validate-schema \
|
|
501
|
+
--mapping field-mappings.json \
|
|
502
|
+
--schema schema.json
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### Expected Output
|
|
506
|
+
|
|
507
|
+
```
|
|
508
|
+
✅ Mapping validation successful
|
|
509
|
+
✅ All required fields present: ref, productRef, locationRef, qty
|
|
510
|
+
✅ All field types compatible with InventoryPositionInput schema
|
|
511
|
+
✅ No unknown fields detected
|
|
512
|
+
|
|
513
|
+
Validation Summary:
|
|
514
|
+
Required fields: 4/4 ✓
|
|
515
|
+
Optional fields: 1
|
|
516
|
+
Custom resolvers: 1 (custom.mapStatus)
|
|
517
|
+
SDK resolvers: 1 (sdk.parseInt)
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
## Error Handling
|
|
521
|
+
|
|
522
|
+
### Mapping Errors
|
|
523
|
+
|
|
524
|
+
```typescript
|
|
525
|
+
const result = await mapper.map(csvData);
|
|
526
|
+
|
|
527
|
+
if (!result.success) {
|
|
528
|
+
// Log all errors
|
|
529
|
+
console.error('Mapping failed with errors:');
|
|
530
|
+
result.errors.forEach((error, index) => {
|
|
531
|
+
console.error(` ${index + 1}. ${error}`);
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
// Optionally: Write failed records to error file
|
|
535
|
+
const errorReport = {
|
|
536
|
+
timestamp: new Date().toISOString(),
|
|
537
|
+
totalRecords: csvData.length,
|
|
538
|
+
errors: result.errors,
|
|
539
|
+
failedRecords: csvData.filter((_, i) => result.errors.some(e => e.includes(`Row ${i}`)))
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
await fs.writeFile('mapping-errors.json', JSON.stringify(errorReport, null, 2));
|
|
543
|
+
|
|
544
|
+
throw new Error(`Mapping failed: ${result.errors.length} errors`);
|
|
545
|
+
}
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### Partial Success Handling
|
|
549
|
+
|
|
550
|
+
```typescript
|
|
551
|
+
async function mapWithPartialSuccess(mapper: UniversalMapper, records: any[]) {
|
|
552
|
+
const successful = [];
|
|
553
|
+
const failed = [];
|
|
554
|
+
|
|
555
|
+
for (const [index, record] of records.entries()) {
|
|
556
|
+
try {
|
|
557
|
+
const result = await mapper.map([record]);
|
|
558
|
+
|
|
559
|
+
if (result.success) {
|
|
560
|
+
successful.push(result.data[0]);
|
|
561
|
+
} else {
|
|
562
|
+
failed.push({ record, errors: result.errors });
|
|
563
|
+
}
|
|
564
|
+
} catch (error) {
|
|
565
|
+
failed.push({ record, error: error.message });
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return {
|
|
570
|
+
successful,
|
|
571
|
+
failed,
|
|
572
|
+
successRate: successful.length / records.length
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
## Advanced Patterns
|
|
578
|
+
|
|
579
|
+
### Conditional Mapping
|
|
580
|
+
|
|
581
|
+
```typescript
|
|
582
|
+
const conditionalMapper = {
|
|
583
|
+
'custom.conditionalStatus': (value, sourceData, config, helpers) => {
|
|
584
|
+
const qty = helpers.parseIntSafe(sourceData.quantity, 0);
|
|
585
|
+
const status = helpers.toString(value).toLowerCase();
|
|
586
|
+
|
|
587
|
+
// Override status based on quantity
|
|
588
|
+
if (qty === 0) {
|
|
589
|
+
return 'ON_HOLD';
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
if (qty > 1000) {
|
|
593
|
+
return 'AVAILABLE';
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// Use source status
|
|
597
|
+
return status === 'available' ? 'AVAILABLE' : 'RESERVED';
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
### Multi-Field Transformation
|
|
603
|
+
|
|
604
|
+
```typescript
|
|
605
|
+
const multiFieldMapper = {
|
|
606
|
+
'custom.generateRef': (value, sourceData, config, helpers) => {
|
|
607
|
+
const sku = helpers.toString(sourceData.sku).trim();
|
|
608
|
+
const location = helpers.toString(sourceData.warehouse).trim();
|
|
609
|
+
const date = new Date().toISOString().split('T')[0];
|
|
610
|
+
|
|
611
|
+
return `${sku}-${location}-${date}`;
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
### Lookup Table Resolver
|
|
617
|
+
|
|
618
|
+
```typescript
|
|
619
|
+
const lookupTables = {
|
|
620
|
+
warehouseCodes: {
|
|
621
|
+
'California DC': 'CA-001',
|
|
622
|
+
'Texas DC': 'TX-001',
|
|
623
|
+
'New York DC': 'NY-001'
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
const lookupResolver = {
|
|
628
|
+
'custom.lookupWarehouse': (value, sourceData, config, helpers) => {
|
|
629
|
+
const warehouseName = helpers.toString(value);
|
|
630
|
+
const code = lookupTables.warehouseCodes[warehouseName];
|
|
631
|
+
|
|
632
|
+
if (!code) {
|
|
633
|
+
throw new Error(`Unknown warehouse: ${warehouseName}`);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return code;
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
## Practice Exercise
|
|
642
|
+
|
|
643
|
+
Create a field mapping that:
|
|
644
|
+
1. Validates SKU format (alphanumeric, min 3 chars)
|
|
645
|
+
2. Maps status from custom values to Fluent values
|
|
646
|
+
3. Calculates available quantity (on_hand - reserved)
|
|
647
|
+
4. Generates a unique position reference
|
|
648
|
+
|
|
649
|
+
<details>
|
|
650
|
+
<summary>Click to see solution</summary>
|
|
651
|
+
|
|
652
|
+
```typescript
|
|
653
|
+
import { UniversalMapper } from '@fluentcommerce/fc-connect-sdk';
|
|
654
|
+
|
|
655
|
+
const mappingConfig = {
|
|
656
|
+
fields: {
|
|
657
|
+
ref: {
|
|
658
|
+
source: 'sku',
|
|
659
|
+
resolver: 'custom.generatePositionRef',
|
|
660
|
+
required: true
|
|
661
|
+
},
|
|
662
|
+
productRef: {
|
|
663
|
+
source: 'sku',
|
|
664
|
+
resolver: 'custom.validateSKU',
|
|
665
|
+
required: true
|
|
666
|
+
},
|
|
667
|
+
locationRef: {
|
|
668
|
+
source: 'warehouse',
|
|
669
|
+
required: true
|
|
670
|
+
},
|
|
671
|
+
qty: {
|
|
672
|
+
source: 'on_hand',
|
|
673
|
+
resolver: 'custom.calculateAvailable',
|
|
674
|
+
required: true
|
|
675
|
+
},
|
|
676
|
+
status: {
|
|
677
|
+
source: 'stock_status',
|
|
678
|
+
resolver: 'custom.mapStockStatus',
|
|
679
|
+
defaultValue: 'AVAILABLE'
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
|
|
684
|
+
const customResolvers = {
|
|
685
|
+
'custom.validateSKU': (value, sourceData, config, helpers) => {
|
|
686
|
+
const sku = helpers.toString(value).trim().toUpperCase();
|
|
687
|
+
|
|
688
|
+
if (!/^[A-Z0-9]{3,}$/.test(sku)) {
|
|
689
|
+
throw new Error(`Invalid SKU format: ${value}`);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
return sku;
|
|
693
|
+
},
|
|
694
|
+
|
|
695
|
+
'custom.generatePositionRef': (value, sourceData, config, helpers) => {
|
|
696
|
+
const sku = helpers.toString(value).trim().toUpperCase();
|
|
697
|
+
const warehouse = helpers.toString(sourceData.warehouse).trim();
|
|
698
|
+
|
|
699
|
+
return `${sku}-${warehouse}`;
|
|
700
|
+
},
|
|
701
|
+
|
|
702
|
+
'custom.calculateAvailable': (value, sourceData, config, helpers) => {
|
|
703
|
+
const onHand = helpers.parseIntSafe(value, 0);
|
|
704
|
+
const reserved = helpers.parseIntSafe(sourceData.reserved, 0);
|
|
705
|
+
|
|
706
|
+
return Math.max(0, onHand - reserved);
|
|
707
|
+
},
|
|
708
|
+
|
|
709
|
+
'custom.mapStockStatus': (value, sourceData, config, helpers) => {
|
|
710
|
+
const statusMap = {
|
|
711
|
+
'active': 'AVAILABLE',
|
|
712
|
+
'low': 'RESERVED',
|
|
713
|
+
'out': 'ON_HOLD',
|
|
714
|
+
'discontinued': 'DISCONTINUED'
|
|
715
|
+
};
|
|
716
|
+
|
|
717
|
+
const status = helpers.toString(value).toLowerCase();
|
|
718
|
+
return statusMap[status] || 'AVAILABLE';
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
const mapper = new UniversalMapper(mappingConfig, { customResolvers });
|
|
723
|
+
|
|
724
|
+
// Test data
|
|
725
|
+
const csvData = [
|
|
726
|
+
{ sku: 'abc123', warehouse: 'WH-001', on_hand: '100', reserved: '20', stock_status: 'active' }
|
|
727
|
+
];
|
|
728
|
+
|
|
729
|
+
const result = await mapper.map(csvData);
|
|
730
|
+
console.log(result);
|
|
731
|
+
// {
|
|
732
|
+
// success: true,
|
|
733
|
+
// data: [{
|
|
734
|
+
// ref: 'ABC123-WH-001',
|
|
735
|
+
// productRef: 'ABC123',
|
|
736
|
+
// locationRef: 'WH-001',
|
|
737
|
+
// qty: 80,
|
|
738
|
+
// status: 'AVAILABLE'
|
|
739
|
+
// }]
|
|
740
|
+
// }
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
</details>
|
|
744
|
+
|
|
745
|
+
## Key Takeaways
|
|
746
|
+
|
|
747
|
+
- 🎯 **UniversalMapper** transforms source data to Fluent schema
|
|
748
|
+
- 🎯 **SDK resolvers** provide common transformations (uppercase, parseInt, etc.)
|
|
749
|
+
- 🎯 **Custom resolvers** implement business logic and validation
|
|
750
|
+
- 🎯 **Schema validation** ensures compatibility before deployment
|
|
751
|
+
- 🎯 **Error handling** provides clear feedback for mapping failures
|
|
752
|
+
- 🎯 **Resolver helpers** simplify safe type conversions
|
|
753
|
+
|
|
754
|
+
## Next Steps
|
|
755
|
+
|
|
756
|
+
Continue to [Module 5: Advanced Parsers →](./02-core-guides-ingestion-05-advanced-parsers.md) to learn about Parquet, XML, and JSON parsing with streaming support.
|
|
757
|
+
|
|
758
|
+
---
|
|
759
|
+
|
|
760
|
+
**Related Documentation:**
|
|
761
|
+
- [Universal Mapping Guide](../../mapping/mapping-readme.md) - Complete field mapping reference
|
|
762
|
+
- [Resolver Development Guide](../../mapping/resolvers/mapping-resolvers-readme.md) - Advanced custom resolver patterns
|
|
763
|
+
- [Schema Validation CLI](../../../../bin/readme.md#validate-04-REFERENCE/schema) - CLI tool documentation
|