@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-04-writing-parquet.md
CHANGED
|
@@ -1,554 +1,554 @@
|
|
|
1
|
-
# Module 4: Writing Parquet Files
|
|
2
|
-
|
|
3
|
-
[← Back to Parquet Guide](../parquet-readme.md)
|
|
4
|
-
|
|
5
|
-
**Module 4 of 8** | **Level**: Intermediate | **Time**: 20 minutes
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Overview
|
|
10
|
-
|
|
11
|
-
Learn how to write Parquet files using external libraries. The SDK focuses on **reading** Parquet files, but this module shows integration patterns for **writing** using `parquetjs`.
|
|
12
|
-
|
|
13
|
-
## Learning Objectives
|
|
14
|
-
|
|
15
|
-
By the end of this module, you will:
|
|
16
|
-
|
|
17
|
-
- ✅ Understand why SDK doesn't include writing (and what to use instead)
|
|
18
|
-
- ✅ Write Parquet files using `parquetjs` library
|
|
19
|
-
- ✅ Define schemas and compression options
|
|
20
|
-
- ✅ Integrate writing with SDK extraction workflows
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## SDK Writing Support
|
|
25
|
-
|
|
26
|
-
⚠️ **IMPORTANT**: The FC Connect SDK **ParquetParserService focuses on reading**, not writing.
|
|
27
|
-
|
|
28
|
-
**Why?**
|
|
29
|
-
|
|
30
|
-
- Reading is the primary use case for integrations (parse incoming files)
|
|
31
|
-
- Writing libraries (`parquetjs`) are mature and well-maintained
|
|
32
|
-
- Keeps SDK focused and lightweight
|
|
33
|
-
|
|
34
|
-
**For Writing**: Use `parquetjs` library alongside the SDK.
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## Writing with parquetjs
|
|
39
|
-
|
|
40
|
-
### Installation
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
npm install parquetjs
|
|
44
|
-
npm install @types/parquetjs --save-dev # TypeScript types
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### Basic Writing Example
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
import * as parquet from 'parquetjs';
|
|
51
|
-
|
|
52
|
-
// Define schema
|
|
53
|
-
const schema = new parquet.ParquetSchema({
|
|
54
|
-
ref: { type: 'UTF8', optional: false },
|
|
55
|
-
productRef: { type: 'UTF8', optional: false },
|
|
56
|
-
locationRef: { type: 'UTF8', optional: false },
|
|
57
|
-
qty: { type: 'INT32', optional: false },
|
|
58
|
-
status: { type: 'UTF8', optional: true },
|
|
59
|
-
updatedOn: { type: 'TIMESTAMP_MILLIS', optional: true },
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// Create writer
|
|
63
|
-
const writer = await parquet.ParquetWriter.openFile(schema, 'inventory.parquet', {
|
|
64
|
-
compression: 'SNAPPY', // Fast compression
|
|
65
|
-
rowGroupSize: 10000, // Records per row group
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// Write records
|
|
69
|
-
const records = [
|
|
70
|
-
{
|
|
71
|
-
ref: 'IP-001',
|
|
72
|
-
productRef: 'SKU-001',
|
|
73
|
-
locationRef: 'WH-001',
|
|
74
|
-
qty: 100,
|
|
75
|
-
status: 'AVAILABLE',
|
|
76
|
-
updatedOn: new Date(),
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
ref: 'IP-002',
|
|
80
|
-
productRef: 'SKU-002',
|
|
81
|
-
locationRef: 'WH-001',
|
|
82
|
-
qty: 50,
|
|
83
|
-
status: 'RESERVED',
|
|
84
|
-
updatedOn: new Date(),
|
|
85
|
-
},
|
|
86
|
-
];
|
|
87
|
-
|
|
88
|
-
for (const record of records) {
|
|
89
|
-
await writer.appendRow(record);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Close writer
|
|
93
|
-
await writer.close();
|
|
94
|
-
|
|
95
|
-
console.log('✅ Parquet file written successfully');
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
## Schema Definition
|
|
101
|
-
|
|
102
|
-
### Supported Data Types
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
const schema = new parquet.ParquetSchema({
|
|
106
|
-
// Strings
|
|
107
|
-
stringField: { type: 'UTF8' },
|
|
108
|
-
|
|
109
|
-
// Integers
|
|
110
|
-
int32Field: { type: 'INT32' },
|
|
111
|
-
int64Field: { type: 'INT64' },
|
|
112
|
-
|
|
113
|
-
// Floating point
|
|
114
|
-
floatField: { type: 'FLOAT' },
|
|
115
|
-
doubleField: { type: 'DOUBLE' },
|
|
116
|
-
|
|
117
|
-
// Boolean
|
|
118
|
-
boolField: { type: 'BOOLEAN' },
|
|
119
|
-
|
|
120
|
-
// Dates/Times
|
|
121
|
-
dateField: { type: 'DATE' },
|
|
122
|
-
timestampField: { type: 'TIMESTAMP_MILLIS' },
|
|
123
|
-
|
|
124
|
-
// Optional fields
|
|
125
|
-
optionalField: { type: 'UTF8', optional: true },
|
|
126
|
-
|
|
127
|
-
// Arrays (repeated fields)
|
|
128
|
-
arrayField: {
|
|
129
|
-
type: 'UTF8',
|
|
130
|
-
repeated: true,
|
|
131
|
-
},
|
|
132
|
-
|
|
133
|
-
// Nested structures
|
|
134
|
-
nestedField: {
|
|
135
|
-
fields: {
|
|
136
|
-
subField1: { type: 'UTF8' },
|
|
137
|
-
subField2: { type: 'INT32' },
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
});
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Inventory Position Schema
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
const inventorySchema = new parquet.ParquetSchema({
|
|
147
|
-
ref: { type: 'UTF8', optional: false },
|
|
148
|
-
productRef: { type: 'UTF8', optional: false },
|
|
149
|
-
locationRef: { type: 'UTF8', optional: false },
|
|
150
|
-
qty: { type: 'INT32', optional: false },
|
|
151
|
-
status: { type: 'UTF8', optional: true },
|
|
152
|
-
type: { type: 'UTF8', optional: true },
|
|
153
|
-
createdOn: { type: 'TIMESTAMP_MILLIS', optional: true },
|
|
154
|
-
updatedOn: { type: 'TIMESTAMP_MILLIS', optional: true },
|
|
155
|
-
});
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
## Compression Options
|
|
161
|
-
|
|
162
|
-
### Available Compression Algorithms
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
// UNCOMPRESSED - No compression (fastest write, largest size)
|
|
166
|
-
const writer1 = await parquet.ParquetWriter.openFile(schema, 'file.parquet', {
|
|
167
|
-
compression: 'UNCOMPRESSED',
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
// SNAPPY - Fast compression (recommended for most cases)
|
|
171
|
-
const writer2 = await parquet.ParquetWriter.openFile(schema, 'file.parquet', {
|
|
172
|
-
compression: 'SNAPPY', // Default, good balance
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
// GZIP - Better compression ratio (slower)
|
|
176
|
-
const writer3 = await parquet.ParquetWriter.openFile(schema, 'file.parquet', {
|
|
177
|
-
compression: 'GZIP',
|
|
178
|
-
compressionLevel: 6, // 1-9, higher = better compression, slower
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
// BROTLI - Best compression (slowest)
|
|
182
|
-
const writer4 = await parquet.ParquetWriter.openFile(schema, 'file.parquet', {
|
|
183
|
-
compression: 'BROTLI',
|
|
184
|
-
compressionLevel: 4, // 1-11
|
|
185
|
-
});
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
### Compression Comparison
|
|
189
|
-
|
|
190
|
-
| Algorithm | Compression Ratio | Write Speed | Read Speed | Use When |
|
|
191
|
-
| ---------------- | ----------------- | ----------- | ---------- | ----------------------------- |
|
|
192
|
-
| **UNCOMPRESSED** | 1x | Fastest | Fastest | Local testing only |
|
|
193
|
-
| **SNAPPY** | 2-3x | Very Fast | Very Fast | General purpose (recommended) |
|
|
194
|
-
| **GZIP** | 3-4x | Moderate | Fast | Storage optimization |
|
|
195
|
-
| **BROTLI** | 4-5x | Slow | Fast | Maximum compression needed |
|
|
196
|
-
|
|
197
|
-
**Recommendation**: Use **SNAPPY** for most cases - excellent balance of speed and compression.
|
|
198
|
-
|
|
199
|
-
---
|
|
200
|
-
|
|
201
|
-
## Integration with SDK Extraction
|
|
202
|
-
|
|
203
|
-
### Pattern: GraphQL → Transform → Parquet
|
|
204
|
-
|
|
205
|
-
```typescript
|
|
206
|
-
import { createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
207
|
-
import * as parquet from 'parquetjs';
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Extract inventory from Fluent Commerce and save as Parquet
|
|
211
|
-
* Business use case: Daily inventory snapshot for analytics
|
|
212
|
-
*/
|
|
213
|
-
async function extractToParquet(outputFile: string) {
|
|
214
|
-
// 1. Setup SDK client
|
|
215
|
-
const client = await createClient({
|
|
216
|
-
config: {
|
|
217
|
-
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
218
|
-
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
219
|
-
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
220
|
-
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
221
|
-
},
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
// 2. Define Parquet schema
|
|
225
|
-
const schema = new parquet.ParquetSchema({
|
|
226
|
-
ref: { type: 'UTF8' },
|
|
227
|
-
productRef: { type: 'UTF8' },
|
|
228
|
-
locationRef: { type: 'UTF8' },
|
|
229
|
-
qty: { type: 'INT32' },
|
|
230
|
-
status: { type: 'UTF8', optional: true },
|
|
231
|
-
extractedAt: { type: 'TIMESTAMP_MILLIS' },
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
// 3. Create Parquet writer
|
|
235
|
-
const writer = await parquet.ParquetWriter.openFile(schema, outputFile, {
|
|
236
|
-
compression: 'SNAPPY',
|
|
237
|
-
rowGroupSize: 10000,
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
// 4. Extract data with pagination
|
|
241
|
-
let hasNextPage = true;
|
|
242
|
-
let cursor: string | null = null;
|
|
243
|
-
let totalRecords = 0;
|
|
244
|
-
|
|
245
|
-
while (hasNextPage) {
|
|
246
|
-
const result = await client.graphql({
|
|
247
|
-
query: `
|
|
248
|
-
query ExtractInventory($after: String, $first: Int!) {
|
|
249
|
-
inventoryPositions(after: $after, first: $first) {
|
|
250
|
-
# ✅ Query.inventoryPositions (InventoryPositionConnection!)
|
|
251
|
-
pageInfo {
|
|
252
|
-
hasNextPage
|
|
253
|
-
}
|
|
254
|
-
edges {
|
|
255
|
-
cursor
|
|
256
|
-
node {
|
|
257
|
-
ref # ✅ InventoryPosition.ref (String!)
|
|
258
|
-
productRef # ✅ InventoryPosition.productRef (String!)
|
|
259
|
-
locationRef # ✅ InventoryPosition.locationRef (String!)
|
|
260
|
-
qty # ✅ InventoryPosition.qty (Int!)
|
|
261
|
-
status # ✅ InventoryPosition.status (String)
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
`,
|
|
267
|
-
variables: {
|
|
268
|
-
first: 1000,
|
|
269
|
-
after: cursor,
|
|
270
|
-
},
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
const { edges, pageInfo } = result.data.inventoryPositions;
|
|
274
|
-
|
|
275
|
-
// 5. Write batch to Parquet
|
|
276
|
-
for (const edge of edges) {
|
|
277
|
-
await writer.appendRow({
|
|
278
|
-
...edge.node,
|
|
279
|
-
extractedAt: new Date(),
|
|
280
|
-
});
|
|
281
|
-
totalRecords++;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
console.log(`Written ${totalRecords} records...`);
|
|
285
|
-
|
|
286
|
-
hasNextPage = pageInfo.hasNextPage;
|
|
287
|
-
// ⚠️ Use last edge cursor (Fluent doesn't return pageInfo.endCursor)
|
|
288
|
-
cursor = edges.length > 0 ? edges[edges.length - 1].cursor : null;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// 6. Close writer
|
|
292
|
-
await writer.close();
|
|
293
|
-
|
|
294
|
-
console.log(`✅ Complete: ${totalRecords} records written to ${outputFile}`);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Usage
|
|
298
|
-
extractToParquet('inventory_2025-10-19.parquet').catch(console.error);
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
---
|
|
302
|
-
|
|
303
|
-
## Batch Writing for Performance
|
|
304
|
-
|
|
305
|
-
### Writing Large Datasets
|
|
306
|
-
|
|
307
|
-
```typescript
|
|
308
|
-
async function writeLargeDataset(records: any[], outputFile: string, batchSize: number = 10000) {
|
|
309
|
-
const schema = new parquet.ParquetSchema({
|
|
310
|
-
ref: { type: 'UTF8' },
|
|
311
|
-
productRef: { type: 'UTF8' },
|
|
312
|
-
locationRef: { type: 'UTF8' },
|
|
313
|
-
qty: { type: 'INT32' },
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
const writer = await parquet.ParquetWriter.openFile(schema, outputFile, {
|
|
317
|
-
compression: 'SNAPPY',
|
|
318
|
-
rowGroupSize: batchSize, // Optimize row group size
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
let written = 0;
|
|
322
|
-
|
|
323
|
-
for (let i = 0; i < records.length; i += batchSize) {
|
|
324
|
-
const batch = records.slice(i, i + batchSize);
|
|
325
|
-
|
|
326
|
-
for (const record of batch) {
|
|
327
|
-
await writer.appendRow(record);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
written += batch.length;
|
|
331
|
-
console.log(`Written ${written} / ${records.length} records`);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
await writer.close();
|
|
335
|
-
console.log(`✅ Complete: ${written} records`);
|
|
336
|
-
}
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
---
|
|
340
|
-
|
|
341
|
-
## S3DataSource.writeParquetContent()
|
|
342
|
-
|
|
343
|
-
The SDK provides a convenience method to generate Parquet files as Buffers, which can then be uploaded to S3.
|
|
344
|
-
|
|
345
|
-
### Method Signature
|
|
346
|
-
|
|
347
|
-
```typescript
|
|
348
|
-
async writeParquetContent(
|
|
349
|
-
records: ParquetDataRecord[],
|
|
350
|
-
options?: {
|
|
351
|
-
compression?: 'UNCOMPRESSED' | 'GZIP' | 'SNAPPY' | 'LZO' | 'BROTLI';
|
|
352
|
-
schema?: Record<string, any>;
|
|
353
|
-
rowGroupSize?: number;
|
|
354
|
-
}
|
|
355
|
-
): Promise<Buffer>
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
### Basic Usage
|
|
359
|
-
|
|
360
|
-
```typescript
|
|
361
|
-
import { S3DataSource, createConsoleLogger, toStructuredLogger } from '@fluentcommerce/fc-connect-sdk';
|
|
362
|
-
|
|
363
|
-
const logger = toStructuredLogger(createConsoleLogger(), { service: 'S3Parquet' });
|
|
364
|
-
|
|
365
|
-
const s3 = new S3DataSource(
|
|
366
|
-
{
|
|
367
|
-
type: 'S3_CSV',
|
|
368
|
-
s3Config: {
|
|
369
|
-
bucket: process.env.S3_BUCKET!,
|
|
370
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
371
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
372
|
-
region: process.env.AWS_REGION!,
|
|
373
|
-
},
|
|
374
|
-
},
|
|
375
|
-
logger
|
|
376
|
-
);
|
|
377
|
-
|
|
378
|
-
const records = [
|
|
379
|
-
{ id: 1, name: 'Product A', qty: 100 },
|
|
380
|
-
{ id: 2, name: 'Product B', qty: 200 },
|
|
381
|
-
];
|
|
382
|
-
|
|
383
|
-
// Generate Parquet Buffer
|
|
384
|
-
const parquetBuffer = await s3.writeParquetContent(records, {
|
|
385
|
-
schema: {
|
|
386
|
-
id: { type: 'INT32' },
|
|
387
|
-
name: { type: 'UTF8' },
|
|
388
|
-
qty: { type: 'INT32' },
|
|
389
|
-
},
|
|
390
|
-
compression: 'SNAPPY',
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
// Upload to S3
|
|
394
|
-
await s3.uploadFile('data/products-2025-10-30.parquet', parquetBuffer);
|
|
395
|
-
|
|
396
|
-
console.log('✅ Parquet file written to S3');
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
### Complete Extraction Example
|
|
400
|
-
|
|
401
|
-
```typescript
|
|
402
|
-
import { createClient, S3DataSource, createConsoleLogger, toStructuredLogger } from '@fluentcommerce/fc-connect-sdk';
|
|
403
|
-
|
|
404
|
-
async function extractToS3Parquet() {
|
|
405
|
-
const logger = toStructuredLogger(createConsoleLogger(), { service: 'Extraction' });
|
|
406
|
-
|
|
407
|
-
// 1. Create Fluent client
|
|
408
|
-
const client = await createClient({
|
|
409
|
-
config: {
|
|
410
|
-
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
411
|
-
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
412
|
-
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
413
|
-
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
414
|
-
},
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
// 2. Setup S3
|
|
418
|
-
const s3 = new S3DataSource(
|
|
419
|
-
{
|
|
420
|
-
type: 'S3_CSV',
|
|
421
|
-
s3Config: {
|
|
422
|
-
bucket: process.env.S3_BUCKET!,
|
|
423
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
424
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
425
|
-
region: process.env.AWS_REGION!,
|
|
426
|
-
},
|
|
427
|
-
},
|
|
428
|
-
logger
|
|
429
|
-
);
|
|
430
|
-
|
|
431
|
-
// 3. Extract data with pagination
|
|
432
|
-
const allRecords = [];
|
|
433
|
-
let hasNextPage = true;
|
|
434
|
-
let cursor: string | null = null;
|
|
435
|
-
|
|
436
|
-
while (hasNextPage) {
|
|
437
|
-
const result = await client.graphql({
|
|
438
|
-
query: `
|
|
439
|
-
query ExtractInventory($after: String, $first: Int!) {
|
|
440
|
-
inventoryPositions(after: $after, first: $first) {
|
|
441
|
-
pageInfo { hasNextPage }
|
|
442
|
-
edges {
|
|
443
|
-
cursor
|
|
444
|
-
node {
|
|
445
|
-
ref
|
|
446
|
-
productRef
|
|
447
|
-
locationRef
|
|
448
|
-
qty
|
|
449
|
-
status
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
`,
|
|
455
|
-
variables: { first: 1000, after: cursor },
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
const { edges, pageInfo } = result.data.inventoryPositions;
|
|
459
|
-
|
|
460
|
-
allRecords.push(...edges.map((e) => ({
|
|
461
|
-
...e.node,
|
|
462
|
-
extractedAt: new Date().toISOString(),
|
|
463
|
-
})));
|
|
464
|
-
|
|
465
|
-
hasNextPage = pageInfo.hasNextPage;
|
|
466
|
-
cursor = edges.length > 0 ? edges[edges.length - 1].cursor : null;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
console.log(`Extracted ${allRecords.length} records`);
|
|
470
|
-
|
|
471
|
-
// 4. Generate Parquet Buffer and upload to S3
|
|
472
|
-
const parquetBuffer = await s3.writeParquetContent(allRecords, {
|
|
473
|
-
schema: {
|
|
474
|
-
ref: { type: 'UTF8' },
|
|
475
|
-
productRef: { type: 'UTF8' },
|
|
476
|
-
locationRef: { type: 'UTF8' },
|
|
477
|
-
qty: { type: 'INT32' },
|
|
478
|
-
status: { type: 'UTF8' },
|
|
479
|
-
extractedAt: { type: 'UTF8' },
|
|
480
|
-
},
|
|
481
|
-
compression: 'SNAPPY',
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
const s3Key = `extracts/inventory_${new Date().toISOString().split('T')[0]}.parquet`;
|
|
485
|
-
await s3.uploadFile(s3Key, parquetBuffer);
|
|
486
|
-
|
|
487
|
-
console.log(`✅ Complete: Data written to S3 as Parquet at ${s3Key}`);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
extractToS3Parquet().catch(console.error);
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
### Advantages
|
|
494
|
-
|
|
495
|
-
- ✅ **No temporary files** - Generates Buffer directly in memory
|
|
496
|
-
- ✅ **Simplified workflow** - Generate Buffer, then upload
|
|
497
|
-
- ✅ **Memory efficient** - No disk I/O needed for generation
|
|
498
|
-
- ✅ **Flexible** - Upload to S3, SFTP, or save locally
|
|
499
|
-
|
|
500
|
-
### Parameters
|
|
501
|
-
|
|
502
|
-
**records** (`ParquetDataRecord[]`)
|
|
503
|
-
- Array of data objects to write
|
|
504
|
-
- Must match the provided schema structure
|
|
505
|
-
|
|
506
|
-
**options.schema** (`Record<string, any>` | optional)
|
|
507
|
-
- Parquet schema definition
|
|
508
|
-
- If not provided, schema is auto-detected from records
|
|
509
|
-
- Example: `{ id: { type: 'INT32' }, name: { type: 'UTF8' } }`
|
|
510
|
-
|
|
511
|
-
**options.compression** (`'UNCOMPRESSED' | 'GZIP' | 'SNAPPY' | 'LZO' | 'BROTLI'` | optional)
|
|
512
|
-
- Compression algorithm (default: `'UNCOMPRESSED'`)
|
|
513
|
-
- Recommended: `'SNAPPY'` for balance of speed and compression
|
|
514
|
-
|
|
515
|
-
**options.rowGroupSize** (`number` | optional)
|
|
516
|
-
- Number of rows per row group (default: 5000)
|
|
517
|
-
- Smaller = better for selective queries
|
|
518
|
-
- Larger = better for full scans
|
|
519
|
-
|
|
520
|
-
**Returns:** `Promise<Buffer>` - Parquet file content as Buffer
|
|
521
|
-
|
|
522
|
-
**Note:** After generating the Buffer, upload it separately:
|
|
523
|
-
```typescript
|
|
524
|
-
const buffer = await s3.writeParquetContent(records, options);
|
|
525
|
-
await s3.uploadFile('path/to/file.parquet', buffer);
|
|
526
|
-
```
|
|
527
|
-
|
|
528
|
-
---
|
|
529
|
-
|
|
530
|
-
## Key Takeaways
|
|
531
|
-
|
|
532
|
-
- 🎯 **SDK reads, parquetjs writes** - Use both together for complete workflows
|
|
533
|
-
- 🎯 **S3DataSource.writeParquetContent()** - Generates Parquet Buffer (then upload separately)
|
|
534
|
-
- 🎯 **No temporary files** - Generates Buffer directly in memory
|
|
535
|
-
- 🎯 **SNAPPY compression** - Best default choice for most use cases
|
|
536
|
-
- 🎯 **Schema optional** - Auto-detected if not provided
|
|
537
|
-
- 🎯 **Row groups** - Optimize size for query patterns (10K-50K typical)
|
|
538
|
-
- 🎯 **Integrate with SDK** - Extract from Fluent → Write to Parquet
|
|
539
|
-
|
|
540
|
-
---
|
|
541
|
-
|
|
542
|
-
## Next Steps
|
|
543
|
-
|
|
544
|
-
Continue to [Module 5: GraphQL Extraction](./03-pattern-guides-parquet-05-graphql-extraction.md/) to learn complete extraction workflows from Fluent Commerce to Parquet.
|
|
545
|
-
|
|
546
|
-
---
|
|
547
|
-
|
|
548
|
-
[← Previous: Module 3 - Reading Parquet](./03-pattern-guides-parquet-03-reading-parquet.md) | [Back to Guide](../parquet-readme.md) | [Next: Module 5 - GraphQL Extraction →](./03-pattern-guides-parquet-05-graphql-extraction.md/)
|
|
549
|
-
|
|
550
|
-
## Related Documentation
|
|
551
|
-
|
|
552
|
-
- [Module 5: GraphQL Extraction](./03-pattern-guides-parquet-05-graphql-extraction.md/) - Complete extraction workflows
|
|
553
|
-
- [Data Extraction Guide](../../extraction/) - GraphQL extraction patterns
|
|
554
|
-
- [parquetjs Documentation](https://github.com/ironSource/parquetjs) - Official library docs
|
|
1
|
+
# Module 4: Writing Parquet Files
|
|
2
|
+
|
|
3
|
+
[← Back to Parquet Guide](../parquet-readme.md)
|
|
4
|
+
|
|
5
|
+
**Module 4 of 8** | **Level**: Intermediate | **Time**: 20 minutes
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Learn how to write Parquet files using external libraries. The SDK focuses on **reading** Parquet files, but this module shows integration patterns for **writing** using `parquetjs`.
|
|
12
|
+
|
|
13
|
+
## Learning Objectives
|
|
14
|
+
|
|
15
|
+
By the end of this module, you will:
|
|
16
|
+
|
|
17
|
+
- ✅ Understand why SDK doesn't include writing (and what to use instead)
|
|
18
|
+
- ✅ Write Parquet files using `parquetjs` library
|
|
19
|
+
- ✅ Define schemas and compression options
|
|
20
|
+
- ✅ Integrate writing with SDK extraction workflows
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## SDK Writing Support
|
|
25
|
+
|
|
26
|
+
⚠️ **IMPORTANT**: The FC Connect SDK **ParquetParserService focuses on reading**, not writing.
|
|
27
|
+
|
|
28
|
+
**Why?**
|
|
29
|
+
|
|
30
|
+
- Reading is the primary use case for integrations (parse incoming files)
|
|
31
|
+
- Writing libraries (`parquetjs`) are mature and well-maintained
|
|
32
|
+
- Keeps SDK focused and lightweight
|
|
33
|
+
|
|
34
|
+
**For Writing**: Use `parquetjs` library alongside the SDK.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Writing with parquetjs
|
|
39
|
+
|
|
40
|
+
### Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install parquetjs
|
|
44
|
+
npm install @types/parquetjs --save-dev # TypeScript types
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Basic Writing Example
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import * as parquet from 'parquetjs';
|
|
51
|
+
|
|
52
|
+
// Define schema
|
|
53
|
+
const schema = new parquet.ParquetSchema({
|
|
54
|
+
ref: { type: 'UTF8', optional: false },
|
|
55
|
+
productRef: { type: 'UTF8', optional: false },
|
|
56
|
+
locationRef: { type: 'UTF8', optional: false },
|
|
57
|
+
qty: { type: 'INT32', optional: false },
|
|
58
|
+
status: { type: 'UTF8', optional: true },
|
|
59
|
+
updatedOn: { type: 'TIMESTAMP_MILLIS', optional: true },
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Create writer
|
|
63
|
+
const writer = await parquet.ParquetWriter.openFile(schema, 'inventory.parquet', {
|
|
64
|
+
compression: 'SNAPPY', // Fast compression
|
|
65
|
+
rowGroupSize: 10000, // Records per row group
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Write records
|
|
69
|
+
const records = [
|
|
70
|
+
{
|
|
71
|
+
ref: 'IP-001',
|
|
72
|
+
productRef: 'SKU-001',
|
|
73
|
+
locationRef: 'WH-001',
|
|
74
|
+
qty: 100,
|
|
75
|
+
status: 'AVAILABLE',
|
|
76
|
+
updatedOn: new Date(),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
ref: 'IP-002',
|
|
80
|
+
productRef: 'SKU-002',
|
|
81
|
+
locationRef: 'WH-001',
|
|
82
|
+
qty: 50,
|
|
83
|
+
status: 'RESERVED',
|
|
84
|
+
updatedOn: new Date(),
|
|
85
|
+
},
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
for (const record of records) {
|
|
89
|
+
await writer.appendRow(record);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Close writer
|
|
93
|
+
await writer.close();
|
|
94
|
+
|
|
95
|
+
console.log('✅ Parquet file written successfully');
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Schema Definition
|
|
101
|
+
|
|
102
|
+
### Supported Data Types
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
const schema = new parquet.ParquetSchema({
|
|
106
|
+
// Strings
|
|
107
|
+
stringField: { type: 'UTF8' },
|
|
108
|
+
|
|
109
|
+
// Integers
|
|
110
|
+
int32Field: { type: 'INT32' },
|
|
111
|
+
int64Field: { type: 'INT64' },
|
|
112
|
+
|
|
113
|
+
// Floating point
|
|
114
|
+
floatField: { type: 'FLOAT' },
|
|
115
|
+
doubleField: { type: 'DOUBLE' },
|
|
116
|
+
|
|
117
|
+
// Boolean
|
|
118
|
+
boolField: { type: 'BOOLEAN' },
|
|
119
|
+
|
|
120
|
+
// Dates/Times
|
|
121
|
+
dateField: { type: 'DATE' },
|
|
122
|
+
timestampField: { type: 'TIMESTAMP_MILLIS' },
|
|
123
|
+
|
|
124
|
+
// Optional fields
|
|
125
|
+
optionalField: { type: 'UTF8', optional: true },
|
|
126
|
+
|
|
127
|
+
// Arrays (repeated fields)
|
|
128
|
+
arrayField: {
|
|
129
|
+
type: 'UTF8',
|
|
130
|
+
repeated: true,
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
// Nested structures
|
|
134
|
+
nestedField: {
|
|
135
|
+
fields: {
|
|
136
|
+
subField1: { type: 'UTF8' },
|
|
137
|
+
subField2: { type: 'INT32' },
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Inventory Position Schema
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
const inventorySchema = new parquet.ParquetSchema({
|
|
147
|
+
ref: { type: 'UTF8', optional: false },
|
|
148
|
+
productRef: { type: 'UTF8', optional: false },
|
|
149
|
+
locationRef: { type: 'UTF8', optional: false },
|
|
150
|
+
qty: { type: 'INT32', optional: false },
|
|
151
|
+
status: { type: 'UTF8', optional: true },
|
|
152
|
+
type: { type: 'UTF8', optional: true },
|
|
153
|
+
createdOn: { type: 'TIMESTAMP_MILLIS', optional: true },
|
|
154
|
+
updatedOn: { type: 'TIMESTAMP_MILLIS', optional: true },
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Compression Options
|
|
161
|
+
|
|
162
|
+
### Available Compression Algorithms
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// UNCOMPRESSED - No compression (fastest write, largest size)
|
|
166
|
+
const writer1 = await parquet.ParquetWriter.openFile(schema, 'file.parquet', {
|
|
167
|
+
compression: 'UNCOMPRESSED',
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// SNAPPY - Fast compression (recommended for most cases)
|
|
171
|
+
const writer2 = await parquet.ParquetWriter.openFile(schema, 'file.parquet', {
|
|
172
|
+
compression: 'SNAPPY', // Default, good balance
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// GZIP - Better compression ratio (slower)
|
|
176
|
+
const writer3 = await parquet.ParquetWriter.openFile(schema, 'file.parquet', {
|
|
177
|
+
compression: 'GZIP',
|
|
178
|
+
compressionLevel: 6, // 1-9, higher = better compression, slower
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// BROTLI - Best compression (slowest)
|
|
182
|
+
const writer4 = await parquet.ParquetWriter.openFile(schema, 'file.parquet', {
|
|
183
|
+
compression: 'BROTLI',
|
|
184
|
+
compressionLevel: 4, // 1-11
|
|
185
|
+
});
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Compression Comparison
|
|
189
|
+
|
|
190
|
+
| Algorithm | Compression Ratio | Write Speed | Read Speed | Use When |
|
|
191
|
+
| ---------------- | ----------------- | ----------- | ---------- | ----------------------------- |
|
|
192
|
+
| **UNCOMPRESSED** | 1x | Fastest | Fastest | Local testing only |
|
|
193
|
+
| **SNAPPY** | 2-3x | Very Fast | Very Fast | General purpose (recommended) |
|
|
194
|
+
| **GZIP** | 3-4x | Moderate | Fast | Storage optimization |
|
|
195
|
+
| **BROTLI** | 4-5x | Slow | Fast | Maximum compression needed |
|
|
196
|
+
|
|
197
|
+
**Recommendation**: Use **SNAPPY** for most cases - excellent balance of speed and compression.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Integration with SDK Extraction
|
|
202
|
+
|
|
203
|
+
### Pattern: GraphQL → Transform → Parquet
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
import { createClient } from '@fluentcommerce/fc-connect-sdk';
|
|
207
|
+
import * as parquet from 'parquetjs';
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Extract inventory from Fluent Commerce and save as Parquet
|
|
211
|
+
* Business use case: Daily inventory snapshot for analytics
|
|
212
|
+
*/
|
|
213
|
+
async function extractToParquet(outputFile: string) {
|
|
214
|
+
// 1. Setup SDK client
|
|
215
|
+
const client = await createClient({
|
|
216
|
+
config: {
|
|
217
|
+
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
218
|
+
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
219
|
+
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
220
|
+
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// 2. Define Parquet schema
|
|
225
|
+
const schema = new parquet.ParquetSchema({
|
|
226
|
+
ref: { type: 'UTF8' },
|
|
227
|
+
productRef: { type: 'UTF8' },
|
|
228
|
+
locationRef: { type: 'UTF8' },
|
|
229
|
+
qty: { type: 'INT32' },
|
|
230
|
+
status: { type: 'UTF8', optional: true },
|
|
231
|
+
extractedAt: { type: 'TIMESTAMP_MILLIS' },
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// 3. Create Parquet writer
|
|
235
|
+
const writer = await parquet.ParquetWriter.openFile(schema, outputFile, {
|
|
236
|
+
compression: 'SNAPPY',
|
|
237
|
+
rowGroupSize: 10000,
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// 4. Extract data with pagination
|
|
241
|
+
let hasNextPage = true;
|
|
242
|
+
let cursor: string | null = null;
|
|
243
|
+
let totalRecords = 0;
|
|
244
|
+
|
|
245
|
+
while (hasNextPage) {
|
|
246
|
+
const result = await client.graphql({
|
|
247
|
+
query: `
|
|
248
|
+
query ExtractInventory($after: String, $first: Int!) {
|
|
249
|
+
inventoryPositions(after: $after, first: $first) {
|
|
250
|
+
# ✅ Query.inventoryPositions (InventoryPositionConnection!)
|
|
251
|
+
pageInfo {
|
|
252
|
+
hasNextPage
|
|
253
|
+
}
|
|
254
|
+
edges {
|
|
255
|
+
cursor
|
|
256
|
+
node {
|
|
257
|
+
ref # ✅ InventoryPosition.ref (String!)
|
|
258
|
+
productRef # ✅ InventoryPosition.productRef (String!)
|
|
259
|
+
locationRef # ✅ InventoryPosition.locationRef (String!)
|
|
260
|
+
qty # ✅ InventoryPosition.qty (Int!)
|
|
261
|
+
status # ✅ InventoryPosition.status (String)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
`,
|
|
267
|
+
variables: {
|
|
268
|
+
first: 1000,
|
|
269
|
+
after: cursor,
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
const { edges, pageInfo } = result.data.inventoryPositions;
|
|
274
|
+
|
|
275
|
+
// 5. Write batch to Parquet
|
|
276
|
+
for (const edge of edges) {
|
|
277
|
+
await writer.appendRow({
|
|
278
|
+
...edge.node,
|
|
279
|
+
extractedAt: new Date(),
|
|
280
|
+
});
|
|
281
|
+
totalRecords++;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
console.log(`Written ${totalRecords} records...`);
|
|
285
|
+
|
|
286
|
+
hasNextPage = pageInfo.hasNextPage;
|
|
287
|
+
// ⚠️ Use last edge cursor (Fluent doesn't return pageInfo.endCursor)
|
|
288
|
+
cursor = edges.length > 0 ? edges[edges.length - 1].cursor : null;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// 6. Close writer
|
|
292
|
+
await writer.close();
|
|
293
|
+
|
|
294
|
+
console.log(`✅ Complete: ${totalRecords} records written to ${outputFile}`);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Usage
|
|
298
|
+
extractToParquet('inventory_2025-10-19.parquet').catch(console.error);
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Batch Writing for Performance
|
|
304
|
+
|
|
305
|
+
### Writing Large Datasets
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
async function writeLargeDataset(records: any[], outputFile: string, batchSize: number = 10000) {
|
|
309
|
+
const schema = new parquet.ParquetSchema({
|
|
310
|
+
ref: { type: 'UTF8' },
|
|
311
|
+
productRef: { type: 'UTF8' },
|
|
312
|
+
locationRef: { type: 'UTF8' },
|
|
313
|
+
qty: { type: 'INT32' },
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
const writer = await parquet.ParquetWriter.openFile(schema, outputFile, {
|
|
317
|
+
compression: 'SNAPPY',
|
|
318
|
+
rowGroupSize: batchSize, // Optimize row group size
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
let written = 0;
|
|
322
|
+
|
|
323
|
+
for (let i = 0; i < records.length; i += batchSize) {
|
|
324
|
+
const batch = records.slice(i, i + batchSize);
|
|
325
|
+
|
|
326
|
+
for (const record of batch) {
|
|
327
|
+
await writer.appendRow(record);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
written += batch.length;
|
|
331
|
+
console.log(`Written ${written} / ${records.length} records`);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
await writer.close();
|
|
335
|
+
console.log(`✅ Complete: ${written} records`);
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## S3DataSource.writeParquetContent()
|
|
342
|
+
|
|
343
|
+
The SDK provides a convenience method to generate Parquet files as Buffers, which can then be uploaded to S3.
|
|
344
|
+
|
|
345
|
+
### Method Signature
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
async writeParquetContent(
|
|
349
|
+
records: ParquetDataRecord[],
|
|
350
|
+
options?: {
|
|
351
|
+
compression?: 'UNCOMPRESSED' | 'GZIP' | 'SNAPPY' | 'LZO' | 'BROTLI';
|
|
352
|
+
schema?: Record<string, any>;
|
|
353
|
+
rowGroupSize?: number;
|
|
354
|
+
}
|
|
355
|
+
): Promise<Buffer>
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Basic Usage
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
import { S3DataSource, createConsoleLogger, toStructuredLogger } from '@fluentcommerce/fc-connect-sdk';
|
|
362
|
+
|
|
363
|
+
const logger = toStructuredLogger(createConsoleLogger(), { service: 'S3Parquet' });
|
|
364
|
+
|
|
365
|
+
const s3 = new S3DataSource(
|
|
366
|
+
{
|
|
367
|
+
type: 'S3_CSV',
|
|
368
|
+
s3Config: {
|
|
369
|
+
bucket: process.env.S3_BUCKET!,
|
|
370
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
371
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
372
|
+
region: process.env.AWS_REGION!,
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
logger
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
const records = [
|
|
379
|
+
{ id: 1, name: 'Product A', qty: 100 },
|
|
380
|
+
{ id: 2, name: 'Product B', qty: 200 },
|
|
381
|
+
];
|
|
382
|
+
|
|
383
|
+
// Generate Parquet Buffer
|
|
384
|
+
const parquetBuffer = await s3.writeParquetContent(records, {
|
|
385
|
+
schema: {
|
|
386
|
+
id: { type: 'INT32' },
|
|
387
|
+
name: { type: 'UTF8' },
|
|
388
|
+
qty: { type: 'INT32' },
|
|
389
|
+
},
|
|
390
|
+
compression: 'SNAPPY',
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
// Upload to S3
|
|
394
|
+
await s3.uploadFile('data/products-2025-10-30.parquet', parquetBuffer);
|
|
395
|
+
|
|
396
|
+
console.log('✅ Parquet file written to S3');
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### Complete Extraction Example
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
import { createClient, S3DataSource, createConsoleLogger, toStructuredLogger } from '@fluentcommerce/fc-connect-sdk';
|
|
403
|
+
|
|
404
|
+
async function extractToS3Parquet() {
|
|
405
|
+
const logger = toStructuredLogger(createConsoleLogger(), { service: 'Extraction' });
|
|
406
|
+
|
|
407
|
+
// 1. Create Fluent client
|
|
408
|
+
const client = await createClient({
|
|
409
|
+
config: {
|
|
410
|
+
baseUrl: process.env.FLUENT_BASE_URL!,
|
|
411
|
+
clientId: process.env.FLUENT_CLIENT_ID!,
|
|
412
|
+
clientSecret: process.env.FLUENT_CLIENT_SECRET!,
|
|
413
|
+
retailerId: process.env.FLUENT_RETAILER_ID!,
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
// 2. Setup S3
|
|
418
|
+
const s3 = new S3DataSource(
|
|
419
|
+
{
|
|
420
|
+
type: 'S3_CSV',
|
|
421
|
+
s3Config: {
|
|
422
|
+
bucket: process.env.S3_BUCKET!,
|
|
423
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
424
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
425
|
+
region: process.env.AWS_REGION!,
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
logger
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
// 3. Extract data with pagination
|
|
432
|
+
const allRecords = [];
|
|
433
|
+
let hasNextPage = true;
|
|
434
|
+
let cursor: string | null = null;
|
|
435
|
+
|
|
436
|
+
while (hasNextPage) {
|
|
437
|
+
const result = await client.graphql({
|
|
438
|
+
query: `
|
|
439
|
+
query ExtractInventory($after: String, $first: Int!) {
|
|
440
|
+
inventoryPositions(after: $after, first: $first) {
|
|
441
|
+
pageInfo { hasNextPage }
|
|
442
|
+
edges {
|
|
443
|
+
cursor
|
|
444
|
+
node {
|
|
445
|
+
ref
|
|
446
|
+
productRef
|
|
447
|
+
locationRef
|
|
448
|
+
qty
|
|
449
|
+
status
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
`,
|
|
455
|
+
variables: { first: 1000, after: cursor },
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
const { edges, pageInfo } = result.data.inventoryPositions;
|
|
459
|
+
|
|
460
|
+
allRecords.push(...edges.map((e) => ({
|
|
461
|
+
...e.node,
|
|
462
|
+
extractedAt: new Date().toISOString(),
|
|
463
|
+
})));
|
|
464
|
+
|
|
465
|
+
hasNextPage = pageInfo.hasNextPage;
|
|
466
|
+
cursor = edges.length > 0 ? edges[edges.length - 1].cursor : null;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
console.log(`Extracted ${allRecords.length} records`);
|
|
470
|
+
|
|
471
|
+
// 4. Generate Parquet Buffer and upload to S3
|
|
472
|
+
const parquetBuffer = await s3.writeParquetContent(allRecords, {
|
|
473
|
+
schema: {
|
|
474
|
+
ref: { type: 'UTF8' },
|
|
475
|
+
productRef: { type: 'UTF8' },
|
|
476
|
+
locationRef: { type: 'UTF8' },
|
|
477
|
+
qty: { type: 'INT32' },
|
|
478
|
+
status: { type: 'UTF8' },
|
|
479
|
+
extractedAt: { type: 'UTF8' },
|
|
480
|
+
},
|
|
481
|
+
compression: 'SNAPPY',
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
const s3Key = `extracts/inventory_${new Date().toISOString().split('T')[0]}.parquet`;
|
|
485
|
+
await s3.uploadFile(s3Key, parquetBuffer);
|
|
486
|
+
|
|
487
|
+
console.log(`✅ Complete: Data written to S3 as Parquet at ${s3Key}`);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
extractToS3Parquet().catch(console.error);
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### Advantages
|
|
494
|
+
|
|
495
|
+
- ✅ **No temporary files** - Generates Buffer directly in memory
|
|
496
|
+
- ✅ **Simplified workflow** - Generate Buffer, then upload
|
|
497
|
+
- ✅ **Memory efficient** - No disk I/O needed for generation
|
|
498
|
+
- ✅ **Flexible** - Upload to S3, SFTP, or save locally
|
|
499
|
+
|
|
500
|
+
### Parameters
|
|
501
|
+
|
|
502
|
+
**records** (`ParquetDataRecord[]`)
|
|
503
|
+
- Array of data objects to write
|
|
504
|
+
- Must match the provided schema structure
|
|
505
|
+
|
|
506
|
+
**options.schema** (`Record<string, any>` | optional)
|
|
507
|
+
- Parquet schema definition
|
|
508
|
+
- If not provided, schema is auto-detected from records
|
|
509
|
+
- Example: `{ id: { type: 'INT32' }, name: { type: 'UTF8' } }`
|
|
510
|
+
|
|
511
|
+
**options.compression** (`'UNCOMPRESSED' | 'GZIP' | 'SNAPPY' | 'LZO' | 'BROTLI'` | optional)
|
|
512
|
+
- Compression algorithm (default: `'UNCOMPRESSED'`)
|
|
513
|
+
- Recommended: `'SNAPPY'` for balance of speed and compression
|
|
514
|
+
|
|
515
|
+
**options.rowGroupSize** (`number` | optional)
|
|
516
|
+
- Number of rows per row group (default: 5000)
|
|
517
|
+
- Smaller = better for selective queries
|
|
518
|
+
- Larger = better for full scans
|
|
519
|
+
|
|
520
|
+
**Returns:** `Promise<Buffer>` - Parquet file content as Buffer
|
|
521
|
+
|
|
522
|
+
**Note:** After generating the Buffer, upload it separately:
|
|
523
|
+
```typescript
|
|
524
|
+
const buffer = await s3.writeParquetContent(records, options);
|
|
525
|
+
await s3.uploadFile('path/to/file.parquet', buffer);
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
---
|
|
529
|
+
|
|
530
|
+
## Key Takeaways
|
|
531
|
+
|
|
532
|
+
- 🎯 **SDK reads, parquetjs writes** - Use both together for complete workflows
|
|
533
|
+
- 🎯 **S3DataSource.writeParquetContent()** - Generates Parquet Buffer (then upload separately)
|
|
534
|
+
- 🎯 **No temporary files** - Generates Buffer directly in memory
|
|
535
|
+
- 🎯 **SNAPPY compression** - Best default choice for most use cases
|
|
536
|
+
- 🎯 **Schema optional** - Auto-detected if not provided
|
|
537
|
+
- 🎯 **Row groups** - Optimize size for query patterns (10K-50K typical)
|
|
538
|
+
- 🎯 **Integrate with SDK** - Extract from Fluent → Write to Parquet
|
|
539
|
+
|
|
540
|
+
---
|
|
541
|
+
|
|
542
|
+
## Next Steps
|
|
543
|
+
|
|
544
|
+
Continue to [Module 5: GraphQL Extraction](./03-pattern-guides-parquet-05-graphql-extraction.md/) to learn complete extraction workflows from Fluent Commerce to Parquet.
|
|
545
|
+
|
|
546
|
+
---
|
|
547
|
+
|
|
548
|
+
[← Previous: Module 3 - Reading Parquet](./03-pattern-guides-parquet-03-reading-parquet.md) | [Back to Guide](../parquet-readme.md) | [Next: Module 5 - GraphQL Extraction →](./03-pattern-guides-parquet-05-graphql-extraction.md/)
|
|
549
|
+
|
|
550
|
+
## Related Documentation
|
|
551
|
+
|
|
552
|
+
- [Module 5: GraphQL Extraction](./03-pattern-guides-parquet-05-graphql-extraction.md/) - Complete extraction workflows
|
|
553
|
+
- [Data Extraction Guide](../../extraction/) - GraphQL extraction patterns
|
|
554
|
+
- [parquetjs Documentation](https://github.com/ironSource/parquetjs) - Official library docs
|