@fluentcommerce/fc-connect-sdk 0.1.54 → 0.1.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -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,507 +1,507 @@
|
|
|
1
|
-
# Module 3: S3 Operations
|
|
2
|
-
|
|
3
|
-
**Level:** Intermediate
|
|
4
|
-
**Estimated Time:** 25 minutes
|
|
5
|
-
|
|
6
|
-
## Overview
|
|
7
|
-
|
|
8
|
-
Complete guide to S3-specific file operations, including presigned URLs, batch operations, and S3-specific features.
|
|
9
|
-
|
|
10
|
-
## Learning Objectives
|
|
11
|
-
|
|
12
|
-
By the end of this module, you will:
|
|
13
|
-
- ✅ Master all S3 file operations (list, read, write, move, copy, delete)
|
|
14
|
-
- ✅ Understand S3-specific concepts (buckets, keys, regions)
|
|
15
|
-
- ✅ Learn presigned URL generation for temporary access
|
|
16
|
-
- ✅ Implement efficient batch operations
|
|
17
|
-
- ✅ Handle S3-specific errors
|
|
18
|
-
|
|
19
|
-
## S3 Concepts
|
|
20
|
-
|
|
21
|
-
### Buckets and Keys
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
// Bucket: Top-level container
|
|
25
|
-
const bucketName = 'my-data-bucket';
|
|
26
|
-
|
|
27
|
-
// Key: Object path within bucket (no leading slash!)
|
|
28
|
-
const key = 'incoming/orders/2025-01-15.csv';
|
|
29
|
-
// └─ prefix ─┘ └──── file ────┘
|
|
30
|
-
|
|
31
|
-
// Full S3 URL: s3://my-data-bucket/incoming/orders/2025-01-15.csv
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Regions
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
const s3 = new S3DataSource({
|
|
38
|
-
type: 'S3_CSV',
|
|
39
|
-
connectionId: 's3-operations',
|
|
40
|
-
name: 'S3 Operations',
|
|
41
|
-
s3Config: {
|
|
42
|
-
region: 'us-east-1', // Must match bucket region
|
|
43
|
-
bucket: 'my-bucket',
|
|
44
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
45
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
46
|
-
}
|
|
47
|
-
}, logger);
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## All S3 Operations
|
|
51
|
-
|
|
52
|
-
### List Files
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
// List all files
|
|
56
|
-
const allFiles = await s3.listFiles();
|
|
57
|
-
|
|
58
|
-
// List with prefix
|
|
59
|
-
const incomingFiles = await s3.listFiles({ prefix: 'incoming/' });
|
|
60
|
-
|
|
61
|
-
// List with maxKeys for pagination
|
|
62
|
-
const csvFiles = await s3.listFiles({ prefix: 'incoming/', maxKeys: 100 });
|
|
63
|
-
|
|
64
|
-
// List with delimiter for folder structure
|
|
65
|
-
const folders = await s3.listFiles({ prefix: 'incoming/', delimiter: '/' });
|
|
66
|
-
|
|
67
|
-
// Examine metadata
|
|
68
|
-
files.forEach(file => {
|
|
69
|
-
console.log(`Name: ${file.name}`);
|
|
70
|
-
console.log(`Path: ${file.path}`);
|
|
71
|
-
console.log(`Size: ${file.size} bytes`);
|
|
72
|
-
console.log(`Source: ${file.source}`); // 'S3'
|
|
73
|
-
if (file.lastModified) {
|
|
74
|
-
console.log(`Modified: ${file.lastModified}`); // ISO string
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### Download Files
|
|
80
|
-
|
|
81
|
-
```typescript
|
|
82
|
-
// Download as string
|
|
83
|
-
const csvContent = await s3.downloadFile('data/orders.csv');
|
|
84
|
-
|
|
85
|
-
// Handle large files
|
|
86
|
-
try {
|
|
87
|
-
const content = await s3.downloadFile('large-file.csv');
|
|
88
|
-
console.log(`Downloaded ${content.length} bytes`);
|
|
89
|
-
} catch (error: any) {
|
|
90
|
-
if (error.name === 'NoSuchKey') {
|
|
91
|
-
console.error('File does not exist');
|
|
92
|
-
} else {
|
|
93
|
-
console.error('Download failed:', error);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### Upload Files
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
import { Buffer } from 'node:buffer'; // Required for Deno/Versori runtime
|
|
102
|
-
|
|
103
|
-
// Upload string content
|
|
104
|
-
const data = JSON.stringify({ status: 'processed' });
|
|
105
|
-
await s3.uploadFile('output/results.json', data);
|
|
106
|
-
|
|
107
|
-
// Upload buffer
|
|
108
|
-
const buffer = Buffer.from('Hello, S3!');
|
|
109
|
-
await s3.uploadFile('messages/greeting.txt', buffer);
|
|
110
|
-
|
|
111
|
-
// Upload with error handling
|
|
112
|
-
try {
|
|
113
|
-
await s3.uploadFile('output/data.csv', csvContent);
|
|
114
|
-
console.log('Upload successful');
|
|
115
|
-
} catch (error: any) {
|
|
116
|
-
if (error.name === 'AccessDenied') {
|
|
117
|
-
console.error('No write permission');
|
|
118
|
-
} else {
|
|
119
|
-
console.error('Upload failed:', error);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### Move Files
|
|
125
|
-
|
|
126
|
-
```typescript
|
|
127
|
-
// Move (copy + delete source - DEFAULT BEHAVIOR)
|
|
128
|
-
await s3.moveFile('incoming/file.csv', 'processed/file.csv');
|
|
129
|
-
// Source file is DELETED by default
|
|
130
|
-
|
|
131
|
-
// Move without deleting source
|
|
132
|
-
await s3.moveFile('incoming/file.csv', 'processed/file.csv', false);
|
|
133
|
-
// Source file is preserved
|
|
134
|
-
|
|
135
|
-
// Move to date-based archive
|
|
136
|
-
const today = new Date().toISOString().split('T')[0];
|
|
137
|
-
await s3.moveFile(
|
|
138
|
-
'incoming/orders.csv',
|
|
139
|
-
`archive/${today}/orders.csv`
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
// Move with error handling
|
|
143
|
-
try {
|
|
144
|
-
await s3.moveFile(sourceKey, destKey);
|
|
145
|
-
console.log('File moved successfully');
|
|
146
|
-
} catch (error: any) {
|
|
147
|
-
if (error.name === 'NoSuchKey') {
|
|
148
|
-
console.error('Source file not found');
|
|
149
|
-
} else {
|
|
150
|
-
console.error('Move failed:', error);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### Copy Files
|
|
156
|
-
|
|
157
|
-
```typescript
|
|
158
|
-
// Copy to backup
|
|
159
|
-
await s3.copyFile('important/data.csv', 'backup/data.csv');
|
|
160
|
-
|
|
161
|
-
// Copy with metadata
|
|
162
|
-
await s3.copyFile('source/file.txt', 'dest/file.txt', {
|
|
163
|
-
metadata: { processedBy: 'sdk' }
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// Copy from different bucket
|
|
167
|
-
await s3.copyFile('source/file.txt', 'dest/file.txt', {
|
|
168
|
-
sourceBucket: 'other-bucket'
|
|
169
|
-
});
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
### Delete Files
|
|
173
|
-
|
|
174
|
-
```typescript
|
|
175
|
-
// Delete single file
|
|
176
|
-
await s3.deleteFile('temp/old-file.csv');
|
|
177
|
-
|
|
178
|
-
// Delete with confirmation
|
|
179
|
-
const fileToDelete = 'archive/old/data.csv';
|
|
180
|
-
const exists = await s3.fileExists(fileToDelete);
|
|
181
|
-
if (exists) {
|
|
182
|
-
await s3.deleteFile(fileToDelete);
|
|
183
|
-
console.log('File deleted');
|
|
184
|
-
}
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### Check File Existence
|
|
188
|
-
|
|
189
|
-
```typescript
|
|
190
|
-
// Check if file exists
|
|
191
|
-
const exists = await s3.fileExists('incoming/orders.csv');
|
|
192
|
-
console.log(`File exists: ${exists}`);
|
|
193
|
-
|
|
194
|
-
// Conditional processing
|
|
195
|
-
if (await s3.fileExists('config/settings.json')) {
|
|
196
|
-
const config = await s3.downloadFile('config/settings.json');
|
|
197
|
-
// Use config
|
|
198
|
-
}
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
## Batch Operations
|
|
202
|
-
|
|
203
|
-
### Process Multiple Files
|
|
204
|
-
|
|
205
|
-
```typescript
|
|
206
|
-
const files = await s3.listFiles({ prefix: 'incoming/', maxKeys: 1000 });
|
|
207
|
-
|
|
208
|
-
for (const file of files) {
|
|
209
|
-
try {
|
|
210
|
-
const content = await s3.downloadFile(file.name);
|
|
211
|
-
const result = await processData(content);
|
|
212
|
-
|
|
213
|
-
// Write result
|
|
214
|
-
const outputKey = file.name.replace('incoming/', 'output/').replace('.csv', '.json');
|
|
215
|
-
await s3.uploadFile(outputKey, JSON.stringify(result));
|
|
216
|
-
|
|
217
|
-
// Archive source
|
|
218
|
-
const archiveKey = file.name.replace('incoming/', 'archive/');
|
|
219
|
-
await s3.moveFile(file.name, archiveKey);
|
|
220
|
-
|
|
221
|
-
console.log(`Processed ${file.name}`);
|
|
222
|
-
|
|
223
|
-
} catch (error) {
|
|
224
|
-
console.error(`Failed to process ${file.name}:`, error);
|
|
225
|
-
// Continue with next file
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
### Parallel Processing
|
|
231
|
-
|
|
232
|
-
```typescript
|
|
233
|
-
const files = await s3.listFiles({ prefix: 'incoming/' });
|
|
234
|
-
|
|
235
|
-
// Process files in parallel (be mindful of rate limits)
|
|
236
|
-
const results = await Promise.allSettled(
|
|
237
|
-
files.map(async (file) => {
|
|
238
|
-
const content = await s3.downloadFile(file.name);
|
|
239
|
-
const result = await processData(content);
|
|
240
|
-
await s3.uploadFile(
|
|
241
|
-
file.name.replace('incoming/', 'output/'),
|
|
242
|
-
JSON.stringify(result)
|
|
243
|
-
);
|
|
244
|
-
return file.name;
|
|
245
|
-
})
|
|
246
|
-
);
|
|
247
|
-
|
|
248
|
-
// Check results
|
|
249
|
-
results.forEach((result, index) => {
|
|
250
|
-
if (result.status === 'fulfilled') {
|
|
251
|
-
console.log(`Success: ${result.value}`);
|
|
252
|
-
} else {
|
|
253
|
-
console.error(`Failed: ${files[index].name}:`, result.reason);
|
|
254
|
-
}
|
|
255
|
-
});
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
## Presigned URLs
|
|
259
|
-
|
|
260
|
-
Use the `S3PresignService` for temporary access:
|
|
261
|
-
|
|
262
|
-
```typescript
|
|
263
|
-
import { S3PresignService } from '@fluentcommerce/fc-connect-sdk';
|
|
264
|
-
|
|
265
|
-
const presignService = new S3PresignService(
|
|
266
|
-
s3Config,
|
|
267
|
-
bucketName,
|
|
268
|
-
logger
|
|
269
|
-
);
|
|
270
|
-
|
|
271
|
-
// Generate download URL (valid for 1 hour)
|
|
272
|
-
const downloadUrl = await presignService.generatePresignedDownloadUrl(
|
|
273
|
-
'reports/monthly-report.pdf',
|
|
274
|
-
3600 // 1 hour in seconds
|
|
275
|
-
);
|
|
276
|
-
|
|
277
|
-
console.log('Download here:', downloadUrl);
|
|
278
|
-
// https://my-bucket.s3.amazonaws.com/reports/monthly-report.pdf?X-Amz-...
|
|
279
|
-
|
|
280
|
-
// Generate upload URL
|
|
281
|
-
const uploadUrl = await presignService.generatePresignedUploadUrl(
|
|
282
|
-
'incoming/upload.csv',
|
|
283
|
-
3600
|
|
284
|
-
);
|
|
285
|
-
|
|
286
|
-
console.log('Upload here:', uploadUrl);
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
## S3-Specific Patterns
|
|
290
|
-
|
|
291
|
-
### Date-Based Organization
|
|
292
|
-
|
|
293
|
-
```typescript
|
|
294
|
-
function getDateBasedKey(filename: string, prefix: string): string {
|
|
295
|
-
const now = new Date();
|
|
296
|
-
const year = now.getFullYear();
|
|
297
|
-
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
298
|
-
const day = String(now.getDate()).padStart(2, '0');
|
|
299
|
-
|
|
300
|
-
return `${prefix}/${year}/${month}/${day}/${filename}`;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// Archive with date structure
|
|
304
|
-
await s3.moveFile(
|
|
305
|
-
'incoming/orders.csv',
|
|
306
|
-
getDateBasedKey('orders.csv', 'archive')
|
|
307
|
-
);
|
|
308
|
-
// Result: archive/2025/01/15/orders.csv
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
### Multi-Prefix Processing
|
|
312
|
-
|
|
313
|
-
```typescript
|
|
314
|
-
const prefixes = ['orders', 'inventory', 'products'];
|
|
315
|
-
|
|
316
|
-
for (const prefix of prefixes) {
|
|
317
|
-
const files = await s3.listFiles({ prefix: `incoming/${prefix}/` });
|
|
318
|
-
|
|
319
|
-
for (const file of files) {
|
|
320
|
-
const content = await s3.downloadFile(file.name);
|
|
321
|
-
await processByType(prefix, content);
|
|
322
|
-
|
|
323
|
-
await s3.moveFile(
|
|
324
|
-
file.name,
|
|
325
|
-
file.name.replace('incoming/', 'processed/')
|
|
326
|
-
);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
## Error Handling
|
|
332
|
-
|
|
333
|
-
### Common S3 Errors
|
|
334
|
-
|
|
335
|
-
```typescript
|
|
336
|
-
try {
|
|
337
|
-
await s3.downloadFile('missing-file.csv');
|
|
338
|
-
} catch (error: any) {
|
|
339
|
-
switch (error.name) {
|
|
340
|
-
case 'NoSuchKey':
|
|
341
|
-
console.error('File does not exist');
|
|
342
|
-
break;
|
|
343
|
-
case 'NoSuchBucket':
|
|
344
|
-
console.error('Bucket does not exist');
|
|
345
|
-
break;
|
|
346
|
-
case 'AccessDenied':
|
|
347
|
-
console.error('Permission denied - check IAM policy');
|
|
348
|
-
break;
|
|
349
|
-
case 'InvalidBucketName':
|
|
350
|
-
console.error('Invalid bucket name');
|
|
351
|
-
break;
|
|
352
|
-
default:
|
|
353
|
-
console.error('S3 error:', error.message);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
### Retry Logic
|
|
359
|
-
|
|
360
|
-
```typescript
|
|
361
|
-
async function downloadWithRetry(
|
|
362
|
-
s3: S3DataSource,
|
|
363
|
-
key: string,
|
|
364
|
-
maxRetries = 3
|
|
365
|
-
): Promise<string> {
|
|
366
|
-
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
367
|
-
try {
|
|
368
|
-
return await s3.downloadFile(key);
|
|
369
|
-
} catch (error: any) {
|
|
370
|
-
if (error.name === 'NoSuchKey') {
|
|
371
|
-
throw error; // Don't retry if file doesn't exist
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
if (attempt === maxRetries) throw error;
|
|
375
|
-
|
|
376
|
-
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
|
|
377
|
-
console.log(`Retry ${attempt}/${maxRetries} after ${delay}ms`);
|
|
378
|
-
await new Promise(resolve => setTimeout(resolve, delay));
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
throw new Error('Should not reach here');
|
|
382
|
-
}
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
## Parquet Support
|
|
386
|
-
|
|
387
|
-
S3 data source supports writing Parquet files for efficient data storage and transfer.
|
|
388
|
-
|
|
389
|
-
### Write Parquet Content
|
|
390
|
-
|
|
391
|
-
```typescript
|
|
392
|
-
try {
|
|
393
|
-
// Prepare data records
|
|
394
|
-
const records = [
|
|
395
|
-
{ sku: 'SKU-001', quantity: 10, price: 99.99, available: true },
|
|
396
|
-
{ sku: 'SKU-002', quantity: 25, price: 149.99, available: true }
|
|
397
|
-
];
|
|
398
|
-
|
|
399
|
-
// Generate Parquet content as Buffer
|
|
400
|
-
const parquetBuffer = await s3.writeParquetContent(records, {
|
|
401
|
-
compression: 'GZIP', // Options: 'UNCOMPRESSED', 'GZIP', 'SNAPPY', 'LZO', 'BROTLI'
|
|
402
|
-
rowGroupSize: 5000, // Number of rows per row group
|
|
403
|
-
schema: { // Optional: explicit schema (auto-detected if not provided)
|
|
404
|
-
sku: { type: 'UTF8' },
|
|
405
|
-
quantity: { type: 'INT64' },
|
|
406
|
-
price: { type: 'DOUBLE' },
|
|
407
|
-
available: { type: 'BOOLEAN' }
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
// Upload Parquet file to S3
|
|
412
|
-
await s3.uploadFile('data/inventory.parquet', parquetBuffer);
|
|
413
|
-
|
|
414
|
-
console.log(`Generated Parquet file: ${parquetBuffer.length} bytes`);
|
|
415
|
-
} finally {
|
|
416
|
-
await s3.dispose();
|
|
417
|
-
}
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
### Parquet with Compression
|
|
421
|
-
|
|
422
|
-
```typescript
|
|
423
|
-
try {
|
|
424
|
-
const records = /* ... large dataset ... */;
|
|
425
|
-
|
|
426
|
-
// Use SNAPPY compression for faster processing
|
|
427
|
-
const compressed = await s3.writeParquetContent(records, {
|
|
428
|
-
compression: 'SNAPPY',
|
|
429
|
-
rowGroupSize: 10000
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
// Use GZIP for smaller file size
|
|
433
|
-
const gzipped = await s3.writeParquetContent(records, {
|
|
434
|
-
compression: 'GZIP',
|
|
435
|
-
rowGroupSize: 10000
|
|
436
|
-
});
|
|
437
|
-
|
|
438
|
-
console.log(`SNAPPY: ${compressed.length} bytes`);
|
|
439
|
-
console.log(`GZIP: ${gzipped.length} bytes`);
|
|
440
|
-
|
|
441
|
-
// Upload smaller file
|
|
442
|
-
await s3.uploadFile('data/compressed.parquet', gzipped);
|
|
443
|
-
} finally {
|
|
444
|
-
await s3.dispose();
|
|
445
|
-
}
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
### Parquet Export Pattern
|
|
449
|
-
|
|
450
|
-
```typescript
|
|
451
|
-
async function exportToParquet(s3: S3DataSource, records: any[], outputKey: string) {
|
|
452
|
-
// Generate Parquet file
|
|
453
|
-
const parquetBuffer = await s3.writeParquetContent(records, {
|
|
454
|
-
compression: 'GZIP',
|
|
455
|
-
rowGroupSize: 10000
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
// Upload to S3
|
|
459
|
-
await s3.uploadFile(outputKey, parquetBuffer);
|
|
460
|
-
|
|
461
|
-
console.log(`Exported ${records.length} records to ${outputKey}`);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
try {
|
|
465
|
-
// Query data from Fluent or other source
|
|
466
|
-
const inventoryData = await fetchInventoryData();
|
|
467
|
-
|
|
468
|
-
// Export to Parquet
|
|
469
|
-
const date = new Date().toISOString().split('T')[0];
|
|
470
|
-
await exportToParquet(s3, inventoryData, `exports/inventory_${date}.parquet`);
|
|
471
|
-
} finally {
|
|
472
|
-
await s3.dispose();
|
|
473
|
-
}
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
**Note:** For reading Parquet files from S3, use `ParquetParserService` from the SDK:
|
|
477
|
-
|
|
478
|
-
```typescript
|
|
479
|
-
import { ParquetParserService } from '@fluentcommerce/fc-connect-sdk';
|
|
480
|
-
|
|
481
|
-
const parser = new ParquetParserService();
|
|
482
|
-
const content = await s3.downloadFile('data/inventory.parquet', {
|
|
483
|
-
encoding: 'binary' // S3 uses 'binary' encoding for binary files
|
|
484
|
-
});
|
|
485
|
-
const records = await parser.parse(content as Buffer);
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
## Key Takeaways
|
|
489
|
-
|
|
490
|
-
- 🎯 S3 uses buckets and keys (no leading slashes in keys)
|
|
491
|
-
- 🎯 Move is implemented as copy + delete (2 operations)
|
|
492
|
-
- 🎯 Presigned URLs provide temporary access without credentials
|
|
493
|
-
- 🎯 Date-based prefixes help organize large datasets
|
|
494
|
-
- 🎯 `writeParquetContent()` generates compressed Parquet files efficiently
|
|
495
|
-
- 🎯 Always handle NoSuchKey and AccessDenied errors
|
|
496
|
-
- 🎯 Use retry logic with exponential backoff for transient errors
|
|
497
|
-
|
|
498
|
-
## Next Steps
|
|
499
|
-
|
|
500
|
-
Continue to [Module 4: SFTP Operations](./file-operations-04-sftp-operations.md) for SFTP-specific features.
|
|
501
|
-
|
|
502
|
-
---
|
|
503
|
-
|
|
504
|
-
**Related Resources:**
|
|
505
|
-
- [Quick Reference](../../../02-CORE-GUIDES/advanced-services/advanced-services-quick-reference.md) - S3 operations cheat sheet
|
|
506
|
-
- [Common Patterns](../examples/common-patterns.ts) - Copy-paste ready snippets
|
|
507
|
-
- [AWS S3 Documentation](https://docs.aws.amazon.com/s3/) - Official AWS docs
|
|
1
|
+
# Module 3: S3 Operations
|
|
2
|
+
|
|
3
|
+
**Level:** Intermediate
|
|
4
|
+
**Estimated Time:** 25 minutes
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Complete guide to S3-specific file operations, including presigned URLs, batch operations, and S3-specific features.
|
|
9
|
+
|
|
10
|
+
## Learning Objectives
|
|
11
|
+
|
|
12
|
+
By the end of this module, you will:
|
|
13
|
+
- ✅ Master all S3 file operations (list, read, write, move, copy, delete)
|
|
14
|
+
- ✅ Understand S3-specific concepts (buckets, keys, regions)
|
|
15
|
+
- ✅ Learn presigned URL generation for temporary access
|
|
16
|
+
- ✅ Implement efficient batch operations
|
|
17
|
+
- ✅ Handle S3-specific errors
|
|
18
|
+
|
|
19
|
+
## S3 Concepts
|
|
20
|
+
|
|
21
|
+
### Buckets and Keys
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
// Bucket: Top-level container
|
|
25
|
+
const bucketName = 'my-data-bucket';
|
|
26
|
+
|
|
27
|
+
// Key: Object path within bucket (no leading slash!)
|
|
28
|
+
const key = 'incoming/orders/2025-01-15.csv';
|
|
29
|
+
// └─ prefix ─┘ └──── file ────┘
|
|
30
|
+
|
|
31
|
+
// Full S3 URL: s3://my-data-bucket/incoming/orders/2025-01-15.csv
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Regions
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
const s3 = new S3DataSource({
|
|
38
|
+
type: 'S3_CSV',
|
|
39
|
+
connectionId: 's3-operations',
|
|
40
|
+
name: 'S3 Operations',
|
|
41
|
+
s3Config: {
|
|
42
|
+
region: 'us-east-1', // Must match bucket region
|
|
43
|
+
bucket: 'my-bucket',
|
|
44
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
45
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
46
|
+
}
|
|
47
|
+
}, logger);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## All S3 Operations
|
|
51
|
+
|
|
52
|
+
### List Files
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// List all files
|
|
56
|
+
const allFiles = await s3.listFiles();
|
|
57
|
+
|
|
58
|
+
// List with prefix
|
|
59
|
+
const incomingFiles = await s3.listFiles({ prefix: 'incoming/' });
|
|
60
|
+
|
|
61
|
+
// List with maxKeys for pagination
|
|
62
|
+
const csvFiles = await s3.listFiles({ prefix: 'incoming/', maxKeys: 100 });
|
|
63
|
+
|
|
64
|
+
// List with delimiter for folder structure
|
|
65
|
+
const folders = await s3.listFiles({ prefix: 'incoming/', delimiter: '/' });
|
|
66
|
+
|
|
67
|
+
// Examine metadata
|
|
68
|
+
files.forEach(file => {
|
|
69
|
+
console.log(`Name: ${file.name}`);
|
|
70
|
+
console.log(`Path: ${file.path}`);
|
|
71
|
+
console.log(`Size: ${file.size} bytes`);
|
|
72
|
+
console.log(`Source: ${file.source}`); // 'S3'
|
|
73
|
+
if (file.lastModified) {
|
|
74
|
+
console.log(`Modified: ${file.lastModified}`); // ISO string
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Download Files
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// Download as string
|
|
83
|
+
const csvContent = await s3.downloadFile('data/orders.csv');
|
|
84
|
+
|
|
85
|
+
// Handle large files
|
|
86
|
+
try {
|
|
87
|
+
const content = await s3.downloadFile('large-file.csv');
|
|
88
|
+
console.log(`Downloaded ${content.length} bytes`);
|
|
89
|
+
} catch (error: any) {
|
|
90
|
+
if (error.name === 'NoSuchKey') {
|
|
91
|
+
console.error('File does not exist');
|
|
92
|
+
} else {
|
|
93
|
+
console.error('Download failed:', error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Upload Files
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { Buffer } from 'node:buffer'; // Required for Deno/Versori runtime
|
|
102
|
+
|
|
103
|
+
// Upload string content
|
|
104
|
+
const data = JSON.stringify({ status: 'processed' });
|
|
105
|
+
await s3.uploadFile('output/results.json', data);
|
|
106
|
+
|
|
107
|
+
// Upload buffer
|
|
108
|
+
const buffer = Buffer.from('Hello, S3!');
|
|
109
|
+
await s3.uploadFile('messages/greeting.txt', buffer);
|
|
110
|
+
|
|
111
|
+
// Upload with error handling
|
|
112
|
+
try {
|
|
113
|
+
await s3.uploadFile('output/data.csv', csvContent);
|
|
114
|
+
console.log('Upload successful');
|
|
115
|
+
} catch (error: any) {
|
|
116
|
+
if (error.name === 'AccessDenied') {
|
|
117
|
+
console.error('No write permission');
|
|
118
|
+
} else {
|
|
119
|
+
console.error('Upload failed:', error);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Move Files
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// Move (copy + delete source - DEFAULT BEHAVIOR)
|
|
128
|
+
await s3.moveFile('incoming/file.csv', 'processed/file.csv');
|
|
129
|
+
// Source file is DELETED by default
|
|
130
|
+
|
|
131
|
+
// Move without deleting source
|
|
132
|
+
await s3.moveFile('incoming/file.csv', 'processed/file.csv', false);
|
|
133
|
+
// Source file is preserved
|
|
134
|
+
|
|
135
|
+
// Move to date-based archive
|
|
136
|
+
const today = new Date().toISOString().split('T')[0];
|
|
137
|
+
await s3.moveFile(
|
|
138
|
+
'incoming/orders.csv',
|
|
139
|
+
`archive/${today}/orders.csv`
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
// Move with error handling
|
|
143
|
+
try {
|
|
144
|
+
await s3.moveFile(sourceKey, destKey);
|
|
145
|
+
console.log('File moved successfully');
|
|
146
|
+
} catch (error: any) {
|
|
147
|
+
if (error.name === 'NoSuchKey') {
|
|
148
|
+
console.error('Source file not found');
|
|
149
|
+
} else {
|
|
150
|
+
console.error('Move failed:', error);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Copy Files
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
// Copy to backup
|
|
159
|
+
await s3.copyFile('important/data.csv', 'backup/data.csv');
|
|
160
|
+
|
|
161
|
+
// Copy with metadata
|
|
162
|
+
await s3.copyFile('source/file.txt', 'dest/file.txt', {
|
|
163
|
+
metadata: { processedBy: 'sdk' }
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Copy from different bucket
|
|
167
|
+
await s3.copyFile('source/file.txt', 'dest/file.txt', {
|
|
168
|
+
sourceBucket: 'other-bucket'
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Delete Files
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
// Delete single file
|
|
176
|
+
await s3.deleteFile('temp/old-file.csv');
|
|
177
|
+
|
|
178
|
+
// Delete with confirmation
|
|
179
|
+
const fileToDelete = 'archive/old/data.csv';
|
|
180
|
+
const exists = await s3.fileExists(fileToDelete);
|
|
181
|
+
if (exists) {
|
|
182
|
+
await s3.deleteFile(fileToDelete);
|
|
183
|
+
console.log('File deleted');
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Check File Existence
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
// Check if file exists
|
|
191
|
+
const exists = await s3.fileExists('incoming/orders.csv');
|
|
192
|
+
console.log(`File exists: ${exists}`);
|
|
193
|
+
|
|
194
|
+
// Conditional processing
|
|
195
|
+
if (await s3.fileExists('config/settings.json')) {
|
|
196
|
+
const config = await s3.downloadFile('config/settings.json');
|
|
197
|
+
// Use config
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Batch Operations
|
|
202
|
+
|
|
203
|
+
### Process Multiple Files
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
const files = await s3.listFiles({ prefix: 'incoming/', maxKeys: 1000 });
|
|
207
|
+
|
|
208
|
+
for (const file of files) {
|
|
209
|
+
try {
|
|
210
|
+
const content = await s3.downloadFile(file.name);
|
|
211
|
+
const result = await processData(content);
|
|
212
|
+
|
|
213
|
+
// Write result
|
|
214
|
+
const outputKey = file.name.replace('incoming/', 'output/').replace('.csv', '.json');
|
|
215
|
+
await s3.uploadFile(outputKey, JSON.stringify(result));
|
|
216
|
+
|
|
217
|
+
// Archive source
|
|
218
|
+
const archiveKey = file.name.replace('incoming/', 'archive/');
|
|
219
|
+
await s3.moveFile(file.name, archiveKey);
|
|
220
|
+
|
|
221
|
+
console.log(`Processed ${file.name}`);
|
|
222
|
+
|
|
223
|
+
} catch (error) {
|
|
224
|
+
console.error(`Failed to process ${file.name}:`, error);
|
|
225
|
+
// Continue with next file
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Parallel Processing
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
const files = await s3.listFiles({ prefix: 'incoming/' });
|
|
234
|
+
|
|
235
|
+
// Process files in parallel (be mindful of rate limits)
|
|
236
|
+
const results = await Promise.allSettled(
|
|
237
|
+
files.map(async (file) => {
|
|
238
|
+
const content = await s3.downloadFile(file.name);
|
|
239
|
+
const result = await processData(content);
|
|
240
|
+
await s3.uploadFile(
|
|
241
|
+
file.name.replace('incoming/', 'output/'),
|
|
242
|
+
JSON.stringify(result)
|
|
243
|
+
);
|
|
244
|
+
return file.name;
|
|
245
|
+
})
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
// Check results
|
|
249
|
+
results.forEach((result, index) => {
|
|
250
|
+
if (result.status === 'fulfilled') {
|
|
251
|
+
console.log(`Success: ${result.value}`);
|
|
252
|
+
} else {
|
|
253
|
+
console.error(`Failed: ${files[index].name}:`, result.reason);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Presigned URLs
|
|
259
|
+
|
|
260
|
+
Use the `S3PresignService` for temporary access:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import { S3PresignService } from '@fluentcommerce/fc-connect-sdk';
|
|
264
|
+
|
|
265
|
+
const presignService = new S3PresignService(
|
|
266
|
+
s3Config,
|
|
267
|
+
bucketName,
|
|
268
|
+
logger
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
// Generate download URL (valid for 1 hour)
|
|
272
|
+
const downloadUrl = await presignService.generatePresignedDownloadUrl(
|
|
273
|
+
'reports/monthly-report.pdf',
|
|
274
|
+
3600 // 1 hour in seconds
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
console.log('Download here:', downloadUrl);
|
|
278
|
+
// https://my-bucket.s3.amazonaws.com/reports/monthly-report.pdf?X-Amz-...
|
|
279
|
+
|
|
280
|
+
// Generate upload URL
|
|
281
|
+
const uploadUrl = await presignService.generatePresignedUploadUrl(
|
|
282
|
+
'incoming/upload.csv',
|
|
283
|
+
3600
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
console.log('Upload here:', uploadUrl);
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## S3-Specific Patterns
|
|
290
|
+
|
|
291
|
+
### Date-Based Organization
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
function getDateBasedKey(filename: string, prefix: string): string {
|
|
295
|
+
const now = new Date();
|
|
296
|
+
const year = now.getFullYear();
|
|
297
|
+
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
298
|
+
const day = String(now.getDate()).padStart(2, '0');
|
|
299
|
+
|
|
300
|
+
return `${prefix}/${year}/${month}/${day}/${filename}`;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Archive with date structure
|
|
304
|
+
await s3.moveFile(
|
|
305
|
+
'incoming/orders.csv',
|
|
306
|
+
getDateBasedKey('orders.csv', 'archive')
|
|
307
|
+
);
|
|
308
|
+
// Result: archive/2025/01/15/orders.csv
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Multi-Prefix Processing
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
const prefixes = ['orders', 'inventory', 'products'];
|
|
315
|
+
|
|
316
|
+
for (const prefix of prefixes) {
|
|
317
|
+
const files = await s3.listFiles({ prefix: `incoming/${prefix}/` });
|
|
318
|
+
|
|
319
|
+
for (const file of files) {
|
|
320
|
+
const content = await s3.downloadFile(file.name);
|
|
321
|
+
await processByType(prefix, content);
|
|
322
|
+
|
|
323
|
+
await s3.moveFile(
|
|
324
|
+
file.name,
|
|
325
|
+
file.name.replace('incoming/', 'processed/')
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Error Handling
|
|
332
|
+
|
|
333
|
+
### Common S3 Errors
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
try {
|
|
337
|
+
await s3.downloadFile('missing-file.csv');
|
|
338
|
+
} catch (error: any) {
|
|
339
|
+
switch (error.name) {
|
|
340
|
+
case 'NoSuchKey':
|
|
341
|
+
console.error('File does not exist');
|
|
342
|
+
break;
|
|
343
|
+
case 'NoSuchBucket':
|
|
344
|
+
console.error('Bucket does not exist');
|
|
345
|
+
break;
|
|
346
|
+
case 'AccessDenied':
|
|
347
|
+
console.error('Permission denied - check IAM policy');
|
|
348
|
+
break;
|
|
349
|
+
case 'InvalidBucketName':
|
|
350
|
+
console.error('Invalid bucket name');
|
|
351
|
+
break;
|
|
352
|
+
default:
|
|
353
|
+
console.error('S3 error:', error.message);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Retry Logic
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
async function downloadWithRetry(
|
|
362
|
+
s3: S3DataSource,
|
|
363
|
+
key: string,
|
|
364
|
+
maxRetries = 3
|
|
365
|
+
): Promise<string> {
|
|
366
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
367
|
+
try {
|
|
368
|
+
return await s3.downloadFile(key);
|
|
369
|
+
} catch (error: any) {
|
|
370
|
+
if (error.name === 'NoSuchKey') {
|
|
371
|
+
throw error; // Don't retry if file doesn't exist
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (attempt === maxRetries) throw error;
|
|
375
|
+
|
|
376
|
+
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
|
|
377
|
+
console.log(`Retry ${attempt}/${maxRetries} after ${delay}ms`);
|
|
378
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
throw new Error('Should not reach here');
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## Parquet Support
|
|
386
|
+
|
|
387
|
+
S3 data source supports writing Parquet files for efficient data storage and transfer.
|
|
388
|
+
|
|
389
|
+
### Write Parquet Content
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
try {
|
|
393
|
+
// Prepare data records
|
|
394
|
+
const records = [
|
|
395
|
+
{ sku: 'SKU-001', quantity: 10, price: 99.99, available: true },
|
|
396
|
+
{ sku: 'SKU-002', quantity: 25, price: 149.99, available: true }
|
|
397
|
+
];
|
|
398
|
+
|
|
399
|
+
// Generate Parquet content as Buffer
|
|
400
|
+
const parquetBuffer = await s3.writeParquetContent(records, {
|
|
401
|
+
compression: 'GZIP', // Options: 'UNCOMPRESSED', 'GZIP', 'SNAPPY', 'LZO', 'BROTLI'
|
|
402
|
+
rowGroupSize: 5000, // Number of rows per row group
|
|
403
|
+
schema: { // Optional: explicit schema (auto-detected if not provided)
|
|
404
|
+
sku: { type: 'UTF8' },
|
|
405
|
+
quantity: { type: 'INT64' },
|
|
406
|
+
price: { type: 'DOUBLE' },
|
|
407
|
+
available: { type: 'BOOLEAN' }
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
// Upload Parquet file to S3
|
|
412
|
+
await s3.uploadFile('data/inventory.parquet', parquetBuffer);
|
|
413
|
+
|
|
414
|
+
console.log(`Generated Parquet file: ${parquetBuffer.length} bytes`);
|
|
415
|
+
} finally {
|
|
416
|
+
await s3.dispose();
|
|
417
|
+
}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Parquet with Compression
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
try {
|
|
424
|
+
const records = /* ... large dataset ... */;
|
|
425
|
+
|
|
426
|
+
// Use SNAPPY compression for faster processing
|
|
427
|
+
const compressed = await s3.writeParquetContent(records, {
|
|
428
|
+
compression: 'SNAPPY',
|
|
429
|
+
rowGroupSize: 10000
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
// Use GZIP for smaller file size
|
|
433
|
+
const gzipped = await s3.writeParquetContent(records, {
|
|
434
|
+
compression: 'GZIP',
|
|
435
|
+
rowGroupSize: 10000
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
console.log(`SNAPPY: ${compressed.length} bytes`);
|
|
439
|
+
console.log(`GZIP: ${gzipped.length} bytes`);
|
|
440
|
+
|
|
441
|
+
// Upload smaller file
|
|
442
|
+
await s3.uploadFile('data/compressed.parquet', gzipped);
|
|
443
|
+
} finally {
|
|
444
|
+
await s3.dispose();
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Parquet Export Pattern
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
async function exportToParquet(s3: S3DataSource, records: any[], outputKey: string) {
|
|
452
|
+
// Generate Parquet file
|
|
453
|
+
const parquetBuffer = await s3.writeParquetContent(records, {
|
|
454
|
+
compression: 'GZIP',
|
|
455
|
+
rowGroupSize: 10000
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
// Upload to S3
|
|
459
|
+
await s3.uploadFile(outputKey, parquetBuffer);
|
|
460
|
+
|
|
461
|
+
console.log(`Exported ${records.length} records to ${outputKey}`);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
try {
|
|
465
|
+
// Query data from Fluent or other source
|
|
466
|
+
const inventoryData = await fetchInventoryData();
|
|
467
|
+
|
|
468
|
+
// Export to Parquet
|
|
469
|
+
const date = new Date().toISOString().split('T')[0];
|
|
470
|
+
await exportToParquet(s3, inventoryData, `exports/inventory_${date}.parquet`);
|
|
471
|
+
} finally {
|
|
472
|
+
await s3.dispose();
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
**Note:** For reading Parquet files from S3, use `ParquetParserService` from the SDK:
|
|
477
|
+
|
|
478
|
+
```typescript
|
|
479
|
+
import { ParquetParserService } from '@fluentcommerce/fc-connect-sdk';
|
|
480
|
+
|
|
481
|
+
const parser = new ParquetParserService();
|
|
482
|
+
const content = await s3.downloadFile('data/inventory.parquet', {
|
|
483
|
+
encoding: 'binary' // S3 uses 'binary' encoding for binary files
|
|
484
|
+
});
|
|
485
|
+
const records = await parser.parse(content as Buffer);
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
## Key Takeaways
|
|
489
|
+
|
|
490
|
+
- 🎯 S3 uses buckets and keys (no leading slashes in keys)
|
|
491
|
+
- 🎯 Move is implemented as copy + delete (2 operations)
|
|
492
|
+
- 🎯 Presigned URLs provide temporary access without credentials
|
|
493
|
+
- 🎯 Date-based prefixes help organize large datasets
|
|
494
|
+
- 🎯 `writeParquetContent()` generates compressed Parquet files efficiently
|
|
495
|
+
- 🎯 Always handle NoSuchKey and AccessDenied errors
|
|
496
|
+
- 🎯 Use retry logic with exponential backoff for transient errors
|
|
497
|
+
|
|
498
|
+
## Next Steps
|
|
499
|
+
|
|
500
|
+
Continue to [Module 4: SFTP Operations](./file-operations-04-sftp-operations.md) for SFTP-specific features.
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
**Related Resources:**
|
|
505
|
+
- [Quick Reference](../../../02-CORE-GUIDES/advanced-services/advanced-services-quick-reference.md) - S3 operations cheat sheet
|
|
506
|
+
- [Common Patterns](../examples/common-patterns.ts) - Copy-paste ready snippets
|
|
507
|
+
- [AWS S3 Documentation](https://docs.aws.amazon.com/s3/) - Official AWS docs
|