@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
package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-s3-integration.md
CHANGED
|
@@ -1,511 +1,511 @@
|
|
|
1
|
-
# Module 6: S3 Integration
|
|
2
|
-
|
|
3
|
-
[← Back to Parquet Guide](../parquet-readme.md)
|
|
4
|
-
|
|
5
|
-
**Module 6 of 8** | **Level**: Advanced | **Time**: 20 minutes
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Overview
|
|
10
|
-
|
|
11
|
-
Integrate Parquet processing with S3 for data lake operations, including reading from S3, writing to S3, and using presigned URLs.
|
|
12
|
-
|
|
13
|
-
## Learning Objectives
|
|
14
|
-
|
|
15
|
-
By the end of this module, you will:
|
|
16
|
-
|
|
17
|
-
- ✅ Read Parquet files from S3
|
|
18
|
-
- ✅ Write extracted Parquet files to S3
|
|
19
|
-
- ✅ Use streaming for large S3 files
|
|
20
|
-
- ✅ Implement presigned URL workflows
|
|
21
|
-
- ✅ Build complete ETL pipelines
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## Reading Parquet from S3
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
import { Buffer } from 'node:buffer'; // Required for Deno/Versori runtime
|
|
29
|
-
import {
|
|
30
|
-
S3DataSource,
|
|
31
|
-
ParquetParserService,
|
|
32
|
-
createConsoleLogger,
|
|
33
|
-
toStructuredLogger
|
|
34
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
35
|
-
|
|
36
|
-
class S3ParquetProcessor {
|
|
37
|
-
private s3: S3DataSource;
|
|
38
|
-
private parser: ParquetParserService;
|
|
39
|
-
private logger: Logger;
|
|
40
|
-
|
|
41
|
-
constructor(s3Config: any) {
|
|
42
|
-
this.logger = toStructuredLogger(createConsoleLogger(), {
|
|
43
|
-
logLevel: 'info'
|
|
44
|
-
});
|
|
45
|
-
this.s3 = new S3DataSource(
|
|
46
|
-
{
|
|
47
|
-
type: 'S3_CSV',
|
|
48
|
-
s3Config: {
|
|
49
|
-
bucket: process.env.S3_BUCKET!,
|
|
50
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
51
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
52
|
-
region: process.env.AWS_REGION!,
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
this.logger
|
|
56
|
-
);
|
|
57
|
-
this.parser = new ParquetParserService(this.logger);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async processParquetFromS3(key: string): Promise<any[]> {
|
|
61
|
-
console.log(`Processing s3://${this.s3.s3Config.bucket}/${key}`);
|
|
62
|
-
|
|
63
|
-
// 1. Download from S3
|
|
64
|
-
const fileBuffer = await this.s3.downloadFile(key, { encoding: 'binary' });
|
|
65
|
-
|
|
66
|
-
// 2. Convert to ArrayBuffer
|
|
67
|
-
const arrayBuffer = fileBuffer.buffer.slice(
|
|
68
|
-
fileBuffer.byteOffset,
|
|
69
|
-
fileBuffer.byteOffset + fileBuffer.byteLength
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
// 3. Parse Parquet file
|
|
73
|
-
const { records, stats } = await this.parser.parse(arrayBuffer, key);
|
|
74
|
-
|
|
75
|
-
console.log(`✅ Processed ${stats.totalRecords} records from S3`);
|
|
76
|
-
console.log(` Processing time: ${stats.processingTimeMs}ms`);
|
|
77
|
-
console.log(` File size: ${(stats.fileSizeBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
78
|
-
|
|
79
|
-
return records;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## Writing Parquet to S3
|
|
87
|
-
|
|
88
|
-
### Method 1: Direct Write (Recommended)
|
|
89
|
-
|
|
90
|
-
Use `S3DataSource.writeParquetContent()` for streamlined direct writes:
|
|
91
|
-
|
|
92
|
-
```typescript
|
|
93
|
-
import { S3DataSource, createClient, createConsoleLogger, toStructuredLogger } from '@fluentcommerce/fc-connect-sdk';
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Extract from Fluent Commerce and write directly to S3
|
|
97
|
-
* Business use case: Daily inventory export to data lake
|
|
98
|
-
*/
|
|
99
|
-
async function extractToS3Direct(s3Key: string): Promise<void> {
|
|
100
|
-
const logger = toStructuredLogger(createConsoleLogger(), { service: 'Extraction' });
|
|
101
|
-
|
|
102
|
-
// 1. Setup client
|
|
103
|
-
const client = await createClient({
|
|
104
|
-
config: {
|
|
105
|
-
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
106
|
-
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
107
|
-
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
108
|
-
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// 2. Setup S3
|
|
113
|
-
const s3 = new S3DataSource(
|
|
114
|
-
{
|
|
115
|
-
type: 'S3_CSV',
|
|
116
|
-
s3Config: {
|
|
117
|
-
bucket: process.env.S3_BUCKET!,
|
|
118
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
119
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
120
|
-
region: process.env.AWS_REGION!,
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
logger
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
// 3. Extract data (pagination loop)
|
|
127
|
-
const allRecords = [];
|
|
128
|
-
let hasNextPage = true;
|
|
129
|
-
let cursor: string | null = null;
|
|
130
|
-
|
|
131
|
-
while (hasNextPage) {
|
|
132
|
-
const result = await client.graphql({
|
|
133
|
-
query: `
|
|
134
|
-
query ExtractInventory($after: String, $first: Int!) {
|
|
135
|
-
inventoryPositions(after: $after, first: $first) {
|
|
136
|
-
pageInfo { hasNextPage }
|
|
137
|
-
edges {
|
|
138
|
-
cursor
|
|
139
|
-
node {
|
|
140
|
-
ref
|
|
141
|
-
productRef
|
|
142
|
-
locationRef
|
|
143
|
-
qty
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
`,
|
|
149
|
-
variables: { first: 1000, after: cursor },
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
const { edges, pageInfo } = result.data.inventoryPositions;
|
|
153
|
-
|
|
154
|
-
allRecords.push(...edges.map((e) => ({
|
|
155
|
-
...e.node,
|
|
156
|
-
extractedAt: new Date().toISOString(),
|
|
157
|
-
})));
|
|
158
|
-
|
|
159
|
-
hasNextPage = pageInfo.hasNextPage;
|
|
160
|
-
cursor = edges.length > 0 ? edges[edges.length - 1].cursor : null;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
console.log(`✅ Extracted ${allRecords.length} records`);
|
|
164
|
-
|
|
165
|
-
// 4. Generate Parquet Buffer and upload to S3
|
|
166
|
-
const parquetBuffer = await s3.writeParquetContent(allRecords, {
|
|
167
|
-
schema: {
|
|
168
|
-
ref: { type: 'UTF8' },
|
|
169
|
-
productRef: { type: 'UTF8' },
|
|
170
|
-
locationRef: { type: 'UTF8' },
|
|
171
|
-
qty: { type: 'INT32' },
|
|
172
|
-
extractedAt: { type: 'UTF8' },
|
|
173
|
-
},
|
|
174
|
-
compression: 'SNAPPY',
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
await s3.uploadFile(s3Key, parquetBuffer);
|
|
178
|
-
|
|
179
|
-
console.log(`✅ Uploaded to s3://${process.env.S3_BUCKET}/${s3Key}`);
|
|
180
|
-
}
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
**Advantages:**
|
|
184
|
-
- ✅ No temporary files needed
|
|
185
|
-
- ✅ Generates Buffer directly in memory
|
|
186
|
-
- ✅ Upload separately for flexibility
|
|
187
|
-
- ✅ Can upload to S3, SFTP, or save locally
|
|
188
|
-
|
|
189
|
-
### Method 2: Temp File Approach
|
|
190
|
-
|
|
191
|
-
For advanced use cases requiring fine-grained control:
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
import * as parquet from 'parquetjs';
|
|
195
|
-
import * as fs from 'fs/promises';
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Extract from Fluent Commerce and upload to S3
|
|
199
|
-
* Business use case: Daily inventory export to data lake
|
|
200
|
-
*/
|
|
201
|
-
async function extractToS3(s3Key: string): Promise<void> {
|
|
202
|
-
const tempFile = `/tmp/inventory_${Date.now()}.parquet`;
|
|
203
|
-
const logger = toStructuredLogger(createConsoleLogger(), {
|
|
204
|
-
logLevel: 'info'
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
const s3 = new S3DataSource(
|
|
208
|
-
{
|
|
209
|
-
type: 'S3_CSV',
|
|
210
|
-
s3Config: {
|
|
211
|
-
bucket: process.env.S3_BUCKET!,
|
|
212
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
213
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
214
|
-
region: process.env.AWS_REGION!,
|
|
215
|
-
},
|
|
216
|
-
},
|
|
217
|
-
logger
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
try {
|
|
221
|
-
// 1. Extract to local Parquet file
|
|
222
|
-
const schema = new parquet.ParquetSchema({
|
|
223
|
-
ref: { type: 'UTF8' },
|
|
224
|
-
productRef: { type: 'UTF8' },
|
|
225
|
-
locationRef: { type: 'UTF8' },
|
|
226
|
-
qty: { type: 'INT32' },
|
|
227
|
-
extractedAt: { type: 'TIMESTAMP_MILLIS' },
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
const writer = await parquet.ParquetWriter.openFile(schema, tempFile, {
|
|
231
|
-
compression: 'SNAPPY',
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
// 2. Extract data (pagination loop)
|
|
235
|
-
let hasNextPage = true;
|
|
236
|
-
let cursor: string | null = null;
|
|
237
|
-
let totalRecords = 0;
|
|
238
|
-
|
|
239
|
-
while (hasNextPage) {
|
|
240
|
-
const result = await client.graphql({
|
|
241
|
-
query: `
|
|
242
|
-
query ExtractInventory($after: String, $first: Int!) {
|
|
243
|
-
inventoryPositions(after: $after, first: $first) {
|
|
244
|
-
pageInfo { hasNextPage }
|
|
245
|
-
edges {
|
|
246
|
-
cursor
|
|
247
|
-
node {
|
|
248
|
-
ref
|
|
249
|
-
productRef
|
|
250
|
-
locationRef
|
|
251
|
-
qty
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
`,
|
|
257
|
-
variables: { first: 1000, after: cursor },
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
const { edges, pageInfo } = result.data.inventoryPositions;
|
|
261
|
-
|
|
262
|
-
for (const edge of edges) {
|
|
263
|
-
await writer.appendRow({
|
|
264
|
-
...edge.node,
|
|
265
|
-
extractedAt: new Date(),
|
|
266
|
-
});
|
|
267
|
-
totalRecords++;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
hasNextPage = pageInfo.hasNextPage;
|
|
271
|
-
cursor = edges.length > 0 ? edges[edges.length - 1].cursor : null;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
await writer.close();
|
|
275
|
-
console.log(`✅ Extracted ${totalRecords} records to ${tempFile}`);
|
|
276
|
-
|
|
277
|
-
// 3. Upload to S3
|
|
278
|
-
const fileBuffer = await fs.readFile(tempFile);
|
|
279
|
-
await s3.uploadFile(s3Key, fileBuffer, {
|
|
280
|
-
contentType: 'application/octet-stream',
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
console.log(`✅ Uploaded to s3://${process.env.S3_BUCKET}/${s3Key}`);
|
|
284
|
-
|
|
285
|
-
// 4. Cleanup temp file
|
|
286
|
-
await fs.unlink(tempFile);
|
|
287
|
-
} catch (error) {
|
|
288
|
-
// Cleanup on error
|
|
289
|
-
try {
|
|
290
|
-
await fs.unlink(tempFile);
|
|
291
|
-
} catch {}
|
|
292
|
-
throw error;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
---
|
|
298
|
-
|
|
299
|
-
## Streaming S3 to S3
|
|
300
|
-
|
|
301
|
-
```typescript
|
|
302
|
-
import { Buffer } from 'node:buffer'; // Required for Deno/Versori
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Stream Parquet from S3, transform, write to target S3
|
|
306
|
-
* Business use case: Data lake transformation pipeline
|
|
307
|
-
*/
|
|
308
|
-
class S3ParquetStreamer {
|
|
309
|
-
constructor(
|
|
310
|
-
private sourceS3: S3DataSource,
|
|
311
|
-
private targetS3: S3DataSource,
|
|
312
|
-
private parser: ParquetParserService
|
|
313
|
-
) {}
|
|
314
|
-
|
|
315
|
-
async streamParquetToJSON(
|
|
316
|
-
sourceBucket: string,
|
|
317
|
-
sourceKey: string,
|
|
318
|
-
targetBucket: string,
|
|
319
|
-
targetKey: string
|
|
320
|
-
): Promise<void> {
|
|
321
|
-
console.log(`Streaming ${sourceKey}...`);
|
|
322
|
-
|
|
323
|
-
// 1. Download from source S3
|
|
324
|
-
const buffer = await this.sourceS3.downloadFile(sourceKey, { encoding: 'binary' });
|
|
325
|
-
const arrayBuffer = buffer.buffer.slice(
|
|
326
|
-
buffer.byteOffset,
|
|
327
|
-
buffer.byteOffset + buffer.byteLength
|
|
328
|
-
);
|
|
329
|
-
|
|
330
|
-
// 2. Stream parse
|
|
331
|
-
const streamResult = await this.parser.parseStreaming(arrayBuffer, sourceKey, {
|
|
332
|
-
batchSize: 1000,
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
const jsonLines: string[] = [];
|
|
336
|
-
let totalRecords = 0;
|
|
337
|
-
|
|
338
|
-
// 3. Process batches
|
|
339
|
-
for await (const batch of streamResult.records) {
|
|
340
|
-
for (const record of batch) {
|
|
341
|
-
jsonLines.push(JSON.stringify(record));
|
|
342
|
-
totalRecords++;
|
|
343
|
-
|
|
344
|
-
// Write chunks to S3 every 10K records
|
|
345
|
-
if (jsonLines.length >= 10000) {
|
|
346
|
-
await this.writeChunk(targetKey, jsonLines.join('\n'), totalRecords);
|
|
347
|
-
jsonLines.length = 0; // Clear array
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// 4. Write remaining records
|
|
353
|
-
if (jsonLines.length > 0) {
|
|
354
|
-
await this.writeChunk(targetKey, jsonLines.join('\n'), totalRecords);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const stats = await streamResult.stats;
|
|
358
|
-
console.log(`✅ Streaming complete:`);
|
|
359
|
-
console.log(` Total records: ${totalRecords}`);
|
|
360
|
-
console.log(` Processing time: ${stats.processingTimeMs}ms`);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
private async writeChunk(
|
|
364
|
-
targetKeyBase: string,
|
|
365
|
-
content: string,
|
|
366
|
-
recordNumber: number
|
|
367
|
-
): Promise<void> {
|
|
368
|
-
const chunkKey = `${targetKeyBase}_chunk_${Math.floor(recordNumber / 10000)}.jsonl`;
|
|
369
|
-
|
|
370
|
-
await this.targetS3.uploadFile(chunkKey, Buffer.from(content), {
|
|
371
|
-
contentType: 'application/x-ndjson',
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
console.log(` Wrote chunk: ${chunkKey}`);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
---
|
|
380
|
-
|
|
381
|
-
## Multiple File Processing
|
|
382
|
-
|
|
383
|
-
```typescript
|
|
384
|
-
/**
|
|
385
|
-
* Process all Parquet files in S3 prefix
|
|
386
|
-
* Business use case: Batch processing of daily extracts
|
|
387
|
-
*/
|
|
388
|
-
async function processAllParquetFiles(prefix: string): Promise<void> {
|
|
389
|
-
const logger = toStructuredLogger(createConsoleLogger(), {
|
|
390
|
-
logLevel: 'info'
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
const s3 = new S3DataSource(
|
|
394
|
-
{
|
|
395
|
-
type: 'S3_CSV',
|
|
396
|
-
s3Config: {
|
|
397
|
-
bucket: process.env.S3_BUCKET!,
|
|
398
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
399
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
400
|
-
region: process.env.AWS_REGION!,
|
|
401
|
-
},
|
|
402
|
-
},
|
|
403
|
-
logger
|
|
404
|
-
);
|
|
405
|
-
|
|
406
|
-
const parser = new ParquetParserService(logger);
|
|
407
|
-
|
|
408
|
-
// 1. List all Parquet files
|
|
409
|
-
const files = await s3.listFiles({ prefix });
|
|
410
|
-
const parquetFiles = files.filter(f => f.path.endsWith('.parquet'));
|
|
411
|
-
|
|
412
|
-
console.log(`Found ${parquetFiles.length} Parquet files with prefix: ${prefix}`);
|
|
413
|
-
|
|
414
|
-
// 2. Process each file
|
|
415
|
-
for (const file of parquetFiles) {
|
|
416
|
-
try {
|
|
417
|
-
console.log(`\nProcessing ${file.path}...`);
|
|
418
|
-
|
|
419
|
-
const buffer = await s3.downloadFile(file.path, { encoding: 'binary' });
|
|
420
|
-
const arrayBuffer = buffer.buffer.slice(
|
|
421
|
-
buffer.byteOffset,
|
|
422
|
-
buffer.byteOffset + buffer.byteLength
|
|
423
|
-
);
|
|
424
|
-
|
|
425
|
-
const { records, stats } = await parser.parse(arrayBuffer, file.path);
|
|
426
|
-
|
|
427
|
-
console.log(`✅ ${file.path}: ${stats.totalRecords} records`);
|
|
428
|
-
|
|
429
|
-
// Your processing logic
|
|
430
|
-
await processRecords(records, file.key);
|
|
431
|
-
} catch (error) {
|
|
432
|
-
console.error(`❌ Failed to process ${file.path}:`, (error as any).message);
|
|
433
|
-
// Continue processing other files
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
console.log(`\n✅ Batch processing complete`);
|
|
438
|
-
}
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
---
|
|
442
|
-
|
|
443
|
-
## Presigned URL Workflows
|
|
444
|
-
|
|
445
|
-
```typescript
|
|
446
|
-
import { S3PresignService } from '@fluentcommerce/fc-connect-sdk';
|
|
447
|
-
|
|
448
|
-
/**
|
|
449
|
-
* Generate presigned URLs for Parquet downloads
|
|
450
|
-
* Business use case: Secure file sharing with analytics team
|
|
451
|
-
*/
|
|
452
|
-
class ParquetPresignService {
|
|
453
|
-
private presign: S3PresignService;
|
|
454
|
-
|
|
455
|
-
constructor(s3Config: any) {
|
|
456
|
-
this.presign = new S3PresignService(s3Config);
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
async generateDownloadUrl(
|
|
460
|
-
bucket: string,
|
|
461
|
-
key: string,
|
|
462
|
-
expiresIn: number = 3600 // 1 hour
|
|
463
|
-
): Promise<string> {
|
|
464
|
-
const url = await this.presign.getPresignedUrl({
|
|
465
|
-
bucket,
|
|
466
|
-
key,
|
|
467
|
-
operation: 'getObject',
|
|
468
|
-
expiresIn,
|
|
469
|
-
});
|
|
470
|
-
|
|
471
|
-
console.log(`✅ Generated presigned URL for ${key}`);
|
|
472
|
-
console.log(` Expires in: ${expiresIn} seconds`);
|
|
473
|
-
|
|
474
|
-
return url;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
async shareParquetFile(bucket: string, key: string): Promise<void> {
|
|
478
|
-
const url = await this.generateDownloadUrl(bucket, key, 86400); // 24 hours
|
|
479
|
-
|
|
480
|
-
console.log(`\nShare this URL with analytics team:`);
|
|
481
|
-
console.log(url);
|
|
482
|
-
console.log(`\nValid for 24 hours`);
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
---
|
|
488
|
-
|
|
489
|
-
## Key Takeaways
|
|
490
|
-
|
|
491
|
-
- 🎯 **S3DataSource.writeParquetContent()** - Generates Parquet Buffer (then upload separately)
|
|
492
|
-
- 🎯 **S3DataSource integration** - Seamless S3 operations with SDK
|
|
493
|
-
- 🎯 **Stream large files** - Avoid loading entire file into memory
|
|
494
|
-
- 🎯 **Batch processing** - Handle multiple files efficiently
|
|
495
|
-
- 🎯 **Presigned URLs** - Secure file sharing
|
|
496
|
-
- 🎯 **Temp file cleanup** - Only needed for advanced temp file approach
|
|
497
|
-
|
|
498
|
-
---
|
|
499
|
-
|
|
500
|
-
## Next Steps
|
|
501
|
-
|
|
502
|
-
Continue to [Module 7: Performance Optimization](./03-pattern-guides-parquet-07-performance-optimization.md) to learn advanced performance tuning techniques.
|
|
503
|
-
|
|
504
|
-
---
|
|
505
|
-
|
|
506
|
-
[← Previous: Module 5 - GraphQL Extraction](./03-pattern-guides-parquet-05-graphql-extraction.md/) | [Back to Guide](../parquet-readme.md) | [Next: Module 7 - Performance →](./03-pattern-guides-parquet-07-performance-optimization.md)
|
|
507
|
-
|
|
508
|
-
## Related Documentation
|
|
509
|
-
|
|
510
|
-
- [S3 Complete Guide](../../../02-CORE-GUIDES/data-sources/data-sources-readme.md) - Complete S3 patterns
|
|
511
|
-
- [S3 Presigned URLs](../../../02-CORE-GUIDES/data-sources/data-sources-readme.md) - Security and expiration
|
|
1
|
+
# Module 6: S3 Integration
|
|
2
|
+
|
|
3
|
+
[← Back to Parquet Guide](../parquet-readme.md)
|
|
4
|
+
|
|
5
|
+
**Module 6 of 8** | **Level**: Advanced | **Time**: 20 minutes
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Integrate Parquet processing with S3 for data lake operations, including reading from S3, writing to S3, and using presigned URLs.
|
|
12
|
+
|
|
13
|
+
## Learning Objectives
|
|
14
|
+
|
|
15
|
+
By the end of this module, you will:
|
|
16
|
+
|
|
17
|
+
- ✅ Read Parquet files from S3
|
|
18
|
+
- ✅ Write extracted Parquet files to S3
|
|
19
|
+
- ✅ Use streaming for large S3 files
|
|
20
|
+
- ✅ Implement presigned URL workflows
|
|
21
|
+
- ✅ Build complete ETL pipelines
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Reading Parquet from S3
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { Buffer } from 'node:buffer'; // Required for Deno/Versori runtime
|
|
29
|
+
import {
|
|
30
|
+
S3DataSource,
|
|
31
|
+
ParquetParserService,
|
|
32
|
+
createConsoleLogger,
|
|
33
|
+
toStructuredLogger
|
|
34
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
35
|
+
|
|
36
|
+
class S3ParquetProcessor {
|
|
37
|
+
private s3: S3DataSource;
|
|
38
|
+
private parser: ParquetParserService;
|
|
39
|
+
private logger: Logger;
|
|
40
|
+
|
|
41
|
+
constructor(s3Config: any) {
|
|
42
|
+
this.logger = toStructuredLogger(createConsoleLogger(), {
|
|
43
|
+
logLevel: 'info'
|
|
44
|
+
});
|
|
45
|
+
this.s3 = new S3DataSource(
|
|
46
|
+
{
|
|
47
|
+
type: 'S3_CSV',
|
|
48
|
+
s3Config: {
|
|
49
|
+
bucket: process.env.S3_BUCKET!,
|
|
50
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
51
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
52
|
+
region: process.env.AWS_REGION!,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
this.logger
|
|
56
|
+
);
|
|
57
|
+
this.parser = new ParquetParserService(this.logger);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async processParquetFromS3(key: string): Promise<any[]> {
|
|
61
|
+
console.log(`Processing s3://${this.s3.s3Config.bucket}/${key}`);
|
|
62
|
+
|
|
63
|
+
// 1. Download from S3
|
|
64
|
+
const fileBuffer = await this.s3.downloadFile(key, { encoding: 'binary' });
|
|
65
|
+
|
|
66
|
+
// 2. Convert to ArrayBuffer
|
|
67
|
+
const arrayBuffer = fileBuffer.buffer.slice(
|
|
68
|
+
fileBuffer.byteOffset,
|
|
69
|
+
fileBuffer.byteOffset + fileBuffer.byteLength
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// 3. Parse Parquet file
|
|
73
|
+
const { records, stats } = await this.parser.parse(arrayBuffer, key);
|
|
74
|
+
|
|
75
|
+
console.log(`✅ Processed ${stats.totalRecords} records from S3`);
|
|
76
|
+
console.log(` Processing time: ${stats.processingTimeMs}ms`);
|
|
77
|
+
console.log(` File size: ${(stats.fileSizeBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
78
|
+
|
|
79
|
+
return records;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Writing Parquet to S3
|
|
87
|
+
|
|
88
|
+
### Method 1: Direct Write (Recommended)
|
|
89
|
+
|
|
90
|
+
Use `S3DataSource.writeParquetContent()` for streamlined direct writes:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import { S3DataSource, createClient, createConsoleLogger, toStructuredLogger } from '@fluentcommerce/fc-connect-sdk';
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Extract from Fluent Commerce and write directly to S3
|
|
97
|
+
* Business use case: Daily inventory export to data lake
|
|
98
|
+
*/
|
|
99
|
+
async function extractToS3Direct(s3Key: string): Promise<void> {
|
|
100
|
+
const logger = toStructuredLogger(createConsoleLogger(), { service: 'Extraction' });
|
|
101
|
+
|
|
102
|
+
// 1. Setup client
|
|
103
|
+
const client = await createClient({
|
|
104
|
+
config: {
|
|
105
|
+
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
106
|
+
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
107
|
+
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
108
|
+
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// 2. Setup S3
|
|
113
|
+
const s3 = new S3DataSource(
|
|
114
|
+
{
|
|
115
|
+
type: 'S3_CSV',
|
|
116
|
+
s3Config: {
|
|
117
|
+
bucket: process.env.S3_BUCKET!,
|
|
118
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
119
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
120
|
+
region: process.env.AWS_REGION!,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
logger
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// 3. Extract data (pagination loop)
|
|
127
|
+
const allRecords = [];
|
|
128
|
+
let hasNextPage = true;
|
|
129
|
+
let cursor: string | null = null;
|
|
130
|
+
|
|
131
|
+
while (hasNextPage) {
|
|
132
|
+
const result = await client.graphql({
|
|
133
|
+
query: `
|
|
134
|
+
query ExtractInventory($after: String, $first: Int!) {
|
|
135
|
+
inventoryPositions(after: $after, first: $first) {
|
|
136
|
+
pageInfo { hasNextPage }
|
|
137
|
+
edges {
|
|
138
|
+
cursor
|
|
139
|
+
node {
|
|
140
|
+
ref
|
|
141
|
+
productRef
|
|
142
|
+
locationRef
|
|
143
|
+
qty
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
`,
|
|
149
|
+
variables: { first: 1000, after: cursor },
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const { edges, pageInfo } = result.data.inventoryPositions;
|
|
153
|
+
|
|
154
|
+
allRecords.push(...edges.map((e) => ({
|
|
155
|
+
...e.node,
|
|
156
|
+
extractedAt: new Date().toISOString(),
|
|
157
|
+
})));
|
|
158
|
+
|
|
159
|
+
hasNextPage = pageInfo.hasNextPage;
|
|
160
|
+
cursor = edges.length > 0 ? edges[edges.length - 1].cursor : null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
console.log(`✅ Extracted ${allRecords.length} records`);
|
|
164
|
+
|
|
165
|
+
// 4. Generate Parquet Buffer and upload to S3
|
|
166
|
+
const parquetBuffer = await s3.writeParquetContent(allRecords, {
|
|
167
|
+
schema: {
|
|
168
|
+
ref: { type: 'UTF8' },
|
|
169
|
+
productRef: { type: 'UTF8' },
|
|
170
|
+
locationRef: { type: 'UTF8' },
|
|
171
|
+
qty: { type: 'INT32' },
|
|
172
|
+
extractedAt: { type: 'UTF8' },
|
|
173
|
+
},
|
|
174
|
+
compression: 'SNAPPY',
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
await s3.uploadFile(s3Key, parquetBuffer);
|
|
178
|
+
|
|
179
|
+
console.log(`✅ Uploaded to s3://${process.env.S3_BUCKET}/${s3Key}`);
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Advantages:**
|
|
184
|
+
- ✅ No temporary files needed
|
|
185
|
+
- ✅ Generates Buffer directly in memory
|
|
186
|
+
- ✅ Upload separately for flexibility
|
|
187
|
+
- ✅ Can upload to S3, SFTP, or save locally
|
|
188
|
+
|
|
189
|
+
### Method 2: Temp File Approach
|
|
190
|
+
|
|
191
|
+
For advanced use cases requiring fine-grained control:
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import * as parquet from 'parquetjs';
|
|
195
|
+
import * as fs from 'fs/promises';
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Extract from Fluent Commerce and upload to S3
|
|
199
|
+
* Business use case: Daily inventory export to data lake
|
|
200
|
+
*/
|
|
201
|
+
async function extractToS3(s3Key: string): Promise<void> {
|
|
202
|
+
const tempFile = `/tmp/inventory_${Date.now()}.parquet`;
|
|
203
|
+
const logger = toStructuredLogger(createConsoleLogger(), {
|
|
204
|
+
logLevel: 'info'
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const s3 = new S3DataSource(
|
|
208
|
+
{
|
|
209
|
+
type: 'S3_CSV',
|
|
210
|
+
s3Config: {
|
|
211
|
+
bucket: process.env.S3_BUCKET!,
|
|
212
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
213
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
214
|
+
region: process.env.AWS_REGION!,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
logger
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
// 1. Extract to local Parquet file
|
|
222
|
+
const schema = new parquet.ParquetSchema({
|
|
223
|
+
ref: { type: 'UTF8' },
|
|
224
|
+
productRef: { type: 'UTF8' },
|
|
225
|
+
locationRef: { type: 'UTF8' },
|
|
226
|
+
qty: { type: 'INT32' },
|
|
227
|
+
extractedAt: { type: 'TIMESTAMP_MILLIS' },
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const writer = await parquet.ParquetWriter.openFile(schema, tempFile, {
|
|
231
|
+
compression: 'SNAPPY',
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// 2. Extract data (pagination loop)
|
|
235
|
+
let hasNextPage = true;
|
|
236
|
+
let cursor: string | null = null;
|
|
237
|
+
let totalRecords = 0;
|
|
238
|
+
|
|
239
|
+
while (hasNextPage) {
|
|
240
|
+
const result = await client.graphql({
|
|
241
|
+
query: `
|
|
242
|
+
query ExtractInventory($after: String, $first: Int!) {
|
|
243
|
+
inventoryPositions(after: $after, first: $first) {
|
|
244
|
+
pageInfo { hasNextPage }
|
|
245
|
+
edges {
|
|
246
|
+
cursor
|
|
247
|
+
node {
|
|
248
|
+
ref
|
|
249
|
+
productRef
|
|
250
|
+
locationRef
|
|
251
|
+
qty
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
`,
|
|
257
|
+
variables: { first: 1000, after: cursor },
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
const { edges, pageInfo } = result.data.inventoryPositions;
|
|
261
|
+
|
|
262
|
+
for (const edge of edges) {
|
|
263
|
+
await writer.appendRow({
|
|
264
|
+
...edge.node,
|
|
265
|
+
extractedAt: new Date(),
|
|
266
|
+
});
|
|
267
|
+
totalRecords++;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
hasNextPage = pageInfo.hasNextPage;
|
|
271
|
+
cursor = edges.length > 0 ? edges[edges.length - 1].cursor : null;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
await writer.close();
|
|
275
|
+
console.log(`✅ Extracted ${totalRecords} records to ${tempFile}`);
|
|
276
|
+
|
|
277
|
+
// 3. Upload to S3
|
|
278
|
+
const fileBuffer = await fs.readFile(tempFile);
|
|
279
|
+
await s3.uploadFile(s3Key, fileBuffer, {
|
|
280
|
+
contentType: 'application/octet-stream',
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
console.log(`✅ Uploaded to s3://${process.env.S3_BUCKET}/${s3Key}`);
|
|
284
|
+
|
|
285
|
+
// 4. Cleanup temp file
|
|
286
|
+
await fs.unlink(tempFile);
|
|
287
|
+
} catch (error) {
|
|
288
|
+
// Cleanup on error
|
|
289
|
+
try {
|
|
290
|
+
await fs.unlink(tempFile);
|
|
291
|
+
} catch {}
|
|
292
|
+
throw error;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Streaming S3 to S3
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
import { Buffer } from 'node:buffer'; // Required for Deno/Versori
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Stream Parquet from S3, transform, write to target S3
|
|
306
|
+
* Business use case: Data lake transformation pipeline
|
|
307
|
+
*/
|
|
308
|
+
class S3ParquetStreamer {
|
|
309
|
+
constructor(
|
|
310
|
+
private sourceS3: S3DataSource,
|
|
311
|
+
private targetS3: S3DataSource,
|
|
312
|
+
private parser: ParquetParserService
|
|
313
|
+
) {}
|
|
314
|
+
|
|
315
|
+
async streamParquetToJSON(
|
|
316
|
+
sourceBucket: string,
|
|
317
|
+
sourceKey: string,
|
|
318
|
+
targetBucket: string,
|
|
319
|
+
targetKey: string
|
|
320
|
+
): Promise<void> {
|
|
321
|
+
console.log(`Streaming ${sourceKey}...`);
|
|
322
|
+
|
|
323
|
+
// 1. Download from source S3
|
|
324
|
+
const buffer = await this.sourceS3.downloadFile(sourceKey, { encoding: 'binary' });
|
|
325
|
+
const arrayBuffer = buffer.buffer.slice(
|
|
326
|
+
buffer.byteOffset,
|
|
327
|
+
buffer.byteOffset + buffer.byteLength
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
// 2. Stream parse
|
|
331
|
+
const streamResult = await this.parser.parseStreaming(arrayBuffer, sourceKey, {
|
|
332
|
+
batchSize: 1000,
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
const jsonLines: string[] = [];
|
|
336
|
+
let totalRecords = 0;
|
|
337
|
+
|
|
338
|
+
// 3. Process batches
|
|
339
|
+
for await (const batch of streamResult.records) {
|
|
340
|
+
for (const record of batch) {
|
|
341
|
+
jsonLines.push(JSON.stringify(record));
|
|
342
|
+
totalRecords++;
|
|
343
|
+
|
|
344
|
+
// Write chunks to S3 every 10K records
|
|
345
|
+
if (jsonLines.length >= 10000) {
|
|
346
|
+
await this.writeChunk(targetKey, jsonLines.join('\n'), totalRecords);
|
|
347
|
+
jsonLines.length = 0; // Clear array
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// 4. Write remaining records
|
|
353
|
+
if (jsonLines.length > 0) {
|
|
354
|
+
await this.writeChunk(targetKey, jsonLines.join('\n'), totalRecords);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const stats = await streamResult.stats;
|
|
358
|
+
console.log(`✅ Streaming complete:`);
|
|
359
|
+
console.log(` Total records: ${totalRecords}`);
|
|
360
|
+
console.log(` Processing time: ${stats.processingTimeMs}ms`);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
private async writeChunk(
|
|
364
|
+
targetKeyBase: string,
|
|
365
|
+
content: string,
|
|
366
|
+
recordNumber: number
|
|
367
|
+
): Promise<void> {
|
|
368
|
+
const chunkKey = `${targetKeyBase}_chunk_${Math.floor(recordNumber / 10000)}.jsonl`;
|
|
369
|
+
|
|
370
|
+
await this.targetS3.uploadFile(chunkKey, Buffer.from(content), {
|
|
371
|
+
contentType: 'application/x-ndjson',
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
console.log(` Wrote chunk: ${chunkKey}`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## Multiple File Processing
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
/**
|
|
385
|
+
* Process all Parquet files in S3 prefix
|
|
386
|
+
* Business use case: Batch processing of daily extracts
|
|
387
|
+
*/
|
|
388
|
+
async function processAllParquetFiles(prefix: string): Promise<void> {
|
|
389
|
+
const logger = toStructuredLogger(createConsoleLogger(), {
|
|
390
|
+
logLevel: 'info'
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
const s3 = new S3DataSource(
|
|
394
|
+
{
|
|
395
|
+
type: 'S3_CSV',
|
|
396
|
+
s3Config: {
|
|
397
|
+
bucket: process.env.S3_BUCKET!,
|
|
398
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
399
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
400
|
+
region: process.env.AWS_REGION!,
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
logger
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
const parser = new ParquetParserService(logger);
|
|
407
|
+
|
|
408
|
+
// 1. List all Parquet files
|
|
409
|
+
const files = await s3.listFiles({ prefix });
|
|
410
|
+
const parquetFiles = files.filter(f => f.path.endsWith('.parquet'));
|
|
411
|
+
|
|
412
|
+
console.log(`Found ${parquetFiles.length} Parquet files with prefix: ${prefix}`);
|
|
413
|
+
|
|
414
|
+
// 2. Process each file
|
|
415
|
+
for (const file of parquetFiles) {
|
|
416
|
+
try {
|
|
417
|
+
console.log(`\nProcessing ${file.path}...`);
|
|
418
|
+
|
|
419
|
+
const buffer = await s3.downloadFile(file.path, { encoding: 'binary' });
|
|
420
|
+
const arrayBuffer = buffer.buffer.slice(
|
|
421
|
+
buffer.byteOffset,
|
|
422
|
+
buffer.byteOffset + buffer.byteLength
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
const { records, stats } = await parser.parse(arrayBuffer, file.path);
|
|
426
|
+
|
|
427
|
+
console.log(`✅ ${file.path}: ${stats.totalRecords} records`);
|
|
428
|
+
|
|
429
|
+
// Your processing logic
|
|
430
|
+
await processRecords(records, file.key);
|
|
431
|
+
} catch (error) {
|
|
432
|
+
console.error(`❌ Failed to process ${file.path}:`, (error as any).message);
|
|
433
|
+
// Continue processing other files
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
console.log(`\n✅ Batch processing complete`);
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## Presigned URL Workflows
|
|
444
|
+
|
|
445
|
+
```typescript
|
|
446
|
+
import { S3PresignService } from '@fluentcommerce/fc-connect-sdk';
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Generate presigned URLs for Parquet downloads
|
|
450
|
+
* Business use case: Secure file sharing with analytics team
|
|
451
|
+
*/
|
|
452
|
+
class ParquetPresignService {
|
|
453
|
+
private presign: S3PresignService;
|
|
454
|
+
|
|
455
|
+
constructor(s3Config: any) {
|
|
456
|
+
this.presign = new S3PresignService(s3Config);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
async generateDownloadUrl(
|
|
460
|
+
bucket: string,
|
|
461
|
+
key: string,
|
|
462
|
+
expiresIn: number = 3600 // 1 hour
|
|
463
|
+
): Promise<string> {
|
|
464
|
+
const url = await this.presign.getPresignedUrl({
|
|
465
|
+
bucket,
|
|
466
|
+
key,
|
|
467
|
+
operation: 'getObject',
|
|
468
|
+
expiresIn,
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
console.log(`✅ Generated presigned URL for ${key}`);
|
|
472
|
+
console.log(` Expires in: ${expiresIn} seconds`);
|
|
473
|
+
|
|
474
|
+
return url;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
async shareParquetFile(bucket: string, key: string): Promise<void> {
|
|
478
|
+
const url = await this.generateDownloadUrl(bucket, key, 86400); // 24 hours
|
|
479
|
+
|
|
480
|
+
console.log(`\nShare this URL with analytics team:`);
|
|
481
|
+
console.log(url);
|
|
482
|
+
console.log(`\nValid for 24 hours`);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## Key Takeaways
|
|
490
|
+
|
|
491
|
+
- 🎯 **S3DataSource.writeParquetContent()** - Generates Parquet Buffer (then upload separately)
|
|
492
|
+
- 🎯 **S3DataSource integration** - Seamless S3 operations with SDK
|
|
493
|
+
- 🎯 **Stream large files** - Avoid loading entire file into memory
|
|
494
|
+
- 🎯 **Batch processing** - Handle multiple files efficiently
|
|
495
|
+
- 🎯 **Presigned URLs** - Secure file sharing
|
|
496
|
+
- 🎯 **Temp file cleanup** - Only needed for advanced temp file approach
|
|
497
|
+
|
|
498
|
+
---
|
|
499
|
+
|
|
500
|
+
## Next Steps
|
|
501
|
+
|
|
502
|
+
Continue to [Module 7: Performance Optimization](./03-pattern-guides-parquet-07-performance-optimization.md) to learn advanced performance tuning techniques.
|
|
503
|
+
|
|
504
|
+
---
|
|
505
|
+
|
|
506
|
+
[← Previous: Module 5 - GraphQL Extraction](./03-pattern-guides-parquet-05-graphql-extraction.md/) | [Back to Guide](../parquet-readme.md) | [Next: Module 7 - Performance →](./03-pattern-guides-parquet-07-performance-optimization.md)
|
|
507
|
+
|
|
508
|
+
## Related Documentation
|
|
509
|
+
|
|
510
|
+
- [S3 Complete Guide](../../../02-CORE-GUIDES/data-sources/data-sources-readme.md) - Complete S3 patterns
|
|
511
|
+
- [S3 Presigned URLs](../../../02-CORE-GUIDES/data-sources/data-sources-readme.md) - Security and expiration
|