@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,658 +1,658 @@
|
|
|
1
|
-
# Module 2: Quick Start - Your First Ingestion
|
|
2
|
-
|
|
3
|
-
[← Back to Ingestion Guide](../ingestion-readme.md)
|
|
4
|
-
|
|
5
|
-
**Module 2 of 9** | **Level**: Beginner | **Time**: 15 minutes
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Overview
|
|
10
|
-
|
|
11
|
-
This module walks you through creating your first complete ingestion workflow: reading a CSV file from S3, transforming it with UniversalMapper, and sending it to Fluent Commerce using the Batch API.
|
|
12
|
-
|
|
13
|
-
## Learning Objectives
|
|
14
|
-
|
|
15
|
-
By the end of this module, you will:
|
|
16
|
-
|
|
17
|
-
- ✅ Install and configure the FC Connect SDK
|
|
18
|
-
- ✅ Create a complete S3 → CSV → Batch API workflow
|
|
19
|
-
- ✅ Understand the basic ingestion pattern
|
|
20
|
-
- ✅ Validate field mappings against the schema
|
|
21
|
-
- ✅ Send your first batch to Fluent Commerce
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## Prerequisites
|
|
26
|
-
|
|
27
|
-
Before starting, ensure you have:
|
|
28
|
-
|
|
29
|
-
1. **Node.js** >= 18.0.0 installed
|
|
30
|
-
2. **Fluent Commerce credentials**:
|
|
31
|
-
- API Base URL (e.g., `https://yourcompany.api.fluentcommerce.com`)
|
|
32
|
-
- OAuth2 Client ID
|
|
33
|
-
- OAuth2 Client Secret
|
|
34
|
-
- Retailer ID
|
|
35
|
-
3. **AWS S3 access** (or local CSV file for testing):
|
|
36
|
-
- Access Key ID
|
|
37
|
-
- Secret Access Key
|
|
38
|
-
- Bucket name
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## Step 1: Installation
|
|
43
|
-
|
|
44
|
-
Install the FC Connect SDK:
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
npm install @fluentcommerce/fc-connect-sdk
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
**Verify installation:**
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
npx @fluentcommerce/fc-connect-sdk --version
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## Step 2: Environment Configuration
|
|
59
|
-
|
|
60
|
-
Create a `.env` file with your credentials:
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
# Fluent Commerce OAuth2 (Password Grant)
|
|
64
|
-
FLUENT_BASE_URL=https://yourcompany.api.fluentcommerce.com
|
|
65
|
-
FLUENT_CLIENT_ID=your-oauth-client-id
|
|
66
|
-
FLUENT_CLIENT_SECRET=your-oauth-client-secret
|
|
67
|
-
FLUENT_USERNAME=your-username # ✅ REQUIRED for password grant
|
|
68
|
-
FLUENT_PASSWORD=your-password # ✅ REQUIRED for password grant
|
|
69
|
-
FLUENT_RETAILER_ID=1
|
|
70
|
-
|
|
71
|
-
# AWS S3 (source)
|
|
72
|
-
AWS_ACCESS_KEY_ID=your-aws-access-key
|
|
73
|
-
AWS_SECRET_ACCESS_KEY=your-aws-secret-key
|
|
74
|
-
AWS_REGION=us-east-1
|
|
75
|
-
S3_BUCKET=your-inventory-bucket
|
|
76
|
-
S3_PREFIX=data/
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
**Load environment variables:**
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
npm install dotenv
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## Step 3: Prepare Sample Data
|
|
88
|
-
|
|
89
|
-
Create a sample CSV file (`sample-inventory.csv`):
|
|
90
|
-
|
|
91
|
-
```csv
|
|
92
|
-
sku,warehouse,quantity,status
|
|
93
|
-
SKU-WM-001,WH-001,500,in_stock
|
|
94
|
-
SKU-WM-002,WH-001,150,in_stock
|
|
95
|
-
SKU-KB-001,WH-001,75,reserved
|
|
96
|
-
SKU-WM-003,WH-002,300,discontinued
|
|
97
|
-
SKU-WM-004,WH-002,200,in_stock
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
**Upload to S3** (or keep local for testing):
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
aws s3 cp sample-inventory.csv s3://your-bucket/data/inventory-2025-01-19.csv
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
## Step 4: Create Field Mapping Configuration
|
|
109
|
-
|
|
110
|
-
Create `field-mappings.json`:
|
|
111
|
-
|
|
112
|
-
```json
|
|
113
|
-
{
|
|
114
|
-
"fields": {
|
|
115
|
-
"ref": {
|
|
116
|
-
"source": "sku",
|
|
117
|
-
"required": true,
|
|
118
|
-
"comment": "✅ InventoryPositionInput.ref (String! required) - Position reference"
|
|
119
|
-
},
|
|
120
|
-
"productRef": {
|
|
121
|
-
"source": "sku",
|
|
122
|
-
"required": true,
|
|
123
|
-
"comment": "✅ InventoryPositionInput.productRef (String! required) - Product SKU"
|
|
124
|
-
},
|
|
125
|
-
"locationRef": {
|
|
126
|
-
"source": "warehouse",
|
|
127
|
-
"required": true,
|
|
128
|
-
"comment": "✅ InventoryPositionInput.locationRef (String! required) - Warehouse code"
|
|
129
|
-
},
|
|
130
|
-
"qty": {
|
|
131
|
-
"source": "quantity",
|
|
132
|
-
"resolver": "sdk.parseInt",
|
|
133
|
-
"required": true,
|
|
134
|
-
"comment": "✅ InventoryPositionInput.qty (Int! required) - Available quantity"
|
|
135
|
-
},
|
|
136
|
-
"status": {
|
|
137
|
-
"source": "status",
|
|
138
|
-
"resolver": "custom.mapStatus",
|
|
139
|
-
"defaultValue": "AVAILABLE",
|
|
140
|
-
"comment": "✅ InventoryPositionInput.status (String optional) - Position status"
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
---
|
|
147
|
-
|
|
148
|
-
## Step 5: Validate Field Mapping Against Schema
|
|
149
|
-
|
|
150
|
-
**CRITICAL**: Before running ingestion, validate your mapping:
|
|
151
|
-
|
|
152
|
-
```bash
|
|
153
|
-
# Step 1: Introspect Fluent Commerce schema
|
|
154
|
-
npx @fluentcommerce/fc-connect-sdk introspect-schema \
|
|
155
|
-
--url https://yourcompany.api.fluentcommerce.com/graphql \
|
|
156
|
-
--client-id $FLUENT_CLIENT_ID \
|
|
157
|
-
--client-secret $FLUENT_CLIENT_SECRET \
|
|
158
|
-
--output schema.json
|
|
159
|
-
|
|
160
|
-
# Step 2: Validate field-mappings.json against schema
|
|
161
|
-
npx @fluentcommerce/fc-connect-sdk validate-schema \
|
|
162
|
-
--mapping field-mappings.json \
|
|
163
|
-
--schema schema.json
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
**Expected output:**
|
|
167
|
-
|
|
168
|
-
```
|
|
169
|
-
✅ Mapping validation successful
|
|
170
|
-
✅ All required fields present: ref, productRef, locationRef, qty
|
|
171
|
-
✅ All field types compatible with InventoryPositionInput schema
|
|
172
|
-
✅ No unknown fields detected
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### Preflight Validation (NEW)
|
|
176
|
-
|
|
177
|
-
Run a preflight validation to catch misconfigurations before execution.
|
|
178
|
-
|
|
179
|
-
```typescript
|
|
180
|
-
import { PreflightValidator } from '@fluentcommerce/fc-connect-sdk';
|
|
181
|
-
|
|
182
|
-
const validator = new PreflightValidator(logger);
|
|
183
|
-
await validator.validate({
|
|
184
|
-
fluent: { client },
|
|
185
|
-
sftp: { host: process.env.SFTP_HOST, username: process.env.SFTP_USERNAME },
|
|
186
|
-
config: { processedPath: process.env.PROCESSED_PATH, errorsPath: process.env.ERRORS_PATH },
|
|
187
|
-
});
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
Checks performed:
|
|
191
|
-
|
|
192
|
-
- Fluent client reachability/auth
|
|
193
|
-
- SFTP connectivity and directory writability (create directories if missing)
|
|
194
|
-
- Required activation/env variables present
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
## Step 6: Complete Ingestion Script
|
|
199
|
-
|
|
200
|
-
Create `ingest-inventory.ts`:
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
import 'dotenv/config';
|
|
204
|
-
import {
|
|
205
|
-
createClient,
|
|
206
|
-
S3DataSource,
|
|
207
|
-
CSVParserService,
|
|
208
|
-
UniversalMapper,
|
|
209
|
-
createConsoleLogger,
|
|
210
|
-
toStructuredLogger
|
|
211
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
212
|
-
|
|
213
|
-
// Custom resolver for status mapping
|
|
214
|
-
const customResolvers = {
|
|
215
|
-
'custom.mapStatus': (value: string) => {
|
|
216
|
-
const statusMap: Record<string, string> = {
|
|
217
|
-
in_stock: 'AVAILABLE',
|
|
218
|
-
out_of_stock: 'ON_HOLD',
|
|
219
|
-
discontinued: 'DISCONTINUED',
|
|
220
|
-
reserved: 'RESERVED',
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
const mapped = statusMap[String(value).toLowerCase()];
|
|
224
|
-
if (!mapped) {
|
|
225
|
-
throw new Error(`Unknown status: ${value}`);
|
|
226
|
-
}
|
|
227
|
-
return mapped;
|
|
228
|
-
},
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
async function ingestInventory() {
|
|
232
|
-
const logger = toStructuredLogger(createConsoleLogger(), {
|
|
233
|
-
service: 'inventory-ingestion',
|
|
234
|
-
correlationId: generateCorrelationId()
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
try {
|
|
238
|
-
// Step 1: Initialize Fluent client with OAuth2 password grant
|
|
239
|
-
logger.info('Initializing Fluent client...');
|
|
240
|
-
const client = await createClient({
|
|
241
|
-
config: {
|
|
242
|
-
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
243
|
-
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
244
|
-
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
245
|
-
username: process.env.FLUENT_USERNAME!, // ✅ REQUIRED for password grant
|
|
246
|
-
password: process.env.FLUENT_PASSWORD!, // ✅ REQUIRED for password grant
|
|
247
|
-
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
// Step 2: Initialize S3 data source with retry logic
|
|
252
|
-
logger.info('Initializing S3 data source...');
|
|
253
|
-
let s3: S3DataSource;
|
|
254
|
-
try {
|
|
255
|
-
s3 = new S3DataSource(
|
|
256
|
-
{
|
|
257
|
-
type: 'S3_CSV',
|
|
258
|
-
connectionId: 's3-inventory',
|
|
259
|
-
name: 'S3 Inventory Source',
|
|
260
|
-
s3Config: {
|
|
261
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
262
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
263
|
-
region: process.env.AWS_REGION!,
|
|
264
|
-
bucket: process.env.S3_BUCKET!,
|
|
265
|
-
},
|
|
266
|
-
},
|
|
267
|
-
logger
|
|
268
|
-
);
|
|
269
|
-
} catch (error) {
|
|
270
|
-
logger.error('Failed to initialize S3 data source', {
|
|
271
|
-
error: error.message,
|
|
272
|
-
bucket: process.env.S3_BUCKET,
|
|
273
|
-
region: process.env.AWS_REGION
|
|
274
|
-
});
|
|
275
|
-
throw new Error(`S3 initialization failed: ${error.message}`);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// Step 3: Initialize CSV parser
|
|
279
|
-
const parser = new CSVParserService(logger);
|
|
280
|
-
// Options are passed to parse() method, not constructor
|
|
281
|
-
|
|
282
|
-
// Step 4: Load field mapping configuration
|
|
283
|
-
const mappingConfig = require('./field-mappings.json');
|
|
284
|
-
const mapper = new UniversalMapper(mappingConfig, { customResolvers });
|
|
285
|
-
|
|
286
|
-
// Step 5: List files in S3 with error handling
|
|
287
|
-
logger.info(`Listing files in s3://${process.env.S3_BUCKET}/${process.env.S3_PREFIX}`);
|
|
288
|
-
let files: any[];
|
|
289
|
-
try {
|
|
290
|
-
files = await s3.listFiles({ prefix: process.env.S3_PREFIX });
|
|
291
|
-
logger.info(`Found ${files.length} files`);
|
|
292
|
-
} catch (error) {
|
|
293
|
-
logger.error('Failed to list S3 files', {
|
|
294
|
-
error: error.message,
|
|
295
|
-
bucket: process.env.S3_BUCKET,
|
|
296
|
-
prefix: process.env.S3_PREFIX
|
|
297
|
-
});
|
|
298
|
-
throw new Error(`S3 file listing failed: ${error.message}`);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Step 6: Process each file with comprehensive error handling
|
|
302
|
-
for (const file of files) {
|
|
303
|
-
logger.info(`Processing file: ${file.path}`);
|
|
304
|
-
|
|
305
|
-
try {
|
|
306
|
-
// Step 6a: Download and parse CSV with error recovery
|
|
307
|
-
let csvData: string;
|
|
308
|
-
let records: any[];
|
|
309
|
-
|
|
310
|
-
try {
|
|
311
|
-
csvData = await s3.downloadFile(file.path);
|
|
312
|
-
logger.info(`Downloaded file: ${file.path} (${csvData.length} bytes)`);
|
|
313
|
-
} catch (error) {
|
|
314
|
-
logger.error('Failed to download file from S3', {
|
|
315
|
-
file: file.path,
|
|
316
|
-
error: error.message
|
|
317
|
-
});
|
|
318
|
-
// Skip to next file on download failure
|
|
319
|
-
continue;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
try {
|
|
323
|
-
records = await parser.parse(csvData);
|
|
324
|
-
logger.info(`Parsed ${records.length} records from CSV`);
|
|
325
|
-
|
|
326
|
-
if (records.length === 0) {
|
|
327
|
-
logger.warn('No records found in CSV file', { file: file.path });
|
|
328
|
-
continue;
|
|
329
|
-
}
|
|
330
|
-
} catch (error) {
|
|
331
|
-
logger.error('CSV parsing failed', {
|
|
332
|
-
file: file.path,
|
|
333
|
-
error: error.message,
|
|
334
|
-
errorType: error.constructor.name
|
|
335
|
-
});
|
|
336
|
-
// Skip to next file on parse failure
|
|
337
|
-
continue;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// Step 6b: Transform data with UniversalMapper
|
|
341
|
-
const mappingResult = await mapper.map(records);
|
|
342
|
-
|
|
343
|
-
if (!mappingResult.success) {
|
|
344
|
-
logger.error('Mapping errors detected', {
|
|
345
|
-
file: file.path,
|
|
346
|
-
errorCount: mappingResult.errors.length,
|
|
347
|
-
errors: mappingResult.errors.slice(0, 5) // First 5 errors
|
|
348
|
-
});
|
|
349
|
-
// Skip to next file on mapping failure
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
logger.info(`Transformed ${mappingResult.data.length} records`);
|
|
354
|
-
|
|
355
|
-
// Step 6c: Create Fluent Commerce job with retry
|
|
356
|
-
let job: any;
|
|
357
|
-
try {
|
|
358
|
-
job = await client.createJob({
|
|
359
|
-
name: `Inventory Import - ${file.path}`,
|
|
360
|
-
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
361
|
-
});
|
|
362
|
-
logger.info(`Created job: ${job.id}`);
|
|
363
|
-
} catch (error) {
|
|
364
|
-
logger.error('Failed to create Fluent job', {
|
|
365
|
-
file: file.path,
|
|
366
|
-
error: error.message
|
|
367
|
-
});
|
|
368
|
-
continue;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// Step 6d: Send batch with rate limiting and validation error handling
|
|
372
|
-
let batch: any;
|
|
373
|
-
try {
|
|
374
|
-
batch = await client.sendBatch(job.id, {
|
|
375
|
-
action: 'UPSERT', // String, not enum
|
|
376
|
-
entityType: 'INVENTORY', // String, not enum
|
|
377
|
-
source: 'S3_CSV_IMPORT', // REQUIRED - Source system identifier
|
|
378
|
-
event: 'INVENTORY_UPDATE', // REQUIRED - Event type identifier
|
|
379
|
-
entities: mappingResult.data, // ✅ Validated InventoryPositionInput[]
|
|
380
|
-
});
|
|
381
|
-
logger.info(`Batch sent: ${batch.id}`);
|
|
382
|
-
} catch (error) {
|
|
383
|
-
if (error.code === 'RATE_LIMIT_ERROR' || error.message.includes('rate limit')) {
|
|
384
|
-
logger.warn('Rate limit hit, waiting before retry', {
|
|
385
|
-
file: file.path,
|
|
386
|
-
jobId: job.id
|
|
387
|
-
});
|
|
388
|
-
// Wait 5 seconds before retry
|
|
389
|
-
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
390
|
-
try {
|
|
391
|
-
batch = await client.sendBatch(job.id, {
|
|
392
|
-
action: 'UPSERT',
|
|
393
|
-
entityType: 'INVENTORY',
|
|
394
|
-
source: 'S3_CSV_IMPORT',
|
|
395
|
-
event: 'INVENTORY_UPDATE',
|
|
396
|
-
entities: mappingResult.data,
|
|
397
|
-
});
|
|
398
|
-
logger.info(`Batch sent after retry: ${batch.id}`);
|
|
399
|
-
} catch (retryError) {
|
|
400
|
-
logger.error('Batch failed after retry', {
|
|
401
|
-
file: file.path,
|
|
402
|
-
jobId: job.id,
|
|
403
|
-
error: retryError.message
|
|
404
|
-
});
|
|
405
|
-
continue;
|
|
406
|
-
}
|
|
407
|
-
} else if (error.code === 'VALIDATION_ERROR') {
|
|
408
|
-
logger.error('Batch validation failed - data does not match schema', {
|
|
409
|
-
file: file.path,
|
|
410
|
-
jobId: job.id,
|
|
411
|
-
error: error.message
|
|
412
|
-
});
|
|
413
|
-
continue;
|
|
414
|
-
} else {
|
|
415
|
-
logger.error('Batch submission failed', {
|
|
416
|
-
file: file.path,
|
|
417
|
-
jobId: job.id,
|
|
418
|
-
error: error.message,
|
|
419
|
-
errorCode: error.code
|
|
420
|
-
});
|
|
421
|
-
continue;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// Step 6e: Monitor batch status with timeout and error handling
|
|
426
|
-
let status: any;
|
|
427
|
-
try {
|
|
428
|
-
status = await client.getBatchStatus(job.id, batch.id);
|
|
429
|
-
logger.info(`Initial batch status: ${status.status}`);
|
|
430
|
-
} catch (error) {
|
|
431
|
-
logger.error('Failed to get batch status', {
|
|
432
|
-
file: file.path,
|
|
433
|
-
jobId: job.id,
|
|
434
|
-
batchId: batch.id,
|
|
435
|
-
error: error.message
|
|
436
|
-
});
|
|
437
|
-
continue;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// Poll for completion with timeout (simplified - see Module 6 for production pattern)
|
|
441
|
-
const startTime = Date.now();
|
|
442
|
-
const timeout = 300000; // 5 minutes
|
|
443
|
-
|
|
444
|
-
while (status.status === 'PENDING' || status.status === 'PROCESSING') {
|
|
445
|
-
if (Date.now() - startTime > timeout) {
|
|
446
|
-
logger.error('Batch processing timeout', {
|
|
447
|
-
file: file.path,
|
|
448
|
-
jobId: job.id,
|
|
449
|
-
batchId: batch.id,
|
|
450
|
-
timeoutMs: timeout
|
|
451
|
-
});
|
|
452
|
-
break;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5s
|
|
456
|
-
|
|
457
|
-
try {
|
|
458
|
-
status = await client.getBatchStatus(job.id, batch.id);
|
|
459
|
-
logger.info(`Batch status: ${status.status}`);
|
|
460
|
-
} catch (error) {
|
|
461
|
-
logger.error('Failed to poll batch status', {
|
|
462
|
-
file: file.path,
|
|
463
|
-
jobId: job.id,
|
|
464
|
-
batchId: batch.id,
|
|
465
|
-
error: error.message
|
|
466
|
-
});
|
|
467
|
-
break;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
if (status.status === 'COMPLETED') {
|
|
472
|
-
logger.info(
|
|
473
|
-
`✅ Successfully ingested ${mappingResult.data.length} records from ${file.path}`
|
|
474
|
-
);
|
|
475
|
-
} else if (status.status === 'FAILED') {
|
|
476
|
-
logger.error(`❌ Batch failed with errors`, {
|
|
477
|
-
file: file.path,
|
|
478
|
-
jobId: job.id,
|
|
479
|
-
batchId: batch.id,
|
|
480
|
-
errors: status.errors || []
|
|
481
|
-
});
|
|
482
|
-
} else {
|
|
483
|
-
logger.warn(`⚠️ Batch ended with unexpected status: ${status.status}`, {
|
|
484
|
-
file: file.path,
|
|
485
|
-
jobId: job.id,
|
|
486
|
-
batchId: batch.id
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
} catch (fileError) {
|
|
490
|
-
logger.error('File processing failed', {
|
|
491
|
-
file: file.path,
|
|
492
|
-
error: fileError.message,
|
|
493
|
-
stack: fileError.stack
|
|
494
|
-
});
|
|
495
|
-
// Continue to next file
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
logger.info('Ingestion complete!');
|
|
500
|
-
} catch (error) {
|
|
501
|
-
logger.error('Critical ingestion failure', {
|
|
502
|
-
error: error.message,
|
|
503
|
-
errorType: error.constructor.name,
|
|
504
|
-
stack: error.stack
|
|
505
|
-
});
|
|
506
|
-
throw error;
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// Run ingestion
|
|
511
|
-
ingestInventory().catch(error => {
|
|
512
|
-
console.error('Fatal error:', error);
|
|
513
|
-
process.exit(1);
|
|
514
|
-
});
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
---
|
|
518
|
-
|
|
519
|
-
## Step 7: Run Your First Ingestion
|
|
520
|
-
|
|
521
|
-
Execute the script:
|
|
522
|
-
|
|
523
|
-
```bash
|
|
524
|
-
npx ts-node ingest-inventory.ts
|
|
525
|
-
```
|
|
526
|
-
|
|
527
|
-
**Expected output:**
|
|
528
|
-
|
|
529
|
-
```
|
|
530
|
-
[INFO] Initializing Fluent client...
|
|
531
|
-
[INFO] Initializing S3 data source...
|
|
532
|
-
[INFO] Listing files in s3://your-bucket/data/
|
|
533
|
-
[INFO] Found 1 files
|
|
534
|
-
[INFO] Processing file: data/inventory-2025-01-19.csv
|
|
535
|
-
[INFO] Parsed 5 records from CSV
|
|
536
|
-
[INFO] Transformed 5 records
|
|
537
|
-
[INFO] Created job: JOB-12345
|
|
538
|
-
[INFO] Batch sent: BATCH-67890
|
|
539
|
-
[INFO] Initial batch status: PENDING
|
|
540
|
-
[INFO] Batch status: PROCESSING
|
|
541
|
-
[INFO] Batch status: COMPLETED
|
|
542
|
-
[INFO] ✅ Successfully ingested 5 records from data/inventory-2025-01-19.csv
|
|
543
|
-
[INFO] Ingestion complete!
|
|
544
|
-
```
|
|
545
|
-
|
|
546
|
-
---
|
|
547
|
-
|
|
548
|
-
## What Just Happened?
|
|
549
|
-
|
|
550
|
-
Your script performed the following steps:
|
|
551
|
-
|
|
552
|
-
1. **Connected to Fluent Commerce** - OAuth2 authentication with client credentials
|
|
553
|
-
2. **Connected to S3** - Listed files in the specified bucket/prefix
|
|
554
|
-
3. **Downloaded CSV** - Retrieved file content from S3
|
|
555
|
-
4. **Parsed CSV** - Converted CSV rows to JavaScript objects
|
|
556
|
-
5. **Transformed Data** - Mapped source fields to Fluent schema using UniversalMapper
|
|
557
|
-
6. **Validated Schema** - Ensured all required fields present and correct types
|
|
558
|
-
7. **Created Job** - Prepared a Batch API job for processing
|
|
559
|
-
8. **Sent Batch** - Submitted inventory positions to Fluent Commerce
|
|
560
|
-
9. **Monitored Status** - Polled until batch completed successfully
|
|
561
|
-
|
|
562
|
-
**Key Concepts Introduced:**
|
|
563
|
-
|
|
564
|
-
- ✅ `createClient()` - Universal client factory (auto-detects Versori vs standalone)
|
|
565
|
-
- ✅ `S3DataSource` - Read files from S3 buckets
|
|
566
|
-
- ✅ `CSVParserService` - Parse CSV with headers and validation
|
|
567
|
-
- ✅ `UniversalMapper` - Transform source → Fluent schema
|
|
568
|
-
- ✅ Custom resolvers - Business logic transformations (`custom.mapStatus`)
|
|
569
|
-
- ✅ Batch API - UPSERT inventory positions
|
|
570
|
-
- ✅ Job lifecycle - Create → Send Batch → Monitor Status
|
|
571
|
-
|
|
572
|
-
---
|
|
573
|
-
|
|
574
|
-
## Troubleshooting
|
|
575
|
-
|
|
576
|
-
### Issue: "Invalid credentials"
|
|
577
|
-
|
|
578
|
-
**Problem**: OAuth2 authentication failed
|
|
579
|
-
|
|
580
|
-
**Solution**:
|
|
581
|
-
|
|
582
|
-
```bash
|
|
583
|
-
# Verify credentials are correct
|
|
584
|
-
echo $FLUENT_CLIENT_ID
|
|
585
|
-
echo $FLUENT_BASE_URL
|
|
586
|
-
|
|
587
|
-
# Test authentication manually
|
|
588
|
-
npx @fluentcommerce/fc-connect-sdk introspect-schema \
|
|
589
|
-
--url $FLUENT_BASE_URL/graphql \
|
|
590
|
-
--client-id $FLUENT_CLIENT_ID \
|
|
591
|
-
--client-secret $FLUENT_CLIENT_SECRET
|
|
592
|
-
```
|
|
593
|
-
|
|
594
|
-
### Issue: "Mapping validation failed"
|
|
595
|
-
|
|
596
|
-
**Problem**: Field mappings don't match schema
|
|
597
|
-
|
|
598
|
-
**Solution**:
|
|
599
|
-
|
|
600
|
-
```bash
|
|
601
|
-
# Re-run schema validation
|
|
602
|
-
npx @fluentcommerce/fc-connect-sdk validate-schema \
|
|
603
|
-
--mapping field-mappings.json \
|
|
604
|
-
--schema schema.json
|
|
605
|
-
|
|
606
|
-
# Check error output for specific field mismatches
|
|
607
|
-
```
|
|
608
|
-
|
|
609
|
-
### Issue: "Missing required field: locationRef"
|
|
610
|
-
|
|
611
|
-
**Problem**: CSV missing required column
|
|
612
|
-
|
|
613
|
-
**Solution**:
|
|
614
|
-
|
|
615
|
-
```typescript
|
|
616
|
-
// Add validation before mapping
|
|
617
|
-
if (!records.every(r => r.warehouse)) {
|
|
618
|
-
throw new Error('CSV missing required column: warehouse');
|
|
619
|
-
}
|
|
620
|
-
```
|
|
621
|
-
|
|
622
|
-
### Issue: "Batch status: FAILED"
|
|
623
|
-
|
|
624
|
-
**Problem**: Batch processing failed in Fluent Commerce
|
|
625
|
-
|
|
626
|
-
**Solution**:
|
|
627
|
-
|
|
628
|
-
```typescript
|
|
629
|
-
// Get detailed error information
|
|
630
|
-
const jobStatus = await client.getJobStatus(job.id);
|
|
631
|
-
console.log('Job errors:', jobStatus.errors);
|
|
632
|
-
|
|
633
|
-
// Check batch-specific errors
|
|
634
|
-
const batchDetails = await client.getBatchStatus(job.id, batch.id);
|
|
635
|
-
console.log('Batch errors:', batchDetails.errors);
|
|
636
|
-
```
|
|
637
|
-
|
|
638
|
-
---
|
|
639
|
-
|
|
640
|
-
## Next Steps
|
|
641
|
-
|
|
642
|
-
Now that you have a working ingestion workflow, explore:
|
|
643
|
-
|
|
644
|
-
- **[Module 3: Data Sources](./02-core-guides-ingestion-03-data-sources.md)** - SFTP, local files, and custom sources
|
|
645
|
-
- **[Module 4: Field Mapping](./02-core-guides-ingestion-04-field-mapping.md)** - Advanced mapping patterns and resolvers
|
|
646
|
-
- **[Module 6: Batch API](./02-core-guides-ingestion-06-batch-api.md)** - Complete job lifecycle and optimization
|
|
647
|
-
- **[Module 7: State Management](./02-core-guides-ingestion-07-state-management.md)** - Prevent duplicate processing
|
|
648
|
-
|
|
649
|
-
---
|
|
650
|
-
|
|
651
|
-
[← Previous: Introduction](./02-core-guides-ingestion-01-introduction.md) | [Back to Guide](../ingestion-readme.md) | [Next: Data Sources →](./02-core-guides-ingestion-03-data-sources.md)
|
|
652
|
-
|
|
653
|
-
## Related Documentation
|
|
654
|
-
|
|
655
|
-
- [S3 Operations Guide](../../data-sources/modules/data-sources-02-s3-operations.md) - Advanced S3 patterns
|
|
656
|
-
- [Universal Mapping Guide](../../mapping/mapping-readme.md) - Complete mapping reference
|
|
657
|
-
- [CSV Parser Guide](../../parsers/modules/02-core-guides-parsers-02-csv-parser.md) - CSV parsing options
|
|
658
|
-
- [Batch API Reference](../../api-reference/modules/api-reference-01-client-api.md#job-batch-operations) - Complete API documentation
|
|
1
|
+
# Module 2: Quick Start - Your First Ingestion
|
|
2
|
+
|
|
3
|
+
[← Back to Ingestion Guide](../ingestion-readme.md)
|
|
4
|
+
|
|
5
|
+
**Module 2 of 9** | **Level**: Beginner | **Time**: 15 minutes
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
This module walks you through creating your first complete ingestion workflow: reading a CSV file from S3, transforming it with UniversalMapper, and sending it to Fluent Commerce using the Batch API.
|
|
12
|
+
|
|
13
|
+
## Learning Objectives
|
|
14
|
+
|
|
15
|
+
By the end of this module, you will:
|
|
16
|
+
|
|
17
|
+
- ✅ Install and configure the FC Connect SDK
|
|
18
|
+
- ✅ Create a complete S3 → CSV → Batch API workflow
|
|
19
|
+
- ✅ Understand the basic ingestion pattern
|
|
20
|
+
- ✅ Validate field mappings against the schema
|
|
21
|
+
- ✅ Send your first batch to Fluent Commerce
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Prerequisites
|
|
26
|
+
|
|
27
|
+
Before starting, ensure you have:
|
|
28
|
+
|
|
29
|
+
1. **Node.js** >= 18.0.0 installed
|
|
30
|
+
2. **Fluent Commerce credentials**:
|
|
31
|
+
- API Base URL (e.g., `https://yourcompany.api.fluentcommerce.com`)
|
|
32
|
+
- OAuth2 Client ID
|
|
33
|
+
- OAuth2 Client Secret
|
|
34
|
+
- Retailer ID
|
|
35
|
+
3. **AWS S3 access** (or local CSV file for testing):
|
|
36
|
+
- Access Key ID
|
|
37
|
+
- Secret Access Key
|
|
38
|
+
- Bucket name
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Step 1: Installation
|
|
43
|
+
|
|
44
|
+
Install the FC Connect SDK:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install @fluentcommerce/fc-connect-sdk
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Verify installation:**
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npx @fluentcommerce/fc-connect-sdk --version
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Step 2: Environment Configuration
|
|
59
|
+
|
|
60
|
+
Create a `.env` file with your credentials:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Fluent Commerce OAuth2 (Password Grant)
|
|
64
|
+
FLUENT_BASE_URL=https://yourcompany.api.fluentcommerce.com
|
|
65
|
+
FLUENT_CLIENT_ID=your-oauth-client-id
|
|
66
|
+
FLUENT_CLIENT_SECRET=your-oauth-client-secret
|
|
67
|
+
FLUENT_USERNAME=your-username # ✅ REQUIRED for password grant
|
|
68
|
+
FLUENT_PASSWORD=your-password # ✅ REQUIRED for password grant
|
|
69
|
+
FLUENT_RETAILER_ID=1
|
|
70
|
+
|
|
71
|
+
# AWS S3 (source)
|
|
72
|
+
AWS_ACCESS_KEY_ID=your-aws-access-key
|
|
73
|
+
AWS_SECRET_ACCESS_KEY=your-aws-secret-key
|
|
74
|
+
AWS_REGION=us-east-1
|
|
75
|
+
S3_BUCKET=your-inventory-bucket
|
|
76
|
+
S3_PREFIX=data/
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Load environment variables:**
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm install dotenv
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Step 3: Prepare Sample Data
|
|
88
|
+
|
|
89
|
+
Create a sample CSV file (`sample-inventory.csv`):
|
|
90
|
+
|
|
91
|
+
```csv
|
|
92
|
+
sku,warehouse,quantity,status
|
|
93
|
+
SKU-WM-001,WH-001,500,in_stock
|
|
94
|
+
SKU-WM-002,WH-001,150,in_stock
|
|
95
|
+
SKU-KB-001,WH-001,75,reserved
|
|
96
|
+
SKU-WM-003,WH-002,300,discontinued
|
|
97
|
+
SKU-WM-004,WH-002,200,in_stock
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Upload to S3** (or keep local for testing):
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
aws s3 cp sample-inventory.csv s3://your-bucket/data/inventory-2025-01-19.csv
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Step 4: Create Field Mapping Configuration
|
|
109
|
+
|
|
110
|
+
Create `field-mappings.json`:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"fields": {
|
|
115
|
+
"ref": {
|
|
116
|
+
"source": "sku",
|
|
117
|
+
"required": true,
|
|
118
|
+
"comment": "✅ InventoryPositionInput.ref (String! required) - Position reference"
|
|
119
|
+
},
|
|
120
|
+
"productRef": {
|
|
121
|
+
"source": "sku",
|
|
122
|
+
"required": true,
|
|
123
|
+
"comment": "✅ InventoryPositionInput.productRef (String! required) - Product SKU"
|
|
124
|
+
},
|
|
125
|
+
"locationRef": {
|
|
126
|
+
"source": "warehouse",
|
|
127
|
+
"required": true,
|
|
128
|
+
"comment": "✅ InventoryPositionInput.locationRef (String! required) - Warehouse code"
|
|
129
|
+
},
|
|
130
|
+
"qty": {
|
|
131
|
+
"source": "quantity",
|
|
132
|
+
"resolver": "sdk.parseInt",
|
|
133
|
+
"required": true,
|
|
134
|
+
"comment": "✅ InventoryPositionInput.qty (Int! required) - Available quantity"
|
|
135
|
+
},
|
|
136
|
+
"status": {
|
|
137
|
+
"source": "status",
|
|
138
|
+
"resolver": "custom.mapStatus",
|
|
139
|
+
"defaultValue": "AVAILABLE",
|
|
140
|
+
"comment": "✅ InventoryPositionInput.status (String optional) - Position status"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Step 5: Validate Field Mapping Against Schema
|
|
149
|
+
|
|
150
|
+
**CRITICAL**: Before running ingestion, validate your mapping:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Step 1: Introspect Fluent Commerce schema
|
|
154
|
+
npx @fluentcommerce/fc-connect-sdk introspect-schema \
|
|
155
|
+
--url https://yourcompany.api.fluentcommerce.com/graphql \
|
|
156
|
+
--client-id $FLUENT_CLIENT_ID \
|
|
157
|
+
--client-secret $FLUENT_CLIENT_SECRET \
|
|
158
|
+
--output schema.json
|
|
159
|
+
|
|
160
|
+
# Step 2: Validate field-mappings.json against schema
|
|
161
|
+
npx @fluentcommerce/fc-connect-sdk validate-schema \
|
|
162
|
+
--mapping field-mappings.json \
|
|
163
|
+
--schema schema.json
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Expected output:**
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
✅ Mapping validation successful
|
|
170
|
+
✅ All required fields present: ref, productRef, locationRef, qty
|
|
171
|
+
✅ All field types compatible with InventoryPositionInput schema
|
|
172
|
+
✅ No unknown fields detected
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Preflight Validation (NEW)
|
|
176
|
+
|
|
177
|
+
Run a preflight validation to catch misconfigurations before execution.
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
import { PreflightValidator } from '@fluentcommerce/fc-connect-sdk';
|
|
181
|
+
|
|
182
|
+
const validator = new PreflightValidator(logger);
|
|
183
|
+
await validator.validate({
|
|
184
|
+
fluent: { client },
|
|
185
|
+
sftp: { host: process.env.SFTP_HOST, username: process.env.SFTP_USERNAME },
|
|
186
|
+
config: { processedPath: process.env.PROCESSED_PATH, errorsPath: process.env.ERRORS_PATH },
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Checks performed:
|
|
191
|
+
|
|
192
|
+
- Fluent client reachability/auth
|
|
193
|
+
- SFTP connectivity and directory writability (create directories if missing)
|
|
194
|
+
- Required activation/env variables present
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Step 6: Complete Ingestion Script
|
|
199
|
+
|
|
200
|
+
Create `ingest-inventory.ts`:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import 'dotenv/config';
|
|
204
|
+
import {
|
|
205
|
+
createClient,
|
|
206
|
+
S3DataSource,
|
|
207
|
+
CSVParserService,
|
|
208
|
+
UniversalMapper,
|
|
209
|
+
createConsoleLogger,
|
|
210
|
+
toStructuredLogger
|
|
211
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
212
|
+
|
|
213
|
+
// Custom resolver for status mapping
|
|
214
|
+
const customResolvers = {
|
|
215
|
+
'custom.mapStatus': (value: string) => {
|
|
216
|
+
const statusMap: Record<string, string> = {
|
|
217
|
+
in_stock: 'AVAILABLE',
|
|
218
|
+
out_of_stock: 'ON_HOLD',
|
|
219
|
+
discontinued: 'DISCONTINUED',
|
|
220
|
+
reserved: 'RESERVED',
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const mapped = statusMap[String(value).toLowerCase()];
|
|
224
|
+
if (!mapped) {
|
|
225
|
+
throw new Error(`Unknown status: ${value}`);
|
|
226
|
+
}
|
|
227
|
+
return mapped;
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
async function ingestInventory() {
|
|
232
|
+
const logger = toStructuredLogger(createConsoleLogger(), {
|
|
233
|
+
service: 'inventory-ingestion',
|
|
234
|
+
correlationId: generateCorrelationId()
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
// Step 1: Initialize Fluent client with OAuth2 password grant
|
|
239
|
+
logger.info('Initializing Fluent client...');
|
|
240
|
+
const client = await createClient({
|
|
241
|
+
config: {
|
|
242
|
+
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
243
|
+
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
244
|
+
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
245
|
+
username: process.env.FLUENT_USERNAME!, // ✅ REQUIRED for password grant
|
|
246
|
+
password: process.env.FLUENT_PASSWORD!, // ✅ REQUIRED for password grant
|
|
247
|
+
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Step 2: Initialize S3 data source with retry logic
|
|
252
|
+
logger.info('Initializing S3 data source...');
|
|
253
|
+
let s3: S3DataSource;
|
|
254
|
+
try {
|
|
255
|
+
s3 = new S3DataSource(
|
|
256
|
+
{
|
|
257
|
+
type: 'S3_CSV',
|
|
258
|
+
connectionId: 's3-inventory',
|
|
259
|
+
name: 'S3 Inventory Source',
|
|
260
|
+
s3Config: {
|
|
261
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
262
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
263
|
+
region: process.env.AWS_REGION!,
|
|
264
|
+
bucket: process.env.S3_BUCKET!,
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
logger
|
|
268
|
+
);
|
|
269
|
+
} catch (error) {
|
|
270
|
+
logger.error('Failed to initialize S3 data source', {
|
|
271
|
+
error: error.message,
|
|
272
|
+
bucket: process.env.S3_BUCKET,
|
|
273
|
+
region: process.env.AWS_REGION
|
|
274
|
+
});
|
|
275
|
+
throw new Error(`S3 initialization failed: ${error.message}`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Step 3: Initialize CSV parser
|
|
279
|
+
const parser = new CSVParserService(logger);
|
|
280
|
+
// Options are passed to parse() method, not constructor
|
|
281
|
+
|
|
282
|
+
// Step 4: Load field mapping configuration
|
|
283
|
+
const mappingConfig = require('./field-mappings.json');
|
|
284
|
+
const mapper = new UniversalMapper(mappingConfig, { customResolvers });
|
|
285
|
+
|
|
286
|
+
// Step 5: List files in S3 with error handling
|
|
287
|
+
logger.info(`Listing files in s3://${process.env.S3_BUCKET}/${process.env.S3_PREFIX}`);
|
|
288
|
+
let files: any[];
|
|
289
|
+
try {
|
|
290
|
+
files = await s3.listFiles({ prefix: process.env.S3_PREFIX });
|
|
291
|
+
logger.info(`Found ${files.length} files`);
|
|
292
|
+
} catch (error) {
|
|
293
|
+
logger.error('Failed to list S3 files', {
|
|
294
|
+
error: error.message,
|
|
295
|
+
bucket: process.env.S3_BUCKET,
|
|
296
|
+
prefix: process.env.S3_PREFIX
|
|
297
|
+
});
|
|
298
|
+
throw new Error(`S3 file listing failed: ${error.message}`);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Step 6: Process each file with comprehensive error handling
|
|
302
|
+
for (const file of files) {
|
|
303
|
+
logger.info(`Processing file: ${file.path}`);
|
|
304
|
+
|
|
305
|
+
try {
|
|
306
|
+
// Step 6a: Download and parse CSV with error recovery
|
|
307
|
+
let csvData: string;
|
|
308
|
+
let records: any[];
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
csvData = await s3.downloadFile(file.path);
|
|
312
|
+
logger.info(`Downloaded file: ${file.path} (${csvData.length} bytes)`);
|
|
313
|
+
} catch (error) {
|
|
314
|
+
logger.error('Failed to download file from S3', {
|
|
315
|
+
file: file.path,
|
|
316
|
+
error: error.message
|
|
317
|
+
});
|
|
318
|
+
// Skip to next file on download failure
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
try {
|
|
323
|
+
records = await parser.parse(csvData);
|
|
324
|
+
logger.info(`Parsed ${records.length} records from CSV`);
|
|
325
|
+
|
|
326
|
+
if (records.length === 0) {
|
|
327
|
+
logger.warn('No records found in CSV file', { file: file.path });
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
} catch (error) {
|
|
331
|
+
logger.error('CSV parsing failed', {
|
|
332
|
+
file: file.path,
|
|
333
|
+
error: error.message,
|
|
334
|
+
errorType: error.constructor.name
|
|
335
|
+
});
|
|
336
|
+
// Skip to next file on parse failure
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Step 6b: Transform data with UniversalMapper
|
|
341
|
+
const mappingResult = await mapper.map(records);
|
|
342
|
+
|
|
343
|
+
if (!mappingResult.success) {
|
|
344
|
+
logger.error('Mapping errors detected', {
|
|
345
|
+
file: file.path,
|
|
346
|
+
errorCount: mappingResult.errors.length,
|
|
347
|
+
errors: mappingResult.errors.slice(0, 5) // First 5 errors
|
|
348
|
+
});
|
|
349
|
+
// Skip to next file on mapping failure
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
logger.info(`Transformed ${mappingResult.data.length} records`);
|
|
354
|
+
|
|
355
|
+
// Step 6c: Create Fluent Commerce job with retry
|
|
356
|
+
let job: any;
|
|
357
|
+
try {
|
|
358
|
+
job = await client.createJob({
|
|
359
|
+
name: `Inventory Import - ${file.path}`,
|
|
360
|
+
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
361
|
+
});
|
|
362
|
+
logger.info(`Created job: ${job.id}`);
|
|
363
|
+
} catch (error) {
|
|
364
|
+
logger.error('Failed to create Fluent job', {
|
|
365
|
+
file: file.path,
|
|
366
|
+
error: error.message
|
|
367
|
+
});
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Step 6d: Send batch with rate limiting and validation error handling
|
|
372
|
+
let batch: any;
|
|
373
|
+
try {
|
|
374
|
+
batch = await client.sendBatch(job.id, {
|
|
375
|
+
action: 'UPSERT', // String, not enum
|
|
376
|
+
entityType: 'INVENTORY', // String, not enum
|
|
377
|
+
source: 'S3_CSV_IMPORT', // REQUIRED - Source system identifier
|
|
378
|
+
event: 'INVENTORY_UPDATE', // REQUIRED - Event type identifier
|
|
379
|
+
entities: mappingResult.data, // ✅ Validated InventoryPositionInput[]
|
|
380
|
+
});
|
|
381
|
+
logger.info(`Batch sent: ${batch.id}`);
|
|
382
|
+
} catch (error) {
|
|
383
|
+
if (error.code === 'RATE_LIMIT_ERROR' || error.message.includes('rate limit')) {
|
|
384
|
+
logger.warn('Rate limit hit, waiting before retry', {
|
|
385
|
+
file: file.path,
|
|
386
|
+
jobId: job.id
|
|
387
|
+
});
|
|
388
|
+
// Wait 5 seconds before retry
|
|
389
|
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
390
|
+
try {
|
|
391
|
+
batch = await client.sendBatch(job.id, {
|
|
392
|
+
action: 'UPSERT',
|
|
393
|
+
entityType: 'INVENTORY',
|
|
394
|
+
source: 'S3_CSV_IMPORT',
|
|
395
|
+
event: 'INVENTORY_UPDATE',
|
|
396
|
+
entities: mappingResult.data,
|
|
397
|
+
});
|
|
398
|
+
logger.info(`Batch sent after retry: ${batch.id}`);
|
|
399
|
+
} catch (retryError) {
|
|
400
|
+
logger.error('Batch failed after retry', {
|
|
401
|
+
file: file.path,
|
|
402
|
+
jobId: job.id,
|
|
403
|
+
error: retryError.message
|
|
404
|
+
});
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
} else if (error.code === 'VALIDATION_ERROR') {
|
|
408
|
+
logger.error('Batch validation failed - data does not match schema', {
|
|
409
|
+
file: file.path,
|
|
410
|
+
jobId: job.id,
|
|
411
|
+
error: error.message
|
|
412
|
+
});
|
|
413
|
+
continue;
|
|
414
|
+
} else {
|
|
415
|
+
logger.error('Batch submission failed', {
|
|
416
|
+
file: file.path,
|
|
417
|
+
jobId: job.id,
|
|
418
|
+
error: error.message,
|
|
419
|
+
errorCode: error.code
|
|
420
|
+
});
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Step 6e: Monitor batch status with timeout and error handling
|
|
426
|
+
let status: any;
|
|
427
|
+
try {
|
|
428
|
+
status = await client.getBatchStatus(job.id, batch.id);
|
|
429
|
+
logger.info(`Initial batch status: ${status.status}`);
|
|
430
|
+
} catch (error) {
|
|
431
|
+
logger.error('Failed to get batch status', {
|
|
432
|
+
file: file.path,
|
|
433
|
+
jobId: job.id,
|
|
434
|
+
batchId: batch.id,
|
|
435
|
+
error: error.message
|
|
436
|
+
});
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Poll for completion with timeout (simplified - see Module 6 for production pattern)
|
|
441
|
+
const startTime = Date.now();
|
|
442
|
+
const timeout = 300000; // 5 minutes
|
|
443
|
+
|
|
444
|
+
while (status.status === 'PENDING' || status.status === 'PROCESSING') {
|
|
445
|
+
if (Date.now() - startTime > timeout) {
|
|
446
|
+
logger.error('Batch processing timeout', {
|
|
447
|
+
file: file.path,
|
|
448
|
+
jobId: job.id,
|
|
449
|
+
batchId: batch.id,
|
|
450
|
+
timeoutMs: timeout
|
|
451
|
+
});
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5s
|
|
456
|
+
|
|
457
|
+
try {
|
|
458
|
+
status = await client.getBatchStatus(job.id, batch.id);
|
|
459
|
+
logger.info(`Batch status: ${status.status}`);
|
|
460
|
+
} catch (error) {
|
|
461
|
+
logger.error('Failed to poll batch status', {
|
|
462
|
+
file: file.path,
|
|
463
|
+
jobId: job.id,
|
|
464
|
+
batchId: batch.id,
|
|
465
|
+
error: error.message
|
|
466
|
+
});
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (status.status === 'COMPLETED') {
|
|
472
|
+
logger.info(
|
|
473
|
+
`✅ Successfully ingested ${mappingResult.data.length} records from ${file.path}`
|
|
474
|
+
);
|
|
475
|
+
} else if (status.status === 'FAILED') {
|
|
476
|
+
logger.error(`❌ Batch failed with errors`, {
|
|
477
|
+
file: file.path,
|
|
478
|
+
jobId: job.id,
|
|
479
|
+
batchId: batch.id,
|
|
480
|
+
errors: status.errors || []
|
|
481
|
+
});
|
|
482
|
+
} else {
|
|
483
|
+
logger.warn(`⚠️ Batch ended with unexpected status: ${status.status}`, {
|
|
484
|
+
file: file.path,
|
|
485
|
+
jobId: job.id,
|
|
486
|
+
batchId: batch.id
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
} catch (fileError) {
|
|
490
|
+
logger.error('File processing failed', {
|
|
491
|
+
file: file.path,
|
|
492
|
+
error: fileError.message,
|
|
493
|
+
stack: fileError.stack
|
|
494
|
+
});
|
|
495
|
+
// Continue to next file
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
logger.info('Ingestion complete!');
|
|
500
|
+
} catch (error) {
|
|
501
|
+
logger.error('Critical ingestion failure', {
|
|
502
|
+
error: error.message,
|
|
503
|
+
errorType: error.constructor.name,
|
|
504
|
+
stack: error.stack
|
|
505
|
+
});
|
|
506
|
+
throw error;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Run ingestion
|
|
511
|
+
ingestInventory().catch(error => {
|
|
512
|
+
console.error('Fatal error:', error);
|
|
513
|
+
process.exit(1);
|
|
514
|
+
});
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
## Step 7: Run Your First Ingestion
|
|
520
|
+
|
|
521
|
+
Execute the script:
|
|
522
|
+
|
|
523
|
+
```bash
|
|
524
|
+
npx ts-node ingest-inventory.ts
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
**Expected output:**
|
|
528
|
+
|
|
529
|
+
```
|
|
530
|
+
[INFO] Initializing Fluent client...
|
|
531
|
+
[INFO] Initializing S3 data source...
|
|
532
|
+
[INFO] Listing files in s3://your-bucket/data/
|
|
533
|
+
[INFO] Found 1 files
|
|
534
|
+
[INFO] Processing file: data/inventory-2025-01-19.csv
|
|
535
|
+
[INFO] Parsed 5 records from CSV
|
|
536
|
+
[INFO] Transformed 5 records
|
|
537
|
+
[INFO] Created job: JOB-12345
|
|
538
|
+
[INFO] Batch sent: BATCH-67890
|
|
539
|
+
[INFO] Initial batch status: PENDING
|
|
540
|
+
[INFO] Batch status: PROCESSING
|
|
541
|
+
[INFO] Batch status: COMPLETED
|
|
542
|
+
[INFO] ✅ Successfully ingested 5 records from data/inventory-2025-01-19.csv
|
|
543
|
+
[INFO] Ingestion complete!
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
---
|
|
547
|
+
|
|
548
|
+
## What Just Happened?
|
|
549
|
+
|
|
550
|
+
Your script performed the following steps:
|
|
551
|
+
|
|
552
|
+
1. **Connected to Fluent Commerce** - OAuth2 authentication with client credentials
|
|
553
|
+
2. **Connected to S3** - Listed files in the specified bucket/prefix
|
|
554
|
+
3. **Downloaded CSV** - Retrieved file content from S3
|
|
555
|
+
4. **Parsed CSV** - Converted CSV rows to JavaScript objects
|
|
556
|
+
5. **Transformed Data** - Mapped source fields to Fluent schema using UniversalMapper
|
|
557
|
+
6. **Validated Schema** - Ensured all required fields present and correct types
|
|
558
|
+
7. **Created Job** - Prepared a Batch API job for processing
|
|
559
|
+
8. **Sent Batch** - Submitted inventory positions to Fluent Commerce
|
|
560
|
+
9. **Monitored Status** - Polled until batch completed successfully
|
|
561
|
+
|
|
562
|
+
**Key Concepts Introduced:**
|
|
563
|
+
|
|
564
|
+
- ✅ `createClient()` - Universal client factory (auto-detects Versori vs standalone)
|
|
565
|
+
- ✅ `S3DataSource` - Read files from S3 buckets
|
|
566
|
+
- ✅ `CSVParserService` - Parse CSV with headers and validation
|
|
567
|
+
- ✅ `UniversalMapper` - Transform source → Fluent schema
|
|
568
|
+
- ✅ Custom resolvers - Business logic transformations (`custom.mapStatus`)
|
|
569
|
+
- ✅ Batch API - UPSERT inventory positions
|
|
570
|
+
- ✅ Job lifecycle - Create → Send Batch → Monitor Status
|
|
571
|
+
|
|
572
|
+
---
|
|
573
|
+
|
|
574
|
+
## Troubleshooting
|
|
575
|
+
|
|
576
|
+
### Issue: "Invalid credentials"
|
|
577
|
+
|
|
578
|
+
**Problem**: OAuth2 authentication failed
|
|
579
|
+
|
|
580
|
+
**Solution**:
|
|
581
|
+
|
|
582
|
+
```bash
|
|
583
|
+
# Verify credentials are correct
|
|
584
|
+
echo $FLUENT_CLIENT_ID
|
|
585
|
+
echo $FLUENT_BASE_URL
|
|
586
|
+
|
|
587
|
+
# Test authentication manually
|
|
588
|
+
npx @fluentcommerce/fc-connect-sdk introspect-schema \
|
|
589
|
+
--url $FLUENT_BASE_URL/graphql \
|
|
590
|
+
--client-id $FLUENT_CLIENT_ID \
|
|
591
|
+
--client-secret $FLUENT_CLIENT_SECRET
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
### Issue: "Mapping validation failed"
|
|
595
|
+
|
|
596
|
+
**Problem**: Field mappings don't match schema
|
|
597
|
+
|
|
598
|
+
**Solution**:
|
|
599
|
+
|
|
600
|
+
```bash
|
|
601
|
+
# Re-run schema validation
|
|
602
|
+
npx @fluentcommerce/fc-connect-sdk validate-schema \
|
|
603
|
+
--mapping field-mappings.json \
|
|
604
|
+
--schema schema.json
|
|
605
|
+
|
|
606
|
+
# Check error output for specific field mismatches
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
### Issue: "Missing required field: locationRef"
|
|
610
|
+
|
|
611
|
+
**Problem**: CSV missing required column
|
|
612
|
+
|
|
613
|
+
**Solution**:
|
|
614
|
+
|
|
615
|
+
```typescript
|
|
616
|
+
// Add validation before mapping
|
|
617
|
+
if (!records.every(r => r.warehouse)) {
|
|
618
|
+
throw new Error('CSV missing required column: warehouse');
|
|
619
|
+
}
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
### Issue: "Batch status: FAILED"
|
|
623
|
+
|
|
624
|
+
**Problem**: Batch processing failed in Fluent Commerce
|
|
625
|
+
|
|
626
|
+
**Solution**:
|
|
627
|
+
|
|
628
|
+
```typescript
|
|
629
|
+
// Get detailed error information
|
|
630
|
+
const jobStatus = await client.getJobStatus(job.id);
|
|
631
|
+
console.log('Job errors:', jobStatus.errors);
|
|
632
|
+
|
|
633
|
+
// Check batch-specific errors
|
|
634
|
+
const batchDetails = await client.getBatchStatus(job.id, batch.id);
|
|
635
|
+
console.log('Batch errors:', batchDetails.errors);
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
---
|
|
639
|
+
|
|
640
|
+
## Next Steps
|
|
641
|
+
|
|
642
|
+
Now that you have a working ingestion workflow, explore:
|
|
643
|
+
|
|
644
|
+
- **[Module 3: Data Sources](./02-core-guides-ingestion-03-data-sources.md)** - SFTP, local files, and custom sources
|
|
645
|
+
- **[Module 4: Field Mapping](./02-core-guides-ingestion-04-field-mapping.md)** - Advanced mapping patterns and resolvers
|
|
646
|
+
- **[Module 6: Batch API](./02-core-guides-ingestion-06-batch-api.md)** - Complete job lifecycle and optimization
|
|
647
|
+
- **[Module 7: State Management](./02-core-guides-ingestion-07-state-management.md)** - Prevent duplicate processing
|
|
648
|
+
|
|
649
|
+
---
|
|
650
|
+
|
|
651
|
+
[← Previous: Introduction](./02-core-guides-ingestion-01-introduction.md) | [Back to Guide](../ingestion-readme.md) | [Next: Data Sources →](./02-core-guides-ingestion-03-data-sources.md)
|
|
652
|
+
|
|
653
|
+
## Related Documentation
|
|
654
|
+
|
|
655
|
+
- [S3 Operations Guide](../../data-sources/modules/data-sources-02-s3-operations.md) - Advanced S3 patterns
|
|
656
|
+
- [Universal Mapping Guide](../../mapping/mapping-readme.md) - Complete mapping reference
|
|
657
|
+
- [CSV Parser Guide](../../parsers/modules/02-core-guides-parsers-02-csv-parser.md) - CSV parsing options
|
|
658
|
+
- [Batch API Reference](../../api-reference/modules/api-reference-01-client-api.md#job-batch-operations) - Complete API documentation
|