@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,724 +1,724 @@
|
|
|
1
|
-
# BatchArchivalService
|
|
2
|
-
|
|
3
|
-
**Level:** Advanced
|
|
4
|
-
**Category:** Compliance & Audit
|
|
5
|
-
**Purpose:** Archive batch payloads to S3 for audit trails and compliance
|
|
6
|
-
|
|
7
|
-
## Overview
|
|
8
|
-
|
|
9
|
-
`BatchArchivalService` provides automatic archival of batch payloads to S3 with hierarchical time-based paths. It creates audit trails for all batch operations, enabling compliance tracking, debugging, and historical analysis.
|
|
10
|
-
|
|
11
|
-
**Key Features:**
|
|
12
|
-
- Hierarchical time-based S3 paths (`YYYY/MM/DD/HH/MM`)
|
|
13
|
-
- Presigned URL uploads (no direct S3 SDK dependencies)
|
|
14
|
-
- Bulk archival with parallel uploads
|
|
15
|
-
- Automatic metadata enrichment
|
|
16
|
-
- Failed upload handling
|
|
17
|
-
|
|
18
|
-
## Use Cases
|
|
19
|
-
|
|
20
|
-
- ✅ Regulatory compliance (SOX, GDPR, HIPAA)
|
|
21
|
-
- ✅ Audit trail requirements
|
|
22
|
-
- ✅ Debug production batch failures
|
|
23
|
-
- ✅ Historical data analysis
|
|
24
|
-
- ✅ Replay failed batches
|
|
25
|
-
- ✅ Track data lineage
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## Installation
|
|
30
|
-
|
|
31
|
-
```typescript
|
|
32
|
-
import {
|
|
33
|
-
BatchArchivalService,
|
|
34
|
-
S3PresignService
|
|
35
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## Basic Usage
|
|
41
|
-
|
|
42
|
-
### Archive Single Batch
|
|
43
|
-
|
|
44
|
-
```typescript
|
|
45
|
-
import { BatchArchivalService, S3PresignService } from '@fluentcommerce/fc-connect-sdk';
|
|
46
|
-
|
|
47
|
-
// Configure archival service
|
|
48
|
-
const config = {
|
|
49
|
-
bucketName: 'my-batch-archives',
|
|
50
|
-
region: 'us-east-1',
|
|
51
|
-
credentials: {
|
|
52
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
53
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
54
|
-
},
|
|
55
|
-
basePath: 'fluent_batches', // Optional: defaults to 'fluent_batches'
|
|
56
|
-
expiresSeconds: 300 // Optional: presigned URL expiry (default: 300s)
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
// Initialize services
|
|
60
|
-
const s3Service = new S3PresignService();
|
|
61
|
-
const archivalService = new BatchArchivalService(config, s3Service, logger);
|
|
62
|
-
|
|
63
|
-
// Archive a batch
|
|
64
|
-
const result = await archivalService.archiveBatch(
|
|
65
|
-
{
|
|
66
|
-
batch: {
|
|
67
|
-
action: 'UPSERT',
|
|
68
|
-
entityType: 'INVENTORY',
|
|
69
|
-
entities: [{ skuRef: 'SKU001', qty: 100 }]
|
|
70
|
-
},
|
|
71
|
-
batchResponse: {
|
|
72
|
-
id: 'batch-123',
|
|
73
|
-
jobId: 'job-456',
|
|
74
|
-
status: 'COMPLETED'
|
|
75
|
-
},
|
|
76
|
-
jobId: 'job-456'
|
|
77
|
-
},
|
|
78
|
-
'client-abc' // Optional client ID for tracking
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
if (result.success) {
|
|
82
|
-
console.log('Archived to:', result.archivedPath);
|
|
83
|
-
// Output: fluent_batches/2025/01/30/14/30/batch-job-456-batch-123.json
|
|
84
|
-
} else {
|
|
85
|
-
console.error('Archival failed:', result.error);
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## API Reference
|
|
92
|
-
|
|
93
|
-
### Constructor
|
|
94
|
-
|
|
95
|
-
```typescript
|
|
96
|
-
new BatchArchivalService(
|
|
97
|
-
config: BatchArchivalConfig,
|
|
98
|
-
s3PresignService: S3PresignService,
|
|
99
|
-
logger?: Logger
|
|
100
|
-
)
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
**Parameters:**
|
|
104
|
-
- `config` - Archival configuration
|
|
105
|
-
- `bucketName` - S3 bucket name
|
|
106
|
-
- `region` - AWS region
|
|
107
|
-
- `credentials` - AWS credentials
|
|
108
|
-
- `basePath` - Optional base path (default: 'fluent_batches')
|
|
109
|
-
- `expiresSeconds` - Optional presigned URL TTL (default: 300)
|
|
110
|
-
- `s3PresignService` - S3 presign service instance
|
|
111
|
-
- `logger` - Optional structured logger
|
|
112
|
-
|
|
113
|
-
**Example:**
|
|
114
|
-
```typescript
|
|
115
|
-
const archivalService = new BatchArchivalService(
|
|
116
|
-
{
|
|
117
|
-
bucketName: 'production-archives',
|
|
118
|
-
region: 'us-west-2',
|
|
119
|
-
credentials: {
|
|
120
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
121
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
122
|
-
},
|
|
123
|
-
basePath: 'compliance/batches',
|
|
124
|
-
expiresSeconds: 600
|
|
125
|
-
},
|
|
126
|
-
s3PresignService,
|
|
127
|
-
logger
|
|
128
|
-
);
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
### archiveBatch()
|
|
134
|
-
|
|
135
|
-
Archive a single batch to S3.
|
|
136
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
await archivalService.archiveBatch(
|
|
139
|
-
batchItem: BatchToArchive,
|
|
140
|
-
clientId?: string
|
|
141
|
-
): Promise<ArchivalResult>
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
**Parameters:**
|
|
145
|
-
- `batchItem` - Batch data to archive
|
|
146
|
-
- `batch` - Original batch payload
|
|
147
|
-
- `batchResponse` - Response from Batch API
|
|
148
|
-
- `jobId` - Job identifier
|
|
149
|
-
- `clientId` - Optional client identifier for multi-tenant tracking
|
|
150
|
-
|
|
151
|
-
**Returns:** `ArchivalResult`
|
|
152
|
-
```typescript
|
|
153
|
-
{
|
|
154
|
-
success: boolean;
|
|
155
|
-
archivedPath?: string; // S3 key if successful
|
|
156
|
-
error?: string; // Error message if failed
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
**Example:**
|
|
161
|
-
```typescript
|
|
162
|
-
const result = await archivalService.archiveBatch(
|
|
163
|
-
{
|
|
164
|
-
batch: {
|
|
165
|
-
action: 'UPSERT',
|
|
166
|
-
entityType: 'INVENTORY',
|
|
167
|
-
catalogueRef: 'DEFAULT:1',
|
|
168
|
-
entities: inventoryRecords
|
|
169
|
-
},
|
|
170
|
-
batchResponse: {
|
|
171
|
-
id: batchResponse.id,
|
|
172
|
-
jobId: batchResponse.jobId,
|
|
173
|
-
status: batchResponse.status
|
|
174
|
-
},
|
|
175
|
-
jobId: 'inventory-sync-2025-01-30'
|
|
176
|
-
},
|
|
177
|
-
'tenant-123'
|
|
178
|
-
);
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
---
|
|
182
|
-
|
|
183
|
-
### archiveBatches()
|
|
184
|
-
|
|
185
|
-
Archive multiple batches in parallel.
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
await archivalService.archiveBatches(
|
|
189
|
-
batches: BatchToArchive[],
|
|
190
|
-
clientId?: string
|
|
191
|
-
): Promise<ArchivalResult[]>
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
**Parameters:**
|
|
195
|
-
- `batches` - Array of batches to archive
|
|
196
|
-
- `clientId` - Optional client identifier
|
|
197
|
-
|
|
198
|
-
**Returns:** Array of `ArchivalResult` (one per batch)
|
|
199
|
-
|
|
200
|
-
**Example:**
|
|
201
|
-
```typescript
|
|
202
|
-
const batches = [
|
|
203
|
-
{ batch: batch1, batchResponse: response1, jobId: 'job-1' },
|
|
204
|
-
{ batch: batch2, batchResponse: response2, jobId: 'job-2' },
|
|
205
|
-
{ batch: batch3, batchResponse: response3, jobId: 'job-3' }
|
|
206
|
-
];
|
|
207
|
-
|
|
208
|
-
const results = await archivalService.archiveBatches(batches, 'tenant-123');
|
|
209
|
-
|
|
210
|
-
const successCount = results.filter(r => r.success).length;
|
|
211
|
-
console.log(`Archived ${successCount} of ${results.length} batches`);
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
---
|
|
215
|
-
|
|
216
|
-
### generateArchivalPath()
|
|
217
|
-
|
|
218
|
-
Generate S3 path without uploading (useful for pre-computation).
|
|
219
|
-
|
|
220
|
-
```typescript
|
|
221
|
-
const path = archivalService.generateArchivalPath(
|
|
222
|
-
jobId: string,
|
|
223
|
-
batchId?: string,
|
|
224
|
-
timestamp?: Date
|
|
225
|
-
): string
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
**Parameters:**
|
|
229
|
-
- `jobId` - Job identifier
|
|
230
|
-
- `batchId` - Optional batch identifier
|
|
231
|
-
- `timestamp` - Optional timestamp (defaults to now)
|
|
232
|
-
|
|
233
|
-
**Returns:** S3 key string
|
|
234
|
-
|
|
235
|
-
**Example:**
|
|
236
|
-
```typescript
|
|
237
|
-
const path = archivalService.generateArchivalPath(
|
|
238
|
-
'inventory-sync-2025-01-30',
|
|
239
|
-
'batch-123',
|
|
240
|
-
new Date('2025-01-30T14:30:00Z')
|
|
241
|
-
);
|
|
242
|
-
|
|
243
|
-
console.log(path);
|
|
244
|
-
// Output: fluent_batches/2025/01/30/14/30/batch-inventory-sync-2025-01-30-batch-123.json
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
---
|
|
248
|
-
|
|
249
|
-
### listArchivalsByDate()
|
|
250
|
-
|
|
251
|
-
List all archived batches for a specific date.
|
|
252
|
-
|
|
253
|
-
```typescript
|
|
254
|
-
const keys = await archivalService.listArchivalsByDate(
|
|
255
|
-
date: Date
|
|
256
|
-
): Promise<string[]>
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
**Parameters:**
|
|
260
|
-
- `date` - Date to query
|
|
261
|
-
|
|
262
|
-
**Returns:** Array of S3 keys
|
|
263
|
-
|
|
264
|
-
**Example:**
|
|
265
|
-
```typescript
|
|
266
|
-
const today = new Date('2025-01-30');
|
|
267
|
-
const archivedBatches = await archivalService.listArchivalsByDate(today);
|
|
268
|
-
|
|
269
|
-
console.log(`Found ${archivedBatches.length} archived batches for today:`);
|
|
270
|
-
archivedBatches.forEach(key => console.log(` - ${key}`));
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
---
|
|
274
|
-
|
|
275
|
-
## S3 Path Structure
|
|
276
|
-
|
|
277
|
-
BatchArchivalService creates hierarchical paths for efficient querying:
|
|
278
|
-
|
|
279
|
-
```
|
|
280
|
-
{basePath}/{YYYY}/{MM}/{DD}/{HH}/{MM}/batch-{jobId}-{batchId}.json
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
**Example Paths:**
|
|
284
|
-
```
|
|
285
|
-
fluent_batches/2025/01/30/14/30/batch-inventory-sync-batch-123.json
|
|
286
|
-
fluent_batches/2025/01/30/14/31/batch-inventory-sync-batch-124.json
|
|
287
|
-
compliance/batches/2025/01/30/15/00/batch-order-sync-batch-456.json
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
**Benefits:**
|
|
291
|
-
- Easy date-based queries
|
|
292
|
-
- Efficient S3 lifecycle policies
|
|
293
|
-
- Time-series analysis
|
|
294
|
-
- Quick drill-down debugging
|
|
295
|
-
|
|
296
|
-
---
|
|
297
|
-
|
|
298
|
-
## Archived Payload Format
|
|
299
|
-
|
|
300
|
-
Each archived file contains:
|
|
301
|
-
|
|
302
|
-
```json
|
|
303
|
-
{
|
|
304
|
-
"action": "UPSERT",
|
|
305
|
-
"entityType": "INVENTORY",
|
|
306
|
-
"catalogueRef": "DEFAULT:1",
|
|
307
|
-
"entities": [
|
|
308
|
-
{ "skuRef": "SKU001", "qty": 100 },
|
|
309
|
-
{ "skuRef": "SKU002", "qty": 200 }
|
|
310
|
-
],
|
|
311
|
-
"clientId": "tenant-123",
|
|
312
|
-
"archivedAt": "2025-01-30T14:30:00.000Z",
|
|
313
|
-
"batchMetadata": {
|
|
314
|
-
"jobId": "inventory-sync-2025-01-30",
|
|
315
|
-
"batchId": "batch-123",
|
|
316
|
-
"status": "COMPLETED"
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
---
|
|
322
|
-
|
|
323
|
-
## Common Patterns
|
|
324
|
-
|
|
325
|
-
### Pattern 1: Archive After Successful Ingestion
|
|
326
|
-
|
|
327
|
-
```typescript
|
|
328
|
-
import {
|
|
329
|
-
FluentBatchManager,
|
|
330
|
-
BatchArchivalService,
|
|
331
|
-
S3PresignService
|
|
332
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
333
|
-
|
|
334
|
-
async function ingestWithArchival(records: any[]) {
|
|
335
|
-
const batchManager = new FluentBatchManager(client, logger);
|
|
336
|
-
const archivalService = new BatchArchivalService(archivalConfig, s3Service, logger);
|
|
337
|
-
|
|
338
|
-
const jobId = `inventory-sync-${Date.now()}`;
|
|
339
|
-
|
|
340
|
-
// Send batch
|
|
341
|
-
const batchResponse = await client.sendBatch(jobId, {
|
|
342
|
-
action: 'UPSERT',
|
|
343
|
-
entityType: 'INVENTORY',
|
|
344
|
-
entities: records
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
// Archive immediately after successful send
|
|
348
|
-
await archivalService.archiveBatch({
|
|
349
|
-
batch: {
|
|
350
|
-
action: 'UPSERT',
|
|
351
|
-
entityType: 'INVENTORY',
|
|
352
|
-
entities: records
|
|
353
|
-
},
|
|
354
|
-
batchResponse,
|
|
355
|
-
jobId
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
logger.info('Batch sent and archived', { jobId, batchId: batchResponse.id });
|
|
359
|
-
}
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
---
|
|
363
|
-
|
|
364
|
-
### Pattern 2: Archive All Batches (Bulk)
|
|
365
|
-
|
|
366
|
-
```typescript
|
|
367
|
-
async function bulkIngestWithArchival(
|
|
368
|
-
fileRecords: Record<string, any[]>
|
|
369
|
-
) {
|
|
370
|
-
const archivalService = new BatchArchivalService(config, s3Service, logger);
|
|
371
|
-
const batchesToArchive: BatchToArchive[] = [];
|
|
372
|
-
|
|
373
|
-
// Process all files
|
|
374
|
-
for (const [fileName, records] of Object.entries(fileRecords)) {
|
|
375
|
-
const jobId = `ingestion-${fileName}-${Date.now()}`;
|
|
376
|
-
|
|
377
|
-
// Send batch
|
|
378
|
-
const batchResponse = await client.sendBatch(jobId, {
|
|
379
|
-
action: 'UPSERT',
|
|
380
|
-
entityType: 'INVENTORY',
|
|
381
|
-
entities: records
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
// Queue for archival
|
|
385
|
-
batchesToArchive.push({
|
|
386
|
-
batch: {
|
|
387
|
-
action: 'UPSERT',
|
|
388
|
-
entityType: 'INVENTORY',
|
|
389
|
-
entities: records
|
|
390
|
-
},
|
|
391
|
-
batchResponse,
|
|
392
|
-
jobId
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// Archive all batches in parallel
|
|
397
|
-
const results = await archivalService.archiveBatches(
|
|
398
|
-
batchesToArchive,
|
|
399
|
-
'tenant-abc'
|
|
400
|
-
);
|
|
401
|
-
|
|
402
|
-
const successCount = results.filter(r => r.success).length;
|
|
403
|
-
logger.info('Bulk archival completed', {
|
|
404
|
-
total: results.length,
|
|
405
|
-
successful: successCount,
|
|
406
|
-
failed: results.length - successCount
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
---
|
|
412
|
-
|
|
413
|
-
### Pattern 3: Archive Failed Batches Only
|
|
414
|
-
|
|
415
|
-
```typescript
|
|
416
|
-
async function archiveFailedBatches(
|
|
417
|
-
batchResults: BatchResult[]
|
|
418
|
-
) {
|
|
419
|
-
const archivalService = new BatchArchivalService(config, s3Service, logger);
|
|
420
|
-
|
|
421
|
-
const failedBatches = batchResults
|
|
422
|
-
.filter(result => result.status === 'FAILED')
|
|
423
|
-
.map(result => ({
|
|
424
|
-
batch: result.originalPayload,
|
|
425
|
-
batchResponse: {
|
|
426
|
-
id: result.batchId,
|
|
427
|
-
jobId: result.jobId,
|
|
428
|
-
status: result.status
|
|
429
|
-
},
|
|
430
|
-
jobId: result.jobId
|
|
431
|
-
}));
|
|
432
|
-
|
|
433
|
-
if (failedBatches.length > 0) {
|
|
434
|
-
await archivalService.archiveBatches(failedBatches);
|
|
435
|
-
logger.warn(`Archived ${failedBatches.length} failed batches for investigation`);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
---
|
|
441
|
-
|
|
442
|
-
### Pattern 4: S3 Lifecycle Integration
|
|
443
|
-
|
|
444
|
-
Configure S3 lifecycle policies to manage archived data:
|
|
445
|
-
|
|
446
|
-
```typescript
|
|
447
|
-
// AWS CLI example for setting up lifecycle policy
|
|
448
|
-
const lifecyclePolicy = {
|
|
449
|
-
Rules: [
|
|
450
|
-
{
|
|
451
|
-
Id: 'ArchiveTo Glacier After 90 Days',
|
|
452
|
-
Status: 'Enabled',
|
|
453
|
-
Prefix: 'fluent_batches/',
|
|
454
|
-
Transitions: [
|
|
455
|
-
{
|
|
456
|
-
Days: 90,
|
|
457
|
-
StorageClass: 'GLACIER'
|
|
458
|
-
}
|
|
459
|
-
]
|
|
460
|
-
},
|
|
461
|
-
{
|
|
462
|
-
Id: 'Delete After 7 Years',
|
|
463
|
-
Status: 'Enabled',
|
|
464
|
-
Prefix: 'fluent_batches/',
|
|
465
|
-
Expiration: {
|
|
466
|
-
Days: 2555 // 7 years
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
]
|
|
470
|
-
};
|
|
471
|
-
|
|
472
|
-
// Apply via AWS CLI:
|
|
473
|
-
// aws s3api put-bucket-lifecycle-configuration \
|
|
474
|
-
// --bucket my-batch-archives \
|
|
475
|
-
// --lifecycle-configuration file://lifecycle-policy.json
|
|
476
|
-
```
|
|
477
|
-
|
|
478
|
-
---
|
|
479
|
-
|
|
480
|
-
### Pattern 5: Query Archived Batches
|
|
481
|
-
|
|
482
|
-
```typescript
|
|
483
|
-
async function queryArchivedBatches(
|
|
484
|
-
startDate: Date,
|
|
485
|
-
endDate: Date
|
|
486
|
-
): Promise<string[]> {
|
|
487
|
-
const archivalService = new BatchArchivalService(config, s3Service, logger);
|
|
488
|
-
const allKeys: string[] = [];
|
|
489
|
-
|
|
490
|
-
// Iterate through date range
|
|
491
|
-
const currentDate = new Date(startDate);
|
|
492
|
-
while (currentDate <= endDate) {
|
|
493
|
-
const keys = await archivalService.listArchivalsByDate(currentDate);
|
|
494
|
-
allKeys.push(...keys);
|
|
495
|
-
|
|
496
|
-
// Move to next day
|
|
497
|
-
currentDate.setDate(currentDate.getDate() + 1);
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
return allKeys;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
// Usage
|
|
504
|
-
const lastWeek = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
|
|
505
|
-
const today = new Date();
|
|
506
|
-
|
|
507
|
-
const archivedBatches = await queryArchivedBatches(lastWeek, today);
|
|
508
|
-
console.log(`Found ${archivedBatches.length} archived batches in the last 7 days`);
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
---
|
|
512
|
-
|
|
513
|
-
## Versori Integration
|
|
514
|
-
|
|
515
|
-
### Pattern: Archive in Versori Workflow
|
|
516
|
-
|
|
517
|
-
```typescript
|
|
518
|
-
import { Buffer } from 'node:buffer'; // Required for Deno/Versori runtime
|
|
519
|
-
import { http } from '@versori/run';
|
|
520
|
-
import {
|
|
521
|
-
createClient,
|
|
522
|
-
BatchArchivalService,
|
|
523
|
-
S3PresignService
|
|
524
|
-
} from '@fluentcommerce/fc-connect-sdk';
|
|
525
|
-
|
|
526
|
-
export const inventoryIngestion = http('inventory-ingestion', {
|
|
527
|
-
connection: 'fluent_commerce'
|
|
528
|
-
}, async ctx => {
|
|
529
|
-
const { log } = ctx;
|
|
530
|
-
|
|
531
|
-
// Initialize services
|
|
532
|
-
const client = await createClient(ctx); // Auto-detects Versori context
|
|
533
|
-
|
|
534
|
-
const s3Service = new S3PresignService();
|
|
535
|
-
const archivalService = new BatchArchivalService(
|
|
536
|
-
{
|
|
537
|
-
bucketName: process.env.ARCHIVE_BUCKET!,
|
|
538
|
-
region: process.env.AWS_REGION!,
|
|
539
|
-
credentials: {
|
|
540
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
541
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
542
|
-
}
|
|
543
|
-
},
|
|
544
|
-
s3Service,
|
|
545
|
-
log
|
|
546
|
-
);
|
|
547
|
-
|
|
548
|
-
// Process ingestion
|
|
549
|
-
const jobId = `versori-ingestion-${Date.now()}`;
|
|
550
|
-
const batchResponse = await client.sendBatch(jobId, {
|
|
551
|
-
action: 'UPSERT',
|
|
552
|
-
entityType: 'INVENTORY',
|
|
553
|
-
entities: inventoryRecords
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
// Archive
|
|
557
|
-
const archiveResult = await archivalService.archiveBatch({
|
|
558
|
-
batch: {
|
|
559
|
-
action: 'UPSERT',
|
|
560
|
-
entityType: 'INVENTORY',
|
|
561
|
-
entities: inventoryRecords
|
|
562
|
-
},
|
|
563
|
-
batchResponse,
|
|
564
|
-
jobId
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
return {
|
|
568
|
-
jobId,
|
|
569
|
-
batchId: batchResponse.id,
|
|
570
|
-
archived: archiveResult.success,
|
|
571
|
-
archivePath: archiveResult.archivedPath
|
|
572
|
-
};
|
|
573
|
-
});
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
---
|
|
577
|
-
|
|
578
|
-
## Error Handling
|
|
579
|
-
|
|
580
|
-
`BatchArchivalService` never throws errors - it returns results with error details.
|
|
581
|
-
|
|
582
|
-
```typescript
|
|
583
|
-
const result = await archivalService.archiveBatch(batchItem);
|
|
584
|
-
|
|
585
|
-
if (!result.success) {
|
|
586
|
-
logger.error('Archival failed', {
|
|
587
|
-
error: result.error,
|
|
588
|
-
jobId: batchItem.jobId
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
// Categorize error
|
|
592
|
-
if (result.error?.includes('403') || result.error?.includes('Access Denied')) {
|
|
593
|
-
// AWS credentials issue
|
|
594
|
-
logger.error('Check AWS credentials and S3 bucket permissions');
|
|
595
|
-
} else if (result.error?.includes('404') || result.error?.includes('NoSuchBucket')) {
|
|
596
|
-
// Bucket doesn't exist
|
|
597
|
-
logger.error('S3 bucket not found - check bucket name');
|
|
598
|
-
} else if (result.error?.includes('timeout')) {
|
|
599
|
-
// Network timeout
|
|
600
|
-
logger.error('S3 upload timeout - check network connectivity');
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
// Continue processing even if archival fails
|
|
604
|
-
// Archival is non-critical for data ingestion
|
|
605
|
-
}
|
|
606
|
-
```
|
|
607
|
-
|
|
608
|
-
---
|
|
609
|
-
|
|
610
|
-
## Patterns
|
|
611
|
-
|
|
612
|
-
### 1. Archive After Batch Send
|
|
613
|
-
|
|
614
|
-
```typescript
|
|
615
|
-
const batchResponse = await client.sendBatch(jobId, payload);
|
|
616
|
-
await archivalService.archiveBatch({ batch: payload, batchResponse, jobId });
|
|
617
|
-
```
|
|
618
|
-
|
|
619
|
-
### 2. Use Client IDs for Multi-Tenant
|
|
620
|
-
|
|
621
|
-
```typescript
|
|
622
|
-
await archivalService.archiveBatch(batchItem, 'client-abc');
|
|
623
|
-
```
|
|
624
|
-
|
|
625
|
-
### 3. Handle Archival Failures Gracefully
|
|
626
|
-
|
|
627
|
-
```typescript
|
|
628
|
-
const batchResponse = await client.sendBatch(jobId, payload);
|
|
629
|
-
const archiveResult = await archivalService.archiveBatch(batchItem);
|
|
630
|
-
|
|
631
|
-
if (!archiveResult.success) {
|
|
632
|
-
logger.warn('Archival failed but ingestion succeeded', {
|
|
633
|
-
jobId,
|
|
634
|
-
error: archiveResult.error
|
|
635
|
-
});
|
|
636
|
-
}
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
### 4. Configure S3 Lifecycle Policies
|
|
640
|
-
|
|
641
|
-
Set up lifecycle policies for cost optimization:
|
|
642
|
-
- Move to Glacier after 90 days (compliance requirements)
|
|
643
|
-
- Delete after 7 years (retention policies)
|
|
644
|
-
|
|
645
|
-
---
|
|
646
|
-
|
|
647
|
-
## Troubleshooting
|
|
648
|
-
|
|
649
|
-
### Archival Fails with "Access Denied"
|
|
650
|
-
|
|
651
|
-
**Problem:** S3 upload returns 403 Forbidden
|
|
652
|
-
|
|
653
|
-
**Causes:**
|
|
654
|
-
1. Invalid AWS credentials
|
|
655
|
-
2. Missing S3 bucket permissions
|
|
656
|
-
3. Bucket policy restrictions
|
|
657
|
-
|
|
658
|
-
**Solution:**
|
|
659
|
-
```typescript
|
|
660
|
-
// 1. Verify credentials
|
|
661
|
-
console.log('AWS Key:', process.env.AWS_ACCESS_KEY_ID?.substring(0, 8) + '...');
|
|
662
|
-
|
|
663
|
-
// 2. Check IAM policy - needs these permissions:
|
|
664
|
-
// {
|
|
665
|
-
// "Version": "2012-10-17",
|
|
666
|
-
// "Statement": [{
|
|
667
|
-
// "Effect": "Allow",
|
|
668
|
-
// "Action": [
|
|
669
|
-
// "s3:PutObject",
|
|
670
|
-
// "s3:ListBucket"
|
|
671
|
-
// ],
|
|
672
|
-
// "Resource": [
|
|
673
|
-
// "arn:aws:s3:::my-batch-archives",
|
|
674
|
-
// "arn:aws:s3:::my-batch-archives/*"
|
|
675
|
-
// ]
|
|
676
|
-
// }]
|
|
677
|
-
// }
|
|
678
|
-
|
|
679
|
-
// 3. Test S3 access directly
|
|
680
|
-
const testResult = await s3Service.presignPutObject({
|
|
681
|
-
bucket: config.bucketName,
|
|
682
|
-
region: config.region,
|
|
683
|
-
credentials: config.credentials,
|
|
684
|
-
key: 'test.txt',
|
|
685
|
-
contentType: 'text/plain',
|
|
686
|
-
expiresSeconds: 300
|
|
687
|
-
});
|
|
688
|
-
console.log('Presigned URL generated:', testResult.url);
|
|
689
|
-
```
|
|
690
|
-
|
|
691
|
-
### Archival Path Not Found When Querying
|
|
692
|
-
|
|
693
|
-
**Problem:** `listArchivalsByDate()` returns empty array
|
|
694
|
-
|
|
695
|
-
**Causes:**
|
|
696
|
-
1. Wrong date/timezone
|
|
697
|
-
2. Incorrect base path
|
|
698
|
-
3. Batches not yet archived
|
|
699
|
-
|
|
700
|
-
**Solution:**
|
|
701
|
-
```typescript
|
|
702
|
-
// Use UTC dates consistently
|
|
703
|
-
const today = new Date();
|
|
704
|
-
today.setUTCHours(0, 0, 0, 0); // Start of day UTC
|
|
705
|
-
|
|
706
|
-
const keys = await archivalService.listArchivalsByDate(today);
|
|
707
|
-
|
|
708
|
-
// Debug the prefix being searched
|
|
709
|
-
const prefix = `${config.basePath}/2025/01/30/`;
|
|
710
|
-
logger.debug('Searching S3 prefix:', prefix);
|
|
711
|
-
```
|
|
712
|
-
|
|
713
|
-
---
|
|
714
|
-
|
|
715
|
-
## See Also
|
|
716
|
-
|
|
717
|
-
- [FluentBatchManager](../ingestion/modules/02-core-guides-ingestion-06-batch-api.md) - Send batches to Fluent
|
|
718
|
-
- [JobTracker](./advanced-services-job-tracker.md) - Track job lifecycle
|
|
719
|
-
- [PartialBatchRecovery](./advanced-services-partial-batch-recovery.md) - Handle partial failures
|
|
720
|
-
- [S3PresignService](../data-sources/modules/data-sources-02-s3-operations.md) - S3 presigned URLs
|
|
721
|
-
- [Advanced Services Overview](./advanced-services-readme.md) - All advanced services
|
|
722
|
-
|
|
723
|
-
---
|
|
724
|
-
|
|
1
|
+
# BatchArchivalService
|
|
2
|
+
|
|
3
|
+
**Level:** Advanced
|
|
4
|
+
**Category:** Compliance & Audit
|
|
5
|
+
**Purpose:** Archive batch payloads to S3 for audit trails and compliance
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
`BatchArchivalService` provides automatic archival of batch payloads to S3 with hierarchical time-based paths. It creates audit trails for all batch operations, enabling compliance tracking, debugging, and historical analysis.
|
|
10
|
+
|
|
11
|
+
**Key Features:**
|
|
12
|
+
- Hierarchical time-based S3 paths (`YYYY/MM/DD/HH/MM`)
|
|
13
|
+
- Presigned URL uploads (no direct S3 SDK dependencies)
|
|
14
|
+
- Bulk archival with parallel uploads
|
|
15
|
+
- Automatic metadata enrichment
|
|
16
|
+
- Failed upload handling
|
|
17
|
+
|
|
18
|
+
## Use Cases
|
|
19
|
+
|
|
20
|
+
- ✅ Regulatory compliance (SOX, GDPR, HIPAA)
|
|
21
|
+
- ✅ Audit trail requirements
|
|
22
|
+
- ✅ Debug production batch failures
|
|
23
|
+
- ✅ Historical data analysis
|
|
24
|
+
- ✅ Replay failed batches
|
|
25
|
+
- ✅ Track data lineage
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import {
|
|
33
|
+
BatchArchivalService,
|
|
34
|
+
S3PresignService
|
|
35
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Basic Usage
|
|
41
|
+
|
|
42
|
+
### Archive Single Batch
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { BatchArchivalService, S3PresignService } from '@fluentcommerce/fc-connect-sdk';
|
|
46
|
+
|
|
47
|
+
// Configure archival service
|
|
48
|
+
const config = {
|
|
49
|
+
bucketName: 'my-batch-archives',
|
|
50
|
+
region: 'us-east-1',
|
|
51
|
+
credentials: {
|
|
52
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
53
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
54
|
+
},
|
|
55
|
+
basePath: 'fluent_batches', // Optional: defaults to 'fluent_batches'
|
|
56
|
+
expiresSeconds: 300 // Optional: presigned URL expiry (default: 300s)
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Initialize services
|
|
60
|
+
const s3Service = new S3PresignService();
|
|
61
|
+
const archivalService = new BatchArchivalService(config, s3Service, logger);
|
|
62
|
+
|
|
63
|
+
// Archive a batch
|
|
64
|
+
const result = await archivalService.archiveBatch(
|
|
65
|
+
{
|
|
66
|
+
batch: {
|
|
67
|
+
action: 'UPSERT',
|
|
68
|
+
entityType: 'INVENTORY',
|
|
69
|
+
entities: [{ skuRef: 'SKU001', qty: 100 }]
|
|
70
|
+
},
|
|
71
|
+
batchResponse: {
|
|
72
|
+
id: 'batch-123',
|
|
73
|
+
jobId: 'job-456',
|
|
74
|
+
status: 'COMPLETED'
|
|
75
|
+
},
|
|
76
|
+
jobId: 'job-456'
|
|
77
|
+
},
|
|
78
|
+
'client-abc' // Optional client ID for tracking
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
if (result.success) {
|
|
82
|
+
console.log('Archived to:', result.archivedPath);
|
|
83
|
+
// Output: fluent_batches/2025/01/30/14/30/batch-job-456-batch-123.json
|
|
84
|
+
} else {
|
|
85
|
+
console.error('Archival failed:', result.error);
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## API Reference
|
|
92
|
+
|
|
93
|
+
### Constructor
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
new BatchArchivalService(
|
|
97
|
+
config: BatchArchivalConfig,
|
|
98
|
+
s3PresignService: S3PresignService,
|
|
99
|
+
logger?: Logger
|
|
100
|
+
)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Parameters:**
|
|
104
|
+
- `config` - Archival configuration
|
|
105
|
+
- `bucketName` - S3 bucket name
|
|
106
|
+
- `region` - AWS region
|
|
107
|
+
- `credentials` - AWS credentials
|
|
108
|
+
- `basePath` - Optional base path (default: 'fluent_batches')
|
|
109
|
+
- `expiresSeconds` - Optional presigned URL TTL (default: 300)
|
|
110
|
+
- `s3PresignService` - S3 presign service instance
|
|
111
|
+
- `logger` - Optional structured logger
|
|
112
|
+
|
|
113
|
+
**Example:**
|
|
114
|
+
```typescript
|
|
115
|
+
const archivalService = new BatchArchivalService(
|
|
116
|
+
{
|
|
117
|
+
bucketName: 'production-archives',
|
|
118
|
+
region: 'us-west-2',
|
|
119
|
+
credentials: {
|
|
120
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
121
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
122
|
+
},
|
|
123
|
+
basePath: 'compliance/batches',
|
|
124
|
+
expiresSeconds: 600
|
|
125
|
+
},
|
|
126
|
+
s3PresignService,
|
|
127
|
+
logger
|
|
128
|
+
);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
### archiveBatch()
|
|
134
|
+
|
|
135
|
+
Archive a single batch to S3.
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
await archivalService.archiveBatch(
|
|
139
|
+
batchItem: BatchToArchive,
|
|
140
|
+
clientId?: string
|
|
141
|
+
): Promise<ArchivalResult>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Parameters:**
|
|
145
|
+
- `batchItem` - Batch data to archive
|
|
146
|
+
- `batch` - Original batch payload
|
|
147
|
+
- `batchResponse` - Response from Batch API
|
|
148
|
+
- `jobId` - Job identifier
|
|
149
|
+
- `clientId` - Optional client identifier for multi-tenant tracking
|
|
150
|
+
|
|
151
|
+
**Returns:** `ArchivalResult`
|
|
152
|
+
```typescript
|
|
153
|
+
{
|
|
154
|
+
success: boolean;
|
|
155
|
+
archivedPath?: string; // S3 key if successful
|
|
156
|
+
error?: string; // Error message if failed
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Example:**
|
|
161
|
+
```typescript
|
|
162
|
+
const result = await archivalService.archiveBatch(
|
|
163
|
+
{
|
|
164
|
+
batch: {
|
|
165
|
+
action: 'UPSERT',
|
|
166
|
+
entityType: 'INVENTORY',
|
|
167
|
+
catalogueRef: 'DEFAULT:1',
|
|
168
|
+
entities: inventoryRecords
|
|
169
|
+
},
|
|
170
|
+
batchResponse: {
|
|
171
|
+
id: batchResponse.id,
|
|
172
|
+
jobId: batchResponse.jobId,
|
|
173
|
+
status: batchResponse.status
|
|
174
|
+
},
|
|
175
|
+
jobId: 'inventory-sync-2025-01-30'
|
|
176
|
+
},
|
|
177
|
+
'tenant-123'
|
|
178
|
+
);
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### archiveBatches()
|
|
184
|
+
|
|
185
|
+
Archive multiple batches in parallel.
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
await archivalService.archiveBatches(
|
|
189
|
+
batches: BatchToArchive[],
|
|
190
|
+
clientId?: string
|
|
191
|
+
): Promise<ArchivalResult[]>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Parameters:**
|
|
195
|
+
- `batches` - Array of batches to archive
|
|
196
|
+
- `clientId` - Optional client identifier
|
|
197
|
+
|
|
198
|
+
**Returns:** Array of `ArchivalResult` (one per batch)
|
|
199
|
+
|
|
200
|
+
**Example:**
|
|
201
|
+
```typescript
|
|
202
|
+
const batches = [
|
|
203
|
+
{ batch: batch1, batchResponse: response1, jobId: 'job-1' },
|
|
204
|
+
{ batch: batch2, batchResponse: response2, jobId: 'job-2' },
|
|
205
|
+
{ batch: batch3, batchResponse: response3, jobId: 'job-3' }
|
|
206
|
+
];
|
|
207
|
+
|
|
208
|
+
const results = await archivalService.archiveBatches(batches, 'tenant-123');
|
|
209
|
+
|
|
210
|
+
const successCount = results.filter(r => r.success).length;
|
|
211
|
+
console.log(`Archived ${successCount} of ${results.length} batches`);
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
### generateArchivalPath()
|
|
217
|
+
|
|
218
|
+
Generate S3 path without uploading (useful for pre-computation).
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
const path = archivalService.generateArchivalPath(
|
|
222
|
+
jobId: string,
|
|
223
|
+
batchId?: string,
|
|
224
|
+
timestamp?: Date
|
|
225
|
+
): string
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Parameters:**
|
|
229
|
+
- `jobId` - Job identifier
|
|
230
|
+
- `batchId` - Optional batch identifier
|
|
231
|
+
- `timestamp` - Optional timestamp (defaults to now)
|
|
232
|
+
|
|
233
|
+
**Returns:** S3 key string
|
|
234
|
+
|
|
235
|
+
**Example:**
|
|
236
|
+
```typescript
|
|
237
|
+
const path = archivalService.generateArchivalPath(
|
|
238
|
+
'inventory-sync-2025-01-30',
|
|
239
|
+
'batch-123',
|
|
240
|
+
new Date('2025-01-30T14:30:00Z')
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
console.log(path);
|
|
244
|
+
// Output: fluent_batches/2025/01/30/14/30/batch-inventory-sync-2025-01-30-batch-123.json
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### listArchivalsByDate()
|
|
250
|
+
|
|
251
|
+
List all archived batches for a specific date.
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
const keys = await archivalService.listArchivalsByDate(
|
|
255
|
+
date: Date
|
|
256
|
+
): Promise<string[]>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**Parameters:**
|
|
260
|
+
- `date` - Date to query
|
|
261
|
+
|
|
262
|
+
**Returns:** Array of S3 keys
|
|
263
|
+
|
|
264
|
+
**Example:**
|
|
265
|
+
```typescript
|
|
266
|
+
const today = new Date('2025-01-30');
|
|
267
|
+
const archivedBatches = await archivalService.listArchivalsByDate(today);
|
|
268
|
+
|
|
269
|
+
console.log(`Found ${archivedBatches.length} archived batches for today:`);
|
|
270
|
+
archivedBatches.forEach(key => console.log(` - ${key}`));
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## S3 Path Structure
|
|
276
|
+
|
|
277
|
+
BatchArchivalService creates hierarchical paths for efficient querying:
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
{basePath}/{YYYY}/{MM}/{DD}/{HH}/{MM}/batch-{jobId}-{batchId}.json
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Example Paths:**
|
|
284
|
+
```
|
|
285
|
+
fluent_batches/2025/01/30/14/30/batch-inventory-sync-batch-123.json
|
|
286
|
+
fluent_batches/2025/01/30/14/31/batch-inventory-sync-batch-124.json
|
|
287
|
+
compliance/batches/2025/01/30/15/00/batch-order-sync-batch-456.json
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Benefits:**
|
|
291
|
+
- Easy date-based queries
|
|
292
|
+
- Efficient S3 lifecycle policies
|
|
293
|
+
- Time-series analysis
|
|
294
|
+
- Quick drill-down debugging
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Archived Payload Format
|
|
299
|
+
|
|
300
|
+
Each archived file contains:
|
|
301
|
+
|
|
302
|
+
```json
|
|
303
|
+
{
|
|
304
|
+
"action": "UPSERT",
|
|
305
|
+
"entityType": "INVENTORY",
|
|
306
|
+
"catalogueRef": "DEFAULT:1",
|
|
307
|
+
"entities": [
|
|
308
|
+
{ "skuRef": "SKU001", "qty": 100 },
|
|
309
|
+
{ "skuRef": "SKU002", "qty": 200 }
|
|
310
|
+
],
|
|
311
|
+
"clientId": "tenant-123",
|
|
312
|
+
"archivedAt": "2025-01-30T14:30:00.000Z",
|
|
313
|
+
"batchMetadata": {
|
|
314
|
+
"jobId": "inventory-sync-2025-01-30",
|
|
315
|
+
"batchId": "batch-123",
|
|
316
|
+
"status": "COMPLETED"
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Common Patterns
|
|
324
|
+
|
|
325
|
+
### Pattern 1: Archive After Successful Ingestion
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import {
|
|
329
|
+
FluentBatchManager,
|
|
330
|
+
BatchArchivalService,
|
|
331
|
+
S3PresignService
|
|
332
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
333
|
+
|
|
334
|
+
async function ingestWithArchival(records: any[]) {
|
|
335
|
+
const batchManager = new FluentBatchManager(client, logger);
|
|
336
|
+
const archivalService = new BatchArchivalService(archivalConfig, s3Service, logger);
|
|
337
|
+
|
|
338
|
+
const jobId = `inventory-sync-${Date.now()}`;
|
|
339
|
+
|
|
340
|
+
// Send batch
|
|
341
|
+
const batchResponse = await client.sendBatch(jobId, {
|
|
342
|
+
action: 'UPSERT',
|
|
343
|
+
entityType: 'INVENTORY',
|
|
344
|
+
entities: records
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// Archive immediately after successful send
|
|
348
|
+
await archivalService.archiveBatch({
|
|
349
|
+
batch: {
|
|
350
|
+
action: 'UPSERT',
|
|
351
|
+
entityType: 'INVENTORY',
|
|
352
|
+
entities: records
|
|
353
|
+
},
|
|
354
|
+
batchResponse,
|
|
355
|
+
jobId
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
logger.info('Batch sent and archived', { jobId, batchId: batchResponse.id });
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
### Pattern 2: Archive All Batches (Bulk)
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
async function bulkIngestWithArchival(
|
|
368
|
+
fileRecords: Record<string, any[]>
|
|
369
|
+
) {
|
|
370
|
+
const archivalService = new BatchArchivalService(config, s3Service, logger);
|
|
371
|
+
const batchesToArchive: BatchToArchive[] = [];
|
|
372
|
+
|
|
373
|
+
// Process all files
|
|
374
|
+
for (const [fileName, records] of Object.entries(fileRecords)) {
|
|
375
|
+
const jobId = `ingestion-${fileName}-${Date.now()}`;
|
|
376
|
+
|
|
377
|
+
// Send batch
|
|
378
|
+
const batchResponse = await client.sendBatch(jobId, {
|
|
379
|
+
action: 'UPSERT',
|
|
380
|
+
entityType: 'INVENTORY',
|
|
381
|
+
entities: records
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
// Queue for archival
|
|
385
|
+
batchesToArchive.push({
|
|
386
|
+
batch: {
|
|
387
|
+
action: 'UPSERT',
|
|
388
|
+
entityType: 'INVENTORY',
|
|
389
|
+
entities: records
|
|
390
|
+
},
|
|
391
|
+
batchResponse,
|
|
392
|
+
jobId
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Archive all batches in parallel
|
|
397
|
+
const results = await archivalService.archiveBatches(
|
|
398
|
+
batchesToArchive,
|
|
399
|
+
'tenant-abc'
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
const successCount = results.filter(r => r.success).length;
|
|
403
|
+
logger.info('Bulk archival completed', {
|
|
404
|
+
total: results.length,
|
|
405
|
+
successful: successCount,
|
|
406
|
+
failed: results.length - successCount
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
### Pattern 3: Archive Failed Batches Only
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
async function archiveFailedBatches(
|
|
417
|
+
batchResults: BatchResult[]
|
|
418
|
+
) {
|
|
419
|
+
const archivalService = new BatchArchivalService(config, s3Service, logger);
|
|
420
|
+
|
|
421
|
+
const failedBatches = batchResults
|
|
422
|
+
.filter(result => result.status === 'FAILED')
|
|
423
|
+
.map(result => ({
|
|
424
|
+
batch: result.originalPayload,
|
|
425
|
+
batchResponse: {
|
|
426
|
+
id: result.batchId,
|
|
427
|
+
jobId: result.jobId,
|
|
428
|
+
status: result.status
|
|
429
|
+
},
|
|
430
|
+
jobId: result.jobId
|
|
431
|
+
}));
|
|
432
|
+
|
|
433
|
+
if (failedBatches.length > 0) {
|
|
434
|
+
await archivalService.archiveBatches(failedBatches);
|
|
435
|
+
logger.warn(`Archived ${failedBatches.length} failed batches for investigation`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
### Pattern 4: S3 Lifecycle Integration
|
|
443
|
+
|
|
444
|
+
Configure S3 lifecycle policies to manage archived data:
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
// AWS CLI example for setting up lifecycle policy
|
|
448
|
+
const lifecyclePolicy = {
|
|
449
|
+
Rules: [
|
|
450
|
+
{
|
|
451
|
+
Id: 'ArchiveTo Glacier After 90 Days',
|
|
452
|
+
Status: 'Enabled',
|
|
453
|
+
Prefix: 'fluent_batches/',
|
|
454
|
+
Transitions: [
|
|
455
|
+
{
|
|
456
|
+
Days: 90,
|
|
457
|
+
StorageClass: 'GLACIER'
|
|
458
|
+
}
|
|
459
|
+
]
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
Id: 'Delete After 7 Years',
|
|
463
|
+
Status: 'Enabled',
|
|
464
|
+
Prefix: 'fluent_batches/',
|
|
465
|
+
Expiration: {
|
|
466
|
+
Days: 2555 // 7 years
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
]
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
// Apply via AWS CLI:
|
|
473
|
+
// aws s3api put-bucket-lifecycle-configuration \
|
|
474
|
+
// --bucket my-batch-archives \
|
|
475
|
+
// --lifecycle-configuration file://lifecycle-policy.json
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
### Pattern 5: Query Archived Batches
|
|
481
|
+
|
|
482
|
+
```typescript
|
|
483
|
+
async function queryArchivedBatches(
|
|
484
|
+
startDate: Date,
|
|
485
|
+
endDate: Date
|
|
486
|
+
): Promise<string[]> {
|
|
487
|
+
const archivalService = new BatchArchivalService(config, s3Service, logger);
|
|
488
|
+
const allKeys: string[] = [];
|
|
489
|
+
|
|
490
|
+
// Iterate through date range
|
|
491
|
+
const currentDate = new Date(startDate);
|
|
492
|
+
while (currentDate <= endDate) {
|
|
493
|
+
const keys = await archivalService.listArchivalsByDate(currentDate);
|
|
494
|
+
allKeys.push(...keys);
|
|
495
|
+
|
|
496
|
+
// Move to next day
|
|
497
|
+
currentDate.setDate(currentDate.getDate() + 1);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return allKeys;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Usage
|
|
504
|
+
const lastWeek = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
|
|
505
|
+
const today = new Date();
|
|
506
|
+
|
|
507
|
+
const archivedBatches = await queryArchivedBatches(lastWeek, today);
|
|
508
|
+
console.log(`Found ${archivedBatches.length} archived batches in the last 7 days`);
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## Versori Integration
|
|
514
|
+
|
|
515
|
+
### Pattern: Archive in Versori Workflow
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
import { Buffer } from 'node:buffer'; // Required for Deno/Versori runtime
|
|
519
|
+
import { http } from '@versori/run';
|
|
520
|
+
import {
|
|
521
|
+
createClient,
|
|
522
|
+
BatchArchivalService,
|
|
523
|
+
S3PresignService
|
|
524
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
525
|
+
|
|
526
|
+
export const inventoryIngestion = http('inventory-ingestion', {
|
|
527
|
+
connection: 'fluent_commerce'
|
|
528
|
+
}, async ctx => {
|
|
529
|
+
const { log } = ctx;
|
|
530
|
+
|
|
531
|
+
// Initialize services
|
|
532
|
+
const client = await createClient(ctx); // Auto-detects Versori context
|
|
533
|
+
|
|
534
|
+
const s3Service = new S3PresignService();
|
|
535
|
+
const archivalService = new BatchArchivalService(
|
|
536
|
+
{
|
|
537
|
+
bucketName: process.env.ARCHIVE_BUCKET!,
|
|
538
|
+
region: process.env.AWS_REGION!,
|
|
539
|
+
credentials: {
|
|
540
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
541
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
|
|
542
|
+
}
|
|
543
|
+
},
|
|
544
|
+
s3Service,
|
|
545
|
+
log
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
// Process ingestion
|
|
549
|
+
const jobId = `versori-ingestion-${Date.now()}`;
|
|
550
|
+
const batchResponse = await client.sendBatch(jobId, {
|
|
551
|
+
action: 'UPSERT',
|
|
552
|
+
entityType: 'INVENTORY',
|
|
553
|
+
entities: inventoryRecords
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
// Archive
|
|
557
|
+
const archiveResult = await archivalService.archiveBatch({
|
|
558
|
+
batch: {
|
|
559
|
+
action: 'UPSERT',
|
|
560
|
+
entityType: 'INVENTORY',
|
|
561
|
+
entities: inventoryRecords
|
|
562
|
+
},
|
|
563
|
+
batchResponse,
|
|
564
|
+
jobId
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
return {
|
|
568
|
+
jobId,
|
|
569
|
+
batchId: batchResponse.id,
|
|
570
|
+
archived: archiveResult.success,
|
|
571
|
+
archivePath: archiveResult.archivedPath
|
|
572
|
+
};
|
|
573
|
+
});
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
## Error Handling
|
|
579
|
+
|
|
580
|
+
`BatchArchivalService` never throws errors - it returns results with error details.
|
|
581
|
+
|
|
582
|
+
```typescript
|
|
583
|
+
const result = await archivalService.archiveBatch(batchItem);
|
|
584
|
+
|
|
585
|
+
if (!result.success) {
|
|
586
|
+
logger.error('Archival failed', {
|
|
587
|
+
error: result.error,
|
|
588
|
+
jobId: batchItem.jobId
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
// Categorize error
|
|
592
|
+
if (result.error?.includes('403') || result.error?.includes('Access Denied')) {
|
|
593
|
+
// AWS credentials issue
|
|
594
|
+
logger.error('Check AWS credentials and S3 bucket permissions');
|
|
595
|
+
} else if (result.error?.includes('404') || result.error?.includes('NoSuchBucket')) {
|
|
596
|
+
// Bucket doesn't exist
|
|
597
|
+
logger.error('S3 bucket not found - check bucket name');
|
|
598
|
+
} else if (result.error?.includes('timeout')) {
|
|
599
|
+
// Network timeout
|
|
600
|
+
logger.error('S3 upload timeout - check network connectivity');
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Continue processing even if archival fails
|
|
604
|
+
// Archival is non-critical for data ingestion
|
|
605
|
+
}
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## Patterns
|
|
611
|
+
|
|
612
|
+
### 1. Archive After Batch Send
|
|
613
|
+
|
|
614
|
+
```typescript
|
|
615
|
+
const batchResponse = await client.sendBatch(jobId, payload);
|
|
616
|
+
await archivalService.archiveBatch({ batch: payload, batchResponse, jobId });
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
### 2. Use Client IDs for Multi-Tenant
|
|
620
|
+
|
|
621
|
+
```typescript
|
|
622
|
+
await archivalService.archiveBatch(batchItem, 'client-abc');
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
### 3. Handle Archival Failures Gracefully
|
|
626
|
+
|
|
627
|
+
```typescript
|
|
628
|
+
const batchResponse = await client.sendBatch(jobId, payload);
|
|
629
|
+
const archiveResult = await archivalService.archiveBatch(batchItem);
|
|
630
|
+
|
|
631
|
+
if (!archiveResult.success) {
|
|
632
|
+
logger.warn('Archival failed but ingestion succeeded', {
|
|
633
|
+
jobId,
|
|
634
|
+
error: archiveResult.error
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
### 4. Configure S3 Lifecycle Policies
|
|
640
|
+
|
|
641
|
+
Set up lifecycle policies for cost optimization:
|
|
642
|
+
- Move to Glacier after 90 days (compliance requirements)
|
|
643
|
+
- Delete after 7 years (retention policies)
|
|
644
|
+
|
|
645
|
+
---
|
|
646
|
+
|
|
647
|
+
## Troubleshooting
|
|
648
|
+
|
|
649
|
+
### Archival Fails with "Access Denied"
|
|
650
|
+
|
|
651
|
+
**Problem:** S3 upload returns 403 Forbidden
|
|
652
|
+
|
|
653
|
+
**Causes:**
|
|
654
|
+
1. Invalid AWS credentials
|
|
655
|
+
2. Missing S3 bucket permissions
|
|
656
|
+
3. Bucket policy restrictions
|
|
657
|
+
|
|
658
|
+
**Solution:**
|
|
659
|
+
```typescript
|
|
660
|
+
// 1. Verify credentials
|
|
661
|
+
console.log('AWS Key:', process.env.AWS_ACCESS_KEY_ID?.substring(0, 8) + '...');
|
|
662
|
+
|
|
663
|
+
// 2. Check IAM policy - needs these permissions:
|
|
664
|
+
// {
|
|
665
|
+
// "Version": "2012-10-17",
|
|
666
|
+
// "Statement": [{
|
|
667
|
+
// "Effect": "Allow",
|
|
668
|
+
// "Action": [
|
|
669
|
+
// "s3:PutObject",
|
|
670
|
+
// "s3:ListBucket"
|
|
671
|
+
// ],
|
|
672
|
+
// "Resource": [
|
|
673
|
+
// "arn:aws:s3:::my-batch-archives",
|
|
674
|
+
// "arn:aws:s3:::my-batch-archives/*"
|
|
675
|
+
// ]
|
|
676
|
+
// }]
|
|
677
|
+
// }
|
|
678
|
+
|
|
679
|
+
// 3. Test S3 access directly
|
|
680
|
+
const testResult = await s3Service.presignPutObject({
|
|
681
|
+
bucket: config.bucketName,
|
|
682
|
+
region: config.region,
|
|
683
|
+
credentials: config.credentials,
|
|
684
|
+
key: 'test.txt',
|
|
685
|
+
contentType: 'text/plain',
|
|
686
|
+
expiresSeconds: 300
|
|
687
|
+
});
|
|
688
|
+
console.log('Presigned URL generated:', testResult.url);
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
### Archival Path Not Found When Querying
|
|
692
|
+
|
|
693
|
+
**Problem:** `listArchivalsByDate()` returns empty array
|
|
694
|
+
|
|
695
|
+
**Causes:**
|
|
696
|
+
1. Wrong date/timezone
|
|
697
|
+
2. Incorrect base path
|
|
698
|
+
3. Batches not yet archived
|
|
699
|
+
|
|
700
|
+
**Solution:**
|
|
701
|
+
```typescript
|
|
702
|
+
// Use UTC dates consistently
|
|
703
|
+
const today = new Date();
|
|
704
|
+
today.setUTCHours(0, 0, 0, 0); // Start of day UTC
|
|
705
|
+
|
|
706
|
+
const keys = await archivalService.listArchivalsByDate(today);
|
|
707
|
+
|
|
708
|
+
// Debug the prefix being searched
|
|
709
|
+
const prefix = `${config.basePath}/2025/01/30/`;
|
|
710
|
+
logger.debug('Searching S3 prefix:', prefix);
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
715
|
+
## See Also
|
|
716
|
+
|
|
717
|
+
- [FluentBatchManager](../ingestion/modules/02-core-guides-ingestion-06-batch-api.md) - Send batches to Fluent
|
|
718
|
+
- [JobTracker](./advanced-services-job-tracker.md) - Track job lifecycle
|
|
719
|
+
- [PartialBatchRecovery](./advanced-services-partial-batch-recovery.md) - Handle partial failures
|
|
720
|
+
- [S3PresignService](../data-sources/modules/data-sources-02-s3-operations.md) - S3 presigned URLs
|
|
721
|
+
- [Advanced Services Overview](./advanced-services-readme.md) - All advanced services
|
|
722
|
+
|
|
723
|
+
---
|
|
724
|
+
|