@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,603 +1,603 @@
|
|
|
1
|
-
# Module 5: Parquet Parser
|
|
2
|
-
|
|
3
|
-
**Level:** Advanced
|
|
4
|
-
**Estimated Time:** 20 minutes
|
|
5
|
-
|
|
6
|
-
## Overview
|
|
7
|
-
|
|
8
|
-
This module covers the Parquet Parser (`ParquetParserService`), designed for efficient large-scale data extraction and analytics. You'll learn how to parse Parquet files, leverage columnar storage, handle compression, and integrate with S3 for data extraction workflows.
|
|
9
|
-
|
|
10
|
-
## Learning Objectives
|
|
11
|
-
|
|
12
|
-
By the end of this module, you will:
|
|
13
|
-
- ✅ Understand Parquet columnar format and its benefits
|
|
14
|
-
- ✅ Parse Parquet files into JavaScript objects
|
|
15
|
-
- ✅ Stream large Parquet files efficiently
|
|
16
|
-
- ✅ Leverage compression and columnar storage
|
|
17
|
-
- ✅ Extract Fluent data to Parquet for analytics
|
|
18
|
-
- ✅ Integrate with S3 extraction workflows
|
|
19
|
-
|
|
20
|
-
## What is Parquet?
|
|
21
|
-
|
|
22
|
-
**Apache Parquet** is a columnar storage format that:
|
|
23
|
-
- Stores data by column instead of by row
|
|
24
|
-
- Uses efficient compression algorithms
|
|
25
|
-
- Optimizes for analytical queries
|
|
26
|
-
- Reduces file size significantly (often 10:1 compression)
|
|
27
|
-
- Is the standard for big data and analytics
|
|
28
|
-
|
|
29
|
-
**Row-based vs Column-based storage:**
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
Row-based (CSV):
|
|
33
|
-
SKU001,100,WH-01
|
|
34
|
-
SKU002,50,WH-01
|
|
35
|
-
SKU003,75,WH-02
|
|
36
|
-
|
|
37
|
-
Column-based (Parquet):
|
|
38
|
-
Column[sku]: [SKU001, SKU002, SKU003]
|
|
39
|
-
Column[qty]: [100, 50, 75]
|
|
40
|
-
Column[location]: [WH-01, WH-01, WH-02]
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
**Benefits:**
|
|
44
|
-
- ✅ Better compression (similar values in a column compress well)
|
|
45
|
-
- ✅ Faster column-specific queries
|
|
46
|
-
- ✅ Smaller file sizes
|
|
47
|
-
- ✅ Efficient for analytics
|
|
48
|
-
|
|
49
|
-
## Basic Parquet Parsing
|
|
50
|
-
|
|
51
|
-
### Simple Parsing
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
import { ParquetParserService, createConsoleLogger, toStructuredLogger } from '@fluentcommerce/fc-connect-sdk';
|
|
55
|
-
import * as fs from 'fs/promises';
|
|
56
|
-
|
|
57
|
-
// ParquetParserService requires a StructuredLogger (not a simple logger)
|
|
58
|
-
const consoleLogger = createConsoleLogger();
|
|
59
|
-
const logger = toStructuredLogger(consoleLogger, { service: 'ParquetParser' });
|
|
60
|
-
|
|
61
|
-
// CRITICAL: Constructor requires logger parameter (NOT optional)
|
|
62
|
-
const parquetParser = new ParquetParserService(logger);
|
|
63
|
-
|
|
64
|
-
// Read Parquet file
|
|
65
|
-
const fileBuffer = await fs.readFile('inventory.parquet');
|
|
66
|
-
|
|
67
|
-
// Convert to ArrayBuffer (parseSimple requires ArrayBuffer, not Buffer)
|
|
68
|
-
const arrayBuffer = fileBuffer.buffer.slice(
|
|
69
|
-
fileBuffer.byteOffset,
|
|
70
|
-
fileBuffer.byteOffset + fileBuffer.byteLength
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
// Parse Parquet (simple mode - easiest)
|
|
74
|
-
const records = await parquetParser.parseSimple(arrayBuffer, 'inventory.parquet');
|
|
75
|
-
|
|
76
|
-
console.log(`Parsed ${records.length} records`);
|
|
77
|
-
console.log('First record:', records[0]);
|
|
78
|
-
// { sku: 'SKU001', qty: 100, location: 'WH-01' }
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Type Safety with TypeScript
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
// Define your record structure
|
|
85
|
-
interface InventoryRecord {
|
|
86
|
-
sku: string;
|
|
87
|
-
qty: number;
|
|
88
|
-
location: string;
|
|
89
|
-
updatedAt: Date;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Parse with type assertion (simple mode)
|
|
93
|
-
const records = await parquetParser.parseSimple(arrayBuffer, 'inventory.parquet');
|
|
94
|
-
|
|
95
|
-
// Or use parse() for detailed stats
|
|
96
|
-
const result = await parquetParser.parse(arrayBuffer, 'inventory.parquet');
|
|
97
|
-
console.log(`Processed ${result.stats.totalRecords} records in ${result.stats.processingTimeMs}ms`);
|
|
98
|
-
|
|
99
|
-
// Full type safety
|
|
100
|
-
result.records.forEach(record => {
|
|
101
|
-
console.log(`${record.sku}: ${record.qty} at ${record.location}`);
|
|
102
|
-
});
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Streaming Large Files
|
|
106
|
-
|
|
107
|
-
For large Parquet files, use streaming to avoid memory issues:
|
|
108
|
-
|
|
109
|
-
### Basic Streaming
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
import { ParquetParserService, createConsoleLogger, toStructuredLogger } from '@fluentcommerce/fc-connect-sdk';
|
|
113
|
-
|
|
114
|
-
const consoleLogger = createConsoleLogger();
|
|
115
|
-
const logger = toStructuredLogger(consoleLogger, { service: 'ParquetParser' });
|
|
116
|
-
|
|
117
|
-
const parquetParser = new ParquetParserService(logger);
|
|
118
|
-
|
|
119
|
-
// Stream Parquet file
|
|
120
|
-
const fileBuffer = await fs.readFile('large-inventory.parquet');
|
|
121
|
-
|
|
122
|
-
// Convert to ArrayBuffer
|
|
123
|
-
const arrayBuffer = fileBuffer.buffer.slice(
|
|
124
|
-
fileBuffer.byteOffset,
|
|
125
|
-
fileBuffer.byteOffset + fileBuffer.byteLength
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
// Process records in batches
|
|
129
|
-
const batchSize = 1000;
|
|
130
|
-
|
|
131
|
-
const streamingResult = await parquetParser.parseStreaming(
|
|
132
|
-
arrayBuffer,
|
|
133
|
-
'large-inventory.parquet',
|
|
134
|
-
{ batchSize }
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
for await (const batch of streamingResult.records) {
|
|
138
|
-
console.log(`Processing batch of ${batch.length} records`);
|
|
139
|
-
await processBatch(batch);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Get final stats
|
|
143
|
-
const stats = await streamingResult.stats;
|
|
144
|
-
console.log(`Processed ${stats.totalRecords} total records`);
|
|
145
|
-
|
|
146
|
-
async function processBatch(records: any[]) {
|
|
147
|
-
// Transform and process
|
|
148
|
-
console.log(`Batch processing ${records.length} records`);
|
|
149
|
-
}
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
### Streaming with Progress Tracking
|
|
153
|
-
|
|
154
|
-
```typescript
|
|
155
|
-
async function streamWithProgress(parquetBuffer: ArrayBuffer) {
|
|
156
|
-
const logger = createConsoleLogger();
|
|
157
|
-
const parquetParser = new ParquetParserService(logger);
|
|
158
|
-
const startTime = Date.now();
|
|
159
|
-
let totalRecords = 0;
|
|
160
|
-
|
|
161
|
-
const streamingResult = await parquetParser.parseStreaming(
|
|
162
|
-
parquetBuffer,
|
|
163
|
-
'file.parquet',
|
|
164
|
-
{ batchSize: 1000 }
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
for await (const batch of streamingResult.records) {
|
|
168
|
-
totalRecords += batch.length;
|
|
169
|
-
|
|
170
|
-
// Process batch
|
|
171
|
-
await processBatch(batch);
|
|
172
|
-
|
|
173
|
-
// Report progress
|
|
174
|
-
const elapsed = (Date.now() - startTime) / 1000;
|
|
175
|
-
const rate = totalRecords / elapsed;
|
|
176
|
-
console.log(`Processed ${totalRecords} records (${rate.toFixed(2)} records/sec)`);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const stats = await streamingResult.stats;
|
|
180
|
-
console.log(`Completed: ${stats.totalRecords} total records`);
|
|
181
|
-
}
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
## Parser Configuration
|
|
185
|
-
|
|
186
|
-
The Parquet parser supports various options:
|
|
187
|
-
|
|
188
|
-
```typescript
|
|
189
|
-
interface ParquetParsingOptions {
|
|
190
|
-
// Batch size for streaming (default: 1000)
|
|
191
|
-
batchSize?: number;
|
|
192
|
-
|
|
193
|
-
// Maximum file size in bytes (default: 100MB)
|
|
194
|
-
maxFileSize?: number;
|
|
195
|
-
|
|
196
|
-
// Enable streaming mode (default: true)
|
|
197
|
-
enableStreaming?: boolean;
|
|
198
|
-
|
|
199
|
-
// Validation options
|
|
200
|
-
validation?: {
|
|
201
|
-
enabled?: boolean;
|
|
202
|
-
requiredColumns?: string[];
|
|
203
|
-
columnTypes?: Record<string, ParquetDataType>;
|
|
204
|
-
allowAdditionalColumns?: boolean;
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### Example Configuration
|
|
210
|
-
|
|
211
|
-
```typescript
|
|
212
|
-
const options: ParquetParsingOptions = {
|
|
213
|
-
batchSize: 5000,
|
|
214
|
-
maxFileSize: 500 * 1024 * 1024, // 500MB
|
|
215
|
-
enableStreaming: true,
|
|
216
|
-
validation: {
|
|
217
|
-
enabled: true,
|
|
218
|
-
requiredColumns: ['sku', 'qty', 'location'],
|
|
219
|
-
columnTypes: {
|
|
220
|
-
sku: 'string',
|
|
221
|
-
qty: 'number',
|
|
222
|
-
location: 'string'
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
const result = await parquetParser.parse(parquetBuffer, 'file.parquet', options);
|
|
228
|
-
const records = result.records;
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
## Data Extraction Workflow
|
|
232
|
-
|
|
233
|
-
The primary use case for Parquet is extracting large datasets from Fluent Commerce to S3.
|
|
234
|
-
|
|
235
|
-
### Complete Extraction Example
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
import {
|
|
239
|
-
createClient,
|
|
240
|
-
ParquetParserService,
|
|
241
|
-
S3DataSource,
|
|
242
|
-
createConsoleLogger
|
|
243
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
244
|
-
|
|
245
|
-
async function extractInventoryToParquet() {
|
|
246
|
-
// 1. Setup logger
|
|
247
|
-
const logger = createConsoleLogger();
|
|
248
|
-
|
|
249
|
-
// 2. Create client
|
|
250
|
-
const client = await createClient({
|
|
251
|
-
config: {
|
|
252
|
-
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
253
|
-
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
254
|
-
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
255
|
-
retailerId: process.env.FLUENT_RETAILER_ID!
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
// 3. Fetch data from Fluent (with auto-pagination)
|
|
260
|
-
const result = await client.graphql({
|
|
261
|
-
query: `
|
|
262
|
-
query GetVirtualPositions($first: Int!, $after: String) {
|
|
263
|
-
virtualPositions(first: $first, after: $after) {
|
|
264
|
-
edges {
|
|
265
|
-
node {
|
|
266
|
-
id
|
|
267
|
-
productRef
|
|
268
|
-
quantity
|
|
269
|
-
groupRef
|
|
270
|
-
createdOn
|
|
271
|
-
updatedOn
|
|
272
|
-
}
|
|
273
|
-
cursor
|
|
274
|
-
}
|
|
275
|
-
pageInfo {
|
|
276
|
-
hasNextPage
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
`,
|
|
281
|
-
variables: { first: 1000 },
|
|
282
|
-
pagination: { maxPages: 100 }
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
// 4. Transform to flat structure
|
|
286
|
-
const records = result.data.virtualPositions.edges.map(edge => ({
|
|
287
|
-
id: edge.node.id,
|
|
288
|
-
productRef: edge.node.productRef,
|
|
289
|
-
quantity: edge.node.quantity,
|
|
290
|
-
groupRef: edge.node.groupRef,
|
|
291
|
-
createdOn: edge.node.createdOn,
|
|
292
|
-
updatedOn: edge.node.updatedOn
|
|
293
|
-
}));
|
|
294
|
-
|
|
295
|
-
console.log(`Extracted ${records.length} virtual positions`);
|
|
296
|
-
|
|
297
|
-
// 5. Convert to Parquet (using parquetjs or hyparquet)
|
|
298
|
-
const parquetBuffer = await convertToParquet(records);
|
|
299
|
-
|
|
300
|
-
// 6. Upload to S3 using S3DataSource
|
|
301
|
-
const s3DataSource = new S3DataSource({
|
|
302
|
-
type: 'S3_PARQUET',
|
|
303
|
-
connectionId: 's3-parquet-extract',
|
|
304
|
-
name: 'S3 Parquet Extract',
|
|
305
|
-
s3Config: {
|
|
306
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
307
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
308
|
-
region: process.env.AWS_REGION!,
|
|
309
|
-
bucket: 'my-analytics-bucket'
|
|
310
|
-
}
|
|
311
|
-
}, logger);
|
|
312
|
-
|
|
313
|
-
await s3DataSource.uploadFile(
|
|
314
|
-
`extracts/virtual-positions-${new Date().toISOString()}.parquet`,
|
|
315
|
-
parquetBuffer,
|
|
316
|
-
{ contentType: 'application/octet-stream' }
|
|
317
|
-
);
|
|
318
|
-
|
|
319
|
-
console.log('✅ Extraction complete!');
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
async function convertToParquet(records: any[]): Promise<Buffer> {
|
|
323
|
-
// Use parquetjs or hyparquet to convert
|
|
324
|
-
// Implementation depends on your choice of Parquet library
|
|
325
|
-
const parquetWriter = /* ... */;
|
|
326
|
-
// Write records and return buffer
|
|
327
|
-
return buffer;
|
|
328
|
-
}
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
## Performance Metrics
|
|
332
|
-
|
|
333
|
-
Get performance statistics from parsing operations:
|
|
334
|
-
|
|
335
|
-
```typescript
|
|
336
|
-
const logger = createConsoleLogger();
|
|
337
|
-
const parquetParser = new ParquetParserService(logger);
|
|
338
|
-
|
|
339
|
-
// Parse file
|
|
340
|
-
const result = await parquetParser.parse(parquetBuffer, 'file.parquet');
|
|
341
|
-
|
|
342
|
-
// Access parsing statistics
|
|
343
|
-
console.log('Parsing statistics:');
|
|
344
|
-
console.log(`Total records: ${result.stats.totalRecords}`);
|
|
345
|
-
console.log(`Processing time: ${result.stats.processingTimeMs}ms`);
|
|
346
|
-
console.log(`Peak memory usage: ${(result.stats.peakMemoryUsage / 1024 / 1024).toFixed(2)}MB`);
|
|
347
|
-
console.log(`Records per second: ${result.stats.recordsPerSecond}`);
|
|
348
|
-
console.log(`Batches processed: ${result.stats.batchesProcessed}`);
|
|
349
|
-
|
|
350
|
-
// Get overall performance metrics
|
|
351
|
-
const metrics = parquetParser.getPerformanceMetrics();
|
|
352
|
-
console.log('Overall metrics:', metrics);
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
## Validation
|
|
356
|
-
|
|
357
|
-
Validate Parquet structure:
|
|
358
|
-
|
|
359
|
-
```typescript
|
|
360
|
-
const logger = createConsoleLogger();
|
|
361
|
-
const parquetParser = new ParquetParserService(logger);
|
|
362
|
-
|
|
363
|
-
// Validate Parquet file
|
|
364
|
-
const validation = await parquetParser.validateFile(parquetBuffer, 'file.parquet');
|
|
365
|
-
|
|
366
|
-
if (validation.isValid) {
|
|
367
|
-
console.log('Parquet file is valid');
|
|
368
|
-
const records = await parquetParser.parseSimple(parquetBuffer, 'file.parquet');
|
|
369
|
-
} else {
|
|
370
|
-
console.error('Validation errors:', validation.errors);
|
|
371
|
-
}
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
## Integration with S3
|
|
375
|
-
|
|
376
|
-
### Read Parquet from S3
|
|
377
|
-
|
|
378
|
-
```typescript
|
|
379
|
-
import { S3DataSource, ParquetParserService, createConsoleLogger } from '@fluentcommerce/fc-connect-sdk';
|
|
380
|
-
|
|
381
|
-
async function readParquetFromS3() {
|
|
382
|
-
const logger = createConsoleLogger();
|
|
383
|
-
|
|
384
|
-
// Initialize S3 data source
|
|
385
|
-
const s3DataSource = new S3DataSource({
|
|
386
|
-
type: 'S3_PARQUET',
|
|
387
|
-
connectionId: 's3-parquet-read',
|
|
388
|
-
name: 'S3 Parquet Read',
|
|
389
|
-
s3Config: {
|
|
390
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
391
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
392
|
-
region: process.env.AWS_REGION!,
|
|
393
|
-
bucket: 'my-data-bucket'
|
|
394
|
-
}
|
|
395
|
-
}, logger);
|
|
396
|
-
|
|
397
|
-
// Download Parquet file from S3
|
|
398
|
-
const parquetBuffer = await s3DataSource.downloadFile('extracts/inventory.parquet');
|
|
399
|
-
|
|
400
|
-
// Parse Parquet
|
|
401
|
-
const parquetParser = new ParquetParserService(logger);
|
|
402
|
-
const records = await parquetParser.parseSimple(parquetBuffer, 'inventory.parquet');
|
|
403
|
-
|
|
404
|
-
console.log(`Loaded ${records.length} records from S3`);
|
|
405
|
-
return records;
|
|
406
|
-
}
|
|
407
|
-
```
|
|
408
|
-
|
|
409
|
-
### Write Parquet to S3
|
|
410
|
-
|
|
411
|
-
```typescript
|
|
412
|
-
async function writeParquetToS3(records: any[]) {
|
|
413
|
-
const logger = createConsoleLogger();
|
|
414
|
-
|
|
415
|
-
// Convert to Parquet
|
|
416
|
-
const parquetBuffer = await convertToParquet(records);
|
|
417
|
-
|
|
418
|
-
// Upload to S3 using S3DataSource
|
|
419
|
-
const s3DataSource = new S3DataSource({
|
|
420
|
-
type: 'S3_PARQUET',
|
|
421
|
-
connectionId: 's3-parquet-write',
|
|
422
|
-
name: 'S3 Parquet Write',
|
|
423
|
-
s3Config: {
|
|
424
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
425
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
426
|
-
region: process.env.AWS_REGION!,
|
|
427
|
-
bucket: 'my-analytics-bucket'
|
|
428
|
-
}
|
|
429
|
-
}, logger);
|
|
430
|
-
|
|
431
|
-
await s3DataSource.uploadFile(
|
|
432
|
-
`extracts/data-${Date.now()}.parquet`,
|
|
433
|
-
parquetBuffer,
|
|
434
|
-
{ contentType: 'application/octet-stream' }
|
|
435
|
-
);
|
|
436
|
-
|
|
437
|
-
console.log('✅ Parquet file uploaded to S3');
|
|
438
|
-
}
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
## Performance Optimization
|
|
442
|
-
|
|
443
|
-
### 1. Use Appropriate Batch Sizes
|
|
444
|
-
|
|
445
|
-
```typescript
|
|
446
|
-
// Small batches for memory-constrained environments
|
|
447
|
-
const smallBatch = await parquetParser.parseStreaming(parquetBuffer, {
|
|
448
|
-
batchSize: 500
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
// Large batches for high-memory environments
|
|
452
|
-
const largeBatch = await parquetParser.parseStreaming(parquetBuffer, {
|
|
453
|
-
batchSize: 10000
|
|
454
|
-
});
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
### 2. Leverage Compression
|
|
458
|
-
|
|
459
|
-
Parquet automatically compresses data, but you can optimize:
|
|
460
|
-
|
|
461
|
-
```typescript
|
|
462
|
-
// When creating Parquet files, use optimal compression
|
|
463
|
-
const parquetOptions = {
|
|
464
|
-
compression: 'SNAPPY', // Fast compression/decompression
|
|
465
|
-
// or 'GZIP' for better compression ratio
|
|
466
|
-
};
|
|
467
|
-
```
|
|
468
|
-
|
|
469
|
-
### 3. Column Pruning
|
|
470
|
-
|
|
471
|
-
Only read columns you need (when using advanced Parquet libraries):
|
|
472
|
-
|
|
473
|
-
```typescript
|
|
474
|
-
// Only read specific columns
|
|
475
|
-
const selectedColumns = await parquetParser.parse(parquetBuffer, {
|
|
476
|
-
columns: ['sku', 'qty'] // Only read these columns
|
|
477
|
-
});
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
## Real-World Example: Analytics Pipeline
|
|
481
|
-
|
|
482
|
-
Complete pipeline for extracting Fluent data to analytics warehouse:
|
|
483
|
-
|
|
484
|
-
```typescript
|
|
485
|
-
import {
|
|
486
|
-
createClient,
|
|
487
|
-
ParquetParserService,
|
|
488
|
-
S3DataSource,
|
|
489
|
-
createConsoleLogger
|
|
490
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
491
|
-
|
|
492
|
-
async function dailyInventoryExtract() {
|
|
493
|
-
const logger = createConsoleLogger();
|
|
494
|
-
const client = await createClient({ config });
|
|
495
|
-
|
|
496
|
-
const s3DataSource = new S3DataSource({
|
|
497
|
-
type: 'S3_PARQUET',
|
|
498
|
-
connectionId: 's3-analytics',
|
|
499
|
-
name: 'S3 Analytics',
|
|
500
|
-
s3Config: {
|
|
501
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
502
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
503
|
-
region: process.env.AWS_REGION!,
|
|
504
|
-
bucket: 'analytics-warehouse'
|
|
505
|
-
}
|
|
506
|
-
}, logger);
|
|
507
|
-
|
|
508
|
-
// 1. Extract inventory from Fluent
|
|
509
|
-
const result = await client.graphql({
|
|
510
|
-
query: inventoryQuery,
|
|
511
|
-
variables: { first: 1000 },
|
|
512
|
-
pagination: { maxRecords: 1000000 }
|
|
513
|
-
});
|
|
514
|
-
|
|
515
|
-
const records = result.data.inventoryPositions.edges.map(e => e.node);
|
|
516
|
-
|
|
517
|
-
console.log(`Extracted ${records.length} inventory positions`);
|
|
518
|
-
|
|
519
|
-
// 2. Convert to Parquet
|
|
520
|
-
const parquetBuffer = await convertToParquet(records);
|
|
521
|
-
|
|
522
|
-
// 3. Upload to S3 analytics bucket
|
|
523
|
-
const timestamp = new Date().toISOString().split('T')[0];
|
|
524
|
-
await s3DataSource.uploadFile(
|
|
525
|
-
`inventory/date=${timestamp}/inventory.parquet`,
|
|
526
|
-
parquetBuffer,
|
|
527
|
-
{ contentType: 'application/octet-stream' }
|
|
528
|
-
);
|
|
529
|
-
|
|
530
|
-
// 4. Trigger data warehouse ingestion (e.g., Snowflake, Redshift)
|
|
531
|
-
await triggerWarehouseIngestion(timestamp);
|
|
532
|
-
|
|
533
|
-
console.log('✅ Daily extract complete!');
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
async function triggerWarehouseIngestion(date: string) {
|
|
537
|
-
// Trigger Snowflake/Redshift/BigQuery ingestion
|
|
538
|
-
console.log(`Triggering warehouse ingestion for ${date}`);
|
|
539
|
-
}
|
|
540
|
-
```
|
|
541
|
-
|
|
542
|
-
## Error Handling
|
|
543
|
-
|
|
544
|
-
```typescript
|
|
545
|
-
async function robustParquetParsing(parquetBuffer: ArrayBuffer) {
|
|
546
|
-
const logger = createConsoleLogger();
|
|
547
|
-
const parquetParser = new ParquetParserService(logger);
|
|
548
|
-
|
|
549
|
-
try {
|
|
550
|
-
// Validate first
|
|
551
|
-
const validation = await parquetParser.validateFile(parquetBuffer, 'file.parquet');
|
|
552
|
-
|
|
553
|
-
if (!validation.isValid) {
|
|
554
|
-
throw new Error(`Validation failed: ${validation.errors.map(e => e.message).join(', ')}`);
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
// Parse
|
|
558
|
-
const records = await parquetParser.parseSimple(parquetBuffer, 'file.parquet');
|
|
559
|
-
return records;
|
|
560
|
-
|
|
561
|
-
} catch (error) {
|
|
562
|
-
if (error.message.includes('Invalid Parquet file')) {
|
|
563
|
-
console.error('File is not a valid Parquet file');
|
|
564
|
-
} else if (error.message.includes('Corrupted')) {
|
|
565
|
-
console.error('Parquet file is corrupted');
|
|
566
|
-
} else {
|
|
567
|
-
console.error('Unexpected error:', error);
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
throw error;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
```
|
|
574
|
-
|
|
575
|
-
## Key Takeaways
|
|
576
|
-
|
|
577
|
-
- 🎯 Parquet is columnar format optimized for analytics
|
|
578
|
-
- 🎯 Use for large-scale data extraction (1M+ records)
|
|
579
|
-
- 🎯 Provides 10:1 compression ratio vs CSV/JSON
|
|
580
|
-
- 🎯 Stream large files with `parseStreaming()` for memory efficiency
|
|
581
|
-
- 🎯 Integrates with S3 for data warehouse pipelines
|
|
582
|
-
- 🎯 Ideal for Fluent → Analytics warehouse workflows
|
|
583
|
-
- 🎯 Column statistics enable query optimization
|
|
584
|
-
|
|
585
|
-
## Practice Exercise
|
|
586
|
-
|
|
587
|
-
**Challenge:** Extract virtual positions from Fluent and save as Parquet:
|
|
588
|
-
|
|
589
|
-
**Requirements:**
|
|
590
|
-
1. Fetch all virtual positions with auto-pagination
|
|
591
|
-
2. Transform to flat structure (no nested objects)
|
|
592
|
-
3. Convert to Parquet format
|
|
593
|
-
4. Upload to S3 with date partition: `data/date=2025-01-15/positions.parquet`
|
|
594
|
-
|
|
595
|
-
**Solution:** See [Parquet Examples](../examples/parquet-parser-examples.ts)
|
|
596
|
-
|
|
597
|
-
## Next Steps
|
|
598
|
-
|
|
599
|
-
Continue to [Module 6: Integration Patterns →](./02-core-guides-parsers-06-integration-patterns.md) to learn how to combine parsers with other SDK services.
|
|
600
|
-
|
|
601
|
-
---
|
|
602
|
-
|
|
603
|
-
**Module 5 Complete!** ✅
|
|
1
|
+
# Module 5: Parquet Parser
|
|
2
|
+
|
|
3
|
+
**Level:** Advanced
|
|
4
|
+
**Estimated Time:** 20 minutes
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
This module covers the Parquet Parser (`ParquetParserService`), designed for efficient large-scale data extraction and analytics. You'll learn how to parse Parquet files, leverage columnar storage, handle compression, and integrate with S3 for data extraction workflows.
|
|
9
|
+
|
|
10
|
+
## Learning Objectives
|
|
11
|
+
|
|
12
|
+
By the end of this module, you will:
|
|
13
|
+
- ✅ Understand Parquet columnar format and its benefits
|
|
14
|
+
- ✅ Parse Parquet files into JavaScript objects
|
|
15
|
+
- ✅ Stream large Parquet files efficiently
|
|
16
|
+
- ✅ Leverage compression and columnar storage
|
|
17
|
+
- ✅ Extract Fluent data to Parquet for analytics
|
|
18
|
+
- ✅ Integrate with S3 extraction workflows
|
|
19
|
+
|
|
20
|
+
## What is Parquet?
|
|
21
|
+
|
|
22
|
+
**Apache Parquet** is a columnar storage format that:
|
|
23
|
+
- Stores data by column instead of by row
|
|
24
|
+
- Uses efficient compression algorithms
|
|
25
|
+
- Optimizes for analytical queries
|
|
26
|
+
- Reduces file size significantly (often 10:1 compression)
|
|
27
|
+
- Is the standard for big data and analytics
|
|
28
|
+
|
|
29
|
+
**Row-based vs Column-based storage:**
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
Row-based (CSV):
|
|
33
|
+
SKU001,100,WH-01
|
|
34
|
+
SKU002,50,WH-01
|
|
35
|
+
SKU003,75,WH-02
|
|
36
|
+
|
|
37
|
+
Column-based (Parquet):
|
|
38
|
+
Column[sku]: [SKU001, SKU002, SKU003]
|
|
39
|
+
Column[qty]: [100, 50, 75]
|
|
40
|
+
Column[location]: [WH-01, WH-01, WH-02]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Benefits:**
|
|
44
|
+
- ✅ Better compression (similar values in a column compress well)
|
|
45
|
+
- ✅ Faster column-specific queries
|
|
46
|
+
- ✅ Smaller file sizes
|
|
47
|
+
- ✅ Efficient for analytics
|
|
48
|
+
|
|
49
|
+
## Basic Parquet Parsing
|
|
50
|
+
|
|
51
|
+
### Simple Parsing
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { ParquetParserService, createConsoleLogger, toStructuredLogger } from '@fluentcommerce/fc-connect-sdk';
|
|
55
|
+
import * as fs from 'fs/promises';
|
|
56
|
+
|
|
57
|
+
// ParquetParserService requires a StructuredLogger (not a simple logger)
|
|
58
|
+
const consoleLogger = createConsoleLogger();
|
|
59
|
+
const logger = toStructuredLogger(consoleLogger, { service: 'ParquetParser' });
|
|
60
|
+
|
|
61
|
+
// CRITICAL: Constructor requires logger parameter (NOT optional)
|
|
62
|
+
const parquetParser = new ParquetParserService(logger);
|
|
63
|
+
|
|
64
|
+
// Read Parquet file
|
|
65
|
+
const fileBuffer = await fs.readFile('inventory.parquet');
|
|
66
|
+
|
|
67
|
+
// Convert to ArrayBuffer (parseSimple requires ArrayBuffer, not Buffer)
|
|
68
|
+
const arrayBuffer = fileBuffer.buffer.slice(
|
|
69
|
+
fileBuffer.byteOffset,
|
|
70
|
+
fileBuffer.byteOffset + fileBuffer.byteLength
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
// Parse Parquet (simple mode - easiest)
|
|
74
|
+
const records = await parquetParser.parseSimple(arrayBuffer, 'inventory.parquet');
|
|
75
|
+
|
|
76
|
+
console.log(`Parsed ${records.length} records`);
|
|
77
|
+
console.log('First record:', records[0]);
|
|
78
|
+
// { sku: 'SKU001', qty: 100, location: 'WH-01' }
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Type Safety with TypeScript
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
// Define your record structure
|
|
85
|
+
interface InventoryRecord {
|
|
86
|
+
sku: string;
|
|
87
|
+
qty: number;
|
|
88
|
+
location: string;
|
|
89
|
+
updatedAt: Date;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Parse with type assertion (simple mode)
|
|
93
|
+
const records = await parquetParser.parseSimple(arrayBuffer, 'inventory.parquet');
|
|
94
|
+
|
|
95
|
+
// Or use parse() for detailed stats
|
|
96
|
+
const result = await parquetParser.parse(arrayBuffer, 'inventory.parquet');
|
|
97
|
+
console.log(`Processed ${result.stats.totalRecords} records in ${result.stats.processingTimeMs}ms`);
|
|
98
|
+
|
|
99
|
+
// Full type safety
|
|
100
|
+
result.records.forEach(record => {
|
|
101
|
+
console.log(`${record.sku}: ${record.qty} at ${record.location}`);
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Streaming Large Files
|
|
106
|
+
|
|
107
|
+
For large Parquet files, use streaming to avoid memory issues:
|
|
108
|
+
|
|
109
|
+
### Basic Streaming
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { ParquetParserService, createConsoleLogger, toStructuredLogger } from '@fluentcommerce/fc-connect-sdk';
|
|
113
|
+
|
|
114
|
+
const consoleLogger = createConsoleLogger();
|
|
115
|
+
const logger = toStructuredLogger(consoleLogger, { service: 'ParquetParser' });
|
|
116
|
+
|
|
117
|
+
const parquetParser = new ParquetParserService(logger);
|
|
118
|
+
|
|
119
|
+
// Stream Parquet file
|
|
120
|
+
const fileBuffer = await fs.readFile('large-inventory.parquet');
|
|
121
|
+
|
|
122
|
+
// Convert to ArrayBuffer
|
|
123
|
+
const arrayBuffer = fileBuffer.buffer.slice(
|
|
124
|
+
fileBuffer.byteOffset,
|
|
125
|
+
fileBuffer.byteOffset + fileBuffer.byteLength
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// Process records in batches
|
|
129
|
+
const batchSize = 1000;
|
|
130
|
+
|
|
131
|
+
const streamingResult = await parquetParser.parseStreaming(
|
|
132
|
+
arrayBuffer,
|
|
133
|
+
'large-inventory.parquet',
|
|
134
|
+
{ batchSize }
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
for await (const batch of streamingResult.records) {
|
|
138
|
+
console.log(`Processing batch of ${batch.length} records`);
|
|
139
|
+
await processBatch(batch);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Get final stats
|
|
143
|
+
const stats = await streamingResult.stats;
|
|
144
|
+
console.log(`Processed ${stats.totalRecords} total records`);
|
|
145
|
+
|
|
146
|
+
async function processBatch(records: any[]) {
|
|
147
|
+
// Transform and process
|
|
148
|
+
console.log(`Batch processing ${records.length} records`);
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Streaming with Progress Tracking
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
async function streamWithProgress(parquetBuffer: ArrayBuffer) {
|
|
156
|
+
const logger = createConsoleLogger();
|
|
157
|
+
const parquetParser = new ParquetParserService(logger);
|
|
158
|
+
const startTime = Date.now();
|
|
159
|
+
let totalRecords = 0;
|
|
160
|
+
|
|
161
|
+
const streamingResult = await parquetParser.parseStreaming(
|
|
162
|
+
parquetBuffer,
|
|
163
|
+
'file.parquet',
|
|
164
|
+
{ batchSize: 1000 }
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
for await (const batch of streamingResult.records) {
|
|
168
|
+
totalRecords += batch.length;
|
|
169
|
+
|
|
170
|
+
// Process batch
|
|
171
|
+
await processBatch(batch);
|
|
172
|
+
|
|
173
|
+
// Report progress
|
|
174
|
+
const elapsed = (Date.now() - startTime) / 1000;
|
|
175
|
+
const rate = totalRecords / elapsed;
|
|
176
|
+
console.log(`Processed ${totalRecords} records (${rate.toFixed(2)} records/sec)`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const stats = await streamingResult.stats;
|
|
180
|
+
console.log(`Completed: ${stats.totalRecords} total records`);
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Parser Configuration
|
|
185
|
+
|
|
186
|
+
The Parquet parser supports various options:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
interface ParquetParsingOptions {
|
|
190
|
+
// Batch size for streaming (default: 1000)
|
|
191
|
+
batchSize?: number;
|
|
192
|
+
|
|
193
|
+
// Maximum file size in bytes (default: 100MB)
|
|
194
|
+
maxFileSize?: number;
|
|
195
|
+
|
|
196
|
+
// Enable streaming mode (default: true)
|
|
197
|
+
enableStreaming?: boolean;
|
|
198
|
+
|
|
199
|
+
// Validation options
|
|
200
|
+
validation?: {
|
|
201
|
+
enabled?: boolean;
|
|
202
|
+
requiredColumns?: string[];
|
|
203
|
+
columnTypes?: Record<string, ParquetDataType>;
|
|
204
|
+
allowAdditionalColumns?: boolean;
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Example Configuration
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
const options: ParquetParsingOptions = {
|
|
213
|
+
batchSize: 5000,
|
|
214
|
+
maxFileSize: 500 * 1024 * 1024, // 500MB
|
|
215
|
+
enableStreaming: true,
|
|
216
|
+
validation: {
|
|
217
|
+
enabled: true,
|
|
218
|
+
requiredColumns: ['sku', 'qty', 'location'],
|
|
219
|
+
columnTypes: {
|
|
220
|
+
sku: 'string',
|
|
221
|
+
qty: 'number',
|
|
222
|
+
location: 'string'
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const result = await parquetParser.parse(parquetBuffer, 'file.parquet', options);
|
|
228
|
+
const records = result.records;
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Data Extraction Workflow
|
|
232
|
+
|
|
233
|
+
The primary use case for Parquet is extracting large datasets from Fluent Commerce to S3.
|
|
234
|
+
|
|
235
|
+
### Complete Extraction Example
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
import {
|
|
239
|
+
createClient,
|
|
240
|
+
ParquetParserService,
|
|
241
|
+
S3DataSource,
|
|
242
|
+
createConsoleLogger
|
|
243
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
244
|
+
|
|
245
|
+
async function extractInventoryToParquet() {
|
|
246
|
+
// 1. Setup logger
|
|
247
|
+
const logger = createConsoleLogger();
|
|
248
|
+
|
|
249
|
+
// 2. Create client
|
|
250
|
+
const client = await createClient({
|
|
251
|
+
config: {
|
|
252
|
+
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
253
|
+
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
254
|
+
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
255
|
+
retailerId: process.env.FLUENT_RETAILER_ID!
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// 3. Fetch data from Fluent (with auto-pagination)
|
|
260
|
+
const result = await client.graphql({
|
|
261
|
+
query: `
|
|
262
|
+
query GetVirtualPositions($first: Int!, $after: String) {
|
|
263
|
+
virtualPositions(first: $first, after: $after) {
|
|
264
|
+
edges {
|
|
265
|
+
node {
|
|
266
|
+
id
|
|
267
|
+
productRef
|
|
268
|
+
quantity
|
|
269
|
+
groupRef
|
|
270
|
+
createdOn
|
|
271
|
+
updatedOn
|
|
272
|
+
}
|
|
273
|
+
cursor
|
|
274
|
+
}
|
|
275
|
+
pageInfo {
|
|
276
|
+
hasNextPage
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
`,
|
|
281
|
+
variables: { first: 1000 },
|
|
282
|
+
pagination: { maxPages: 100 }
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// 4. Transform to flat structure
|
|
286
|
+
const records = result.data.virtualPositions.edges.map(edge => ({
|
|
287
|
+
id: edge.node.id,
|
|
288
|
+
productRef: edge.node.productRef,
|
|
289
|
+
quantity: edge.node.quantity,
|
|
290
|
+
groupRef: edge.node.groupRef,
|
|
291
|
+
createdOn: edge.node.createdOn,
|
|
292
|
+
updatedOn: edge.node.updatedOn
|
|
293
|
+
}));
|
|
294
|
+
|
|
295
|
+
console.log(`Extracted ${records.length} virtual positions`);
|
|
296
|
+
|
|
297
|
+
// 5. Convert to Parquet (using parquetjs or hyparquet)
|
|
298
|
+
const parquetBuffer = await convertToParquet(records);
|
|
299
|
+
|
|
300
|
+
// 6. Upload to S3 using S3DataSource
|
|
301
|
+
const s3DataSource = new S3DataSource({
|
|
302
|
+
type: 'S3_PARQUET',
|
|
303
|
+
connectionId: 's3-parquet-extract',
|
|
304
|
+
name: 'S3 Parquet Extract',
|
|
305
|
+
s3Config: {
|
|
306
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
307
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
308
|
+
region: process.env.AWS_REGION!,
|
|
309
|
+
bucket: 'my-analytics-bucket'
|
|
310
|
+
}
|
|
311
|
+
}, logger);
|
|
312
|
+
|
|
313
|
+
await s3DataSource.uploadFile(
|
|
314
|
+
`extracts/virtual-positions-${new Date().toISOString()}.parquet`,
|
|
315
|
+
parquetBuffer,
|
|
316
|
+
{ contentType: 'application/octet-stream' }
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
console.log('✅ Extraction complete!');
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
async function convertToParquet(records: any[]): Promise<Buffer> {
|
|
323
|
+
// Use parquetjs or hyparquet to convert
|
|
324
|
+
// Implementation depends on your choice of Parquet library
|
|
325
|
+
const parquetWriter = /* ... */;
|
|
326
|
+
// Write records and return buffer
|
|
327
|
+
return buffer;
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Performance Metrics
|
|
332
|
+
|
|
333
|
+
Get performance statistics from parsing operations:
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
const logger = createConsoleLogger();
|
|
337
|
+
const parquetParser = new ParquetParserService(logger);
|
|
338
|
+
|
|
339
|
+
// Parse file
|
|
340
|
+
const result = await parquetParser.parse(parquetBuffer, 'file.parquet');
|
|
341
|
+
|
|
342
|
+
// Access parsing statistics
|
|
343
|
+
console.log('Parsing statistics:');
|
|
344
|
+
console.log(`Total records: ${result.stats.totalRecords}`);
|
|
345
|
+
console.log(`Processing time: ${result.stats.processingTimeMs}ms`);
|
|
346
|
+
console.log(`Peak memory usage: ${(result.stats.peakMemoryUsage / 1024 / 1024).toFixed(2)}MB`);
|
|
347
|
+
console.log(`Records per second: ${result.stats.recordsPerSecond}`);
|
|
348
|
+
console.log(`Batches processed: ${result.stats.batchesProcessed}`);
|
|
349
|
+
|
|
350
|
+
// Get overall performance metrics
|
|
351
|
+
const metrics = parquetParser.getPerformanceMetrics();
|
|
352
|
+
console.log('Overall metrics:', metrics);
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## Validation
|
|
356
|
+
|
|
357
|
+
Validate Parquet structure:
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
const logger = createConsoleLogger();
|
|
361
|
+
const parquetParser = new ParquetParserService(logger);
|
|
362
|
+
|
|
363
|
+
// Validate Parquet file
|
|
364
|
+
const validation = await parquetParser.validateFile(parquetBuffer, 'file.parquet');
|
|
365
|
+
|
|
366
|
+
if (validation.isValid) {
|
|
367
|
+
console.log('Parquet file is valid');
|
|
368
|
+
const records = await parquetParser.parseSimple(parquetBuffer, 'file.parquet');
|
|
369
|
+
} else {
|
|
370
|
+
console.error('Validation errors:', validation.errors);
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Integration with S3
|
|
375
|
+
|
|
376
|
+
### Read Parquet from S3
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
import { S3DataSource, ParquetParserService, createConsoleLogger } from '@fluentcommerce/fc-connect-sdk';
|
|
380
|
+
|
|
381
|
+
async function readParquetFromS3() {
|
|
382
|
+
const logger = createConsoleLogger();
|
|
383
|
+
|
|
384
|
+
// Initialize S3 data source
|
|
385
|
+
const s3DataSource = new S3DataSource({
|
|
386
|
+
type: 'S3_PARQUET',
|
|
387
|
+
connectionId: 's3-parquet-read',
|
|
388
|
+
name: 'S3 Parquet Read',
|
|
389
|
+
s3Config: {
|
|
390
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
391
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
392
|
+
region: process.env.AWS_REGION!,
|
|
393
|
+
bucket: 'my-data-bucket'
|
|
394
|
+
}
|
|
395
|
+
}, logger);
|
|
396
|
+
|
|
397
|
+
// Download Parquet file from S3
|
|
398
|
+
const parquetBuffer = await s3DataSource.downloadFile('extracts/inventory.parquet');
|
|
399
|
+
|
|
400
|
+
// Parse Parquet
|
|
401
|
+
const parquetParser = new ParquetParserService(logger);
|
|
402
|
+
const records = await parquetParser.parseSimple(parquetBuffer, 'inventory.parquet');
|
|
403
|
+
|
|
404
|
+
console.log(`Loaded ${records.length} records from S3`);
|
|
405
|
+
return records;
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Write Parquet to S3
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
async function writeParquetToS3(records: any[]) {
|
|
413
|
+
const logger = createConsoleLogger();
|
|
414
|
+
|
|
415
|
+
// Convert to Parquet
|
|
416
|
+
const parquetBuffer = await convertToParquet(records);
|
|
417
|
+
|
|
418
|
+
// Upload to S3 using S3DataSource
|
|
419
|
+
const s3DataSource = new S3DataSource({
|
|
420
|
+
type: 'S3_PARQUET',
|
|
421
|
+
connectionId: 's3-parquet-write',
|
|
422
|
+
name: 'S3 Parquet Write',
|
|
423
|
+
s3Config: {
|
|
424
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
425
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
426
|
+
region: process.env.AWS_REGION!,
|
|
427
|
+
bucket: 'my-analytics-bucket'
|
|
428
|
+
}
|
|
429
|
+
}, logger);
|
|
430
|
+
|
|
431
|
+
await s3DataSource.uploadFile(
|
|
432
|
+
`extracts/data-${Date.now()}.parquet`,
|
|
433
|
+
parquetBuffer,
|
|
434
|
+
{ contentType: 'application/octet-stream' }
|
|
435
|
+
);
|
|
436
|
+
|
|
437
|
+
console.log('✅ Parquet file uploaded to S3');
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Performance Optimization
|
|
442
|
+
|
|
443
|
+
### 1. Use Appropriate Batch Sizes
|
|
444
|
+
|
|
445
|
+
```typescript
|
|
446
|
+
// Small batches for memory-constrained environments
|
|
447
|
+
const smallBatch = await parquetParser.parseStreaming(parquetBuffer, {
|
|
448
|
+
batchSize: 500
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// Large batches for high-memory environments
|
|
452
|
+
const largeBatch = await parquetParser.parseStreaming(parquetBuffer, {
|
|
453
|
+
batchSize: 10000
|
|
454
|
+
});
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### 2. Leverage Compression
|
|
458
|
+
|
|
459
|
+
Parquet automatically compresses data, but you can optimize:
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
// When creating Parquet files, use optimal compression
|
|
463
|
+
const parquetOptions = {
|
|
464
|
+
compression: 'SNAPPY', // Fast compression/decompression
|
|
465
|
+
// or 'GZIP' for better compression ratio
|
|
466
|
+
};
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### 3. Column Pruning
|
|
470
|
+
|
|
471
|
+
Only read columns you need (when using advanced Parquet libraries):
|
|
472
|
+
|
|
473
|
+
```typescript
|
|
474
|
+
// Only read specific columns
|
|
475
|
+
const selectedColumns = await parquetParser.parse(parquetBuffer, {
|
|
476
|
+
columns: ['sku', 'qty'] // Only read these columns
|
|
477
|
+
});
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## Real-World Example: Analytics Pipeline
|
|
481
|
+
|
|
482
|
+
Complete pipeline for extracting Fluent data to analytics warehouse:
|
|
483
|
+
|
|
484
|
+
```typescript
|
|
485
|
+
import {
|
|
486
|
+
createClient,
|
|
487
|
+
ParquetParserService,
|
|
488
|
+
S3DataSource,
|
|
489
|
+
createConsoleLogger
|
|
490
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
491
|
+
|
|
492
|
+
async function dailyInventoryExtract() {
|
|
493
|
+
const logger = createConsoleLogger();
|
|
494
|
+
const client = await createClient({ config });
|
|
495
|
+
|
|
496
|
+
const s3DataSource = new S3DataSource({
|
|
497
|
+
type: 'S3_PARQUET',
|
|
498
|
+
connectionId: 's3-analytics',
|
|
499
|
+
name: 'S3 Analytics',
|
|
500
|
+
s3Config: {
|
|
501
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
502
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
503
|
+
region: process.env.AWS_REGION!,
|
|
504
|
+
bucket: 'analytics-warehouse'
|
|
505
|
+
}
|
|
506
|
+
}, logger);
|
|
507
|
+
|
|
508
|
+
// 1. Extract inventory from Fluent
|
|
509
|
+
const result = await client.graphql({
|
|
510
|
+
query: inventoryQuery,
|
|
511
|
+
variables: { first: 1000 },
|
|
512
|
+
pagination: { maxRecords: 1000000 }
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
const records = result.data.inventoryPositions.edges.map(e => e.node);
|
|
516
|
+
|
|
517
|
+
console.log(`Extracted ${records.length} inventory positions`);
|
|
518
|
+
|
|
519
|
+
// 2. Convert to Parquet
|
|
520
|
+
const parquetBuffer = await convertToParquet(records);
|
|
521
|
+
|
|
522
|
+
// 3. Upload to S3 analytics bucket
|
|
523
|
+
const timestamp = new Date().toISOString().split('T')[0];
|
|
524
|
+
await s3DataSource.uploadFile(
|
|
525
|
+
`inventory/date=${timestamp}/inventory.parquet`,
|
|
526
|
+
parquetBuffer,
|
|
527
|
+
{ contentType: 'application/octet-stream' }
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
// 4. Trigger data warehouse ingestion (e.g., Snowflake, Redshift)
|
|
531
|
+
await triggerWarehouseIngestion(timestamp);
|
|
532
|
+
|
|
533
|
+
console.log('✅ Daily extract complete!');
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
async function triggerWarehouseIngestion(date: string) {
|
|
537
|
+
// Trigger Snowflake/Redshift/BigQuery ingestion
|
|
538
|
+
console.log(`Triggering warehouse ingestion for ${date}`);
|
|
539
|
+
}
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
## Error Handling
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
async function robustParquetParsing(parquetBuffer: ArrayBuffer) {
|
|
546
|
+
const logger = createConsoleLogger();
|
|
547
|
+
const parquetParser = new ParquetParserService(logger);
|
|
548
|
+
|
|
549
|
+
try {
|
|
550
|
+
// Validate first
|
|
551
|
+
const validation = await parquetParser.validateFile(parquetBuffer, 'file.parquet');
|
|
552
|
+
|
|
553
|
+
if (!validation.isValid) {
|
|
554
|
+
throw new Error(`Validation failed: ${validation.errors.map(e => e.message).join(', ')}`);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Parse
|
|
558
|
+
const records = await parquetParser.parseSimple(parquetBuffer, 'file.parquet');
|
|
559
|
+
return records;
|
|
560
|
+
|
|
561
|
+
} catch (error) {
|
|
562
|
+
if (error.message.includes('Invalid Parquet file')) {
|
|
563
|
+
console.error('File is not a valid Parquet file');
|
|
564
|
+
} else if (error.message.includes('Corrupted')) {
|
|
565
|
+
console.error('Parquet file is corrupted');
|
|
566
|
+
} else {
|
|
567
|
+
console.error('Unexpected error:', error);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
throw error;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
## Key Takeaways
|
|
576
|
+
|
|
577
|
+
- 🎯 Parquet is columnar format optimized for analytics
|
|
578
|
+
- 🎯 Use for large-scale data extraction (1M+ records)
|
|
579
|
+
- 🎯 Provides 10:1 compression ratio vs CSV/JSON
|
|
580
|
+
- 🎯 Stream large files with `parseStreaming()` for memory efficiency
|
|
581
|
+
- 🎯 Integrates with S3 for data warehouse pipelines
|
|
582
|
+
- 🎯 Ideal for Fluent → Analytics warehouse workflows
|
|
583
|
+
- 🎯 Column statistics enable query optimization
|
|
584
|
+
|
|
585
|
+
## Practice Exercise
|
|
586
|
+
|
|
587
|
+
**Challenge:** Extract virtual positions from Fluent and save as Parquet:
|
|
588
|
+
|
|
589
|
+
**Requirements:**
|
|
590
|
+
1. Fetch all virtual positions with auto-pagination
|
|
591
|
+
2. Transform to flat structure (no nested objects)
|
|
592
|
+
3. Convert to Parquet format
|
|
593
|
+
4. Upload to S3 with date partition: `data/date=2025-01-15/positions.parquet`
|
|
594
|
+
|
|
595
|
+
**Solution:** See [Parquet Examples](../examples/parquet-parser-examples.ts)
|
|
596
|
+
|
|
597
|
+
## Next Steps
|
|
598
|
+
|
|
599
|
+
Continue to [Module 6: Integration Patterns →](./02-core-guides-parsers-06-integration-patterns.md) to learn how to combine parsers with other SDK services.
|
|
600
|
+
|
|
601
|
+
---
|
|
602
|
+
|
|
603
|
+
**Module 5 Complete!** ✅
|