@fluentcommerce/fc-connect-sdk 0.1.54 → 0.1.56
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/README.md +11 -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,686 +1,686 @@
|
|
|
1
|
-
# Adding New Data Sources to fc-connect-sdk
|
|
2
|
-
|
|
3
|
-
This guide explains how to add new data sources (GCP Storage, Azure Blob Storage, etc.) to the SDK following the established factory pattern.
|
|
4
|
-
|
|
5
|
-
> **⚠️ IMPORTANT:**
|
|
6
|
-
>
|
|
7
|
-
> `uploadFile()` is a **required** abstract method. All data source implementations
|
|
8
|
-
> MUST implement this method or TypeScript will throw compilation errors.
|
|
9
|
-
|
|
10
|
-
## Architecture Overview
|
|
11
|
-
|
|
12
|
-
The SDK uses a **factory pattern** with abstract base classes for data source extensibility:
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
AbstractDataSource (base class)
|
|
16
|
-
├── REQUIRED Contract (abstract methods - MUST implement):
|
|
17
|
-
│ ├── listFiles() - List available files
|
|
18
|
-
│ ├── downloadFile() - Download file content
|
|
19
|
-
│ ├── uploadFile() - Upload file ⚠️ **REQUIRED**
|
|
20
|
-
│ ├── deleteFile() - Delete file
|
|
21
|
-
│ ├── copyFileInternal() - Copy file
|
|
22
|
-
│ └── validateConnection() - Test connection
|
|
23
|
-
│
|
|
24
|
-
├── ⚠️ IMPORTANT:
|
|
25
|
-
│ uploadFile() is REQUIRED. Implementations without it will fail type checking.
|
|
26
|
-
│
|
|
27
|
-
├── TEMPLATE Methods (inherited - don't override):
|
|
28
|
-
│ ├── moveFile() - Uses copyFileInternal() + deleteFile()
|
|
29
|
-
│ └── archiveFile() - Uses moveFile() with timestamp
|
|
30
|
-
├── Built-in: Retry logic, connection caching, file filtering
|
|
31
|
-
└── Implementations extend this
|
|
32
|
-
|
|
33
|
-
DataSourceFactory (interface)
|
|
34
|
-
├── create(config, logger): AbstractDataSource
|
|
35
|
-
├── supports(type): boolean
|
|
36
|
-
└── getDefaultConfig(type): Partial<DataSourceConfig>
|
|
37
|
-
|
|
38
|
-
DataSourceRegistry (singleton)
|
|
39
|
-
├── Stores factories by type (S3_CSV, SFTP_CSV, etc.)
|
|
40
|
-
├── Creates instances via registered factories
|
|
41
|
-
└── Validates type support
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Current Implementations
|
|
45
|
-
|
|
46
|
-
| Data Source | File | Size | Types Supported |
|
|
47
|
-
|------------|------|------|----------------|
|
|
48
|
-
| **S3DataSource** | `s3-data-source.ts` | 33KB | S3_CSV, S3_JSON, S3_XML, S3_PARQUET |
|
|
49
|
-
| **SftpDataSource** | `sftp-data-source.ts` | 99KB | SFTP_CSV, SFTP_JSON, SFTP_XML, SFTP_PARQUET |
|
|
50
|
-
|
|
51
|
-
## Step-by-Step: Adding GCP Storage Data Source
|
|
52
|
-
|
|
53
|
-
### Step 1: Create Data Source Class
|
|
54
|
-
|
|
55
|
-
Create `src/data-sources/gcp-storage-data-source.ts`:
|
|
56
|
-
|
|
57
|
-
```typescript
|
|
58
|
-
import { AbstractDataSource, DataSourceFactory } from './abstract-data-source';
|
|
59
|
-
import { DataSourceConfig, FileMetadata, StructuredLogger } from '../types';
|
|
60
|
-
import { Storage } from '@google-cloud/storage';
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* GCP Storage configuration
|
|
64
|
-
*/
|
|
65
|
-
export interface GcpStorageConfig {
|
|
66
|
-
projectId: string;
|
|
67
|
-
keyFilename?: string; // Path to service account JSON
|
|
68
|
-
credentials?: object; // Or inline credentials
|
|
69
|
-
bucket: string;
|
|
70
|
-
prefix?: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* GCP Storage Data Source Configuration
|
|
75
|
-
*/
|
|
76
|
-
export interface GcpStorageDataSourceConfig extends DataSourceConfig {
|
|
77
|
-
type: 'GCP_CSV' | 'GCP_JSON' | 'GCP_XML' | 'GCP_PARQUET';
|
|
78
|
-
gcpConfig: GcpStorageConfig;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* GCP Storage Data Source Implementation
|
|
83
|
-
*/
|
|
84
|
-
export class GcpStorageDataSource extends AbstractDataSource {
|
|
85
|
-
type = 'GCP_STORAGE';
|
|
86
|
-
private storage: Storage;
|
|
87
|
-
private bucket: string;
|
|
88
|
-
|
|
89
|
-
constructor(config: GcpStorageDataSourceConfig, logger: StructuredLogger) {
|
|
90
|
-
super(config, logger);
|
|
91
|
-
|
|
92
|
-
// Initialize GCP Storage client
|
|
93
|
-
this.storage = new Storage({
|
|
94
|
-
projectId: config.gcpConfig.projectId,
|
|
95
|
-
keyFilename: config.gcpConfig.keyFilename,
|
|
96
|
-
credentials: config.gcpConfig.credentials,
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
this.bucket = config.gcpConfig.bucket;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* List files in GCP bucket
|
|
104
|
-
*/
|
|
105
|
-
async listFiles(params?: Record<string, unknown>): Promise<FileMetadata[]> {
|
|
106
|
-
try {
|
|
107
|
-
const prefix = params?.prefix as string | undefined;
|
|
108
|
-
const [files] = await this.storage.bucket(this.bucket).getFiles({ prefix });
|
|
109
|
-
|
|
110
|
-
return files.map(file => ({
|
|
111
|
-
name: file.name,
|
|
112
|
-
path: `gs://${this.bucket}/${file.name}`,
|
|
113
|
-
size: parseInt(file.metadata.size as string, 10),
|
|
114
|
-
lastModified: file.metadata.updated,
|
|
115
|
-
etag: file.metadata.etag,
|
|
116
|
-
}));
|
|
117
|
-
} catch (error) {
|
|
118
|
-
this.handleError('listFiles', error);
|
|
119
|
-
throw error;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Download file from GCP bucket
|
|
125
|
-
*/
|
|
126
|
-
async downloadFile(path: string, options?: Record<string, unknown>): Promise<string | Buffer> {
|
|
127
|
-
try {
|
|
128
|
-
const file = this.storage.bucket(this.bucket).file(path);
|
|
129
|
-
const [content] = await file.download();
|
|
130
|
-
|
|
131
|
-
if (options?.encoding === 'utf8') {
|
|
132
|
-
return content.toString('utf8');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return content;
|
|
136
|
-
} catch (error) {
|
|
137
|
-
this.handleError('downloadFile', error);
|
|
138
|
-
throw error;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Upload file to GCP bucket
|
|
144
|
-
*
|
|
145
|
-
* REQUIRED by AbstractDataSource contract
|
|
146
|
-
*
|
|
147
|
-
* @param path Remote path in bucket
|
|
148
|
-
* @param content Content to upload (string or Buffer)
|
|
149
|
-
* @param options Optional upload parameters
|
|
150
|
-
*/
|
|
151
|
-
async uploadFile(
|
|
152
|
-
path: string,
|
|
153
|
-
content: Buffer | string,
|
|
154
|
-
options?: Record<string, unknown>
|
|
155
|
-
): Promise<void> {
|
|
156
|
-
try {
|
|
157
|
-
const file = this.storage.bucket(this.bucket).file(path);
|
|
158
|
-
await file.save(content, {
|
|
159
|
-
contentType: options?.contentType as string | undefined,
|
|
160
|
-
metadata: options?.metadata as Record<string, string> | undefined,
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
this.logger.info('File uploaded to GCP', {
|
|
164
|
-
bucket: this.bucket,
|
|
165
|
-
path,
|
|
166
|
-
size: typeof content === 'string' ? content.length : content.length,
|
|
167
|
-
});
|
|
168
|
-
} catch (error) {
|
|
169
|
-
this.handleError('uploadFile', error);
|
|
170
|
-
throw error;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Delete file from GCP bucket
|
|
176
|
-
*
|
|
177
|
-
* REQUIRED by AbstractDataSource contract
|
|
178
|
-
*/
|
|
179
|
-
async deleteFile(path: string): Promise<void> {
|
|
180
|
-
try {
|
|
181
|
-
await this.storage.bucket(this.bucket).file(path).delete();
|
|
182
|
-
this.logger.info('File deleted from GCP', { bucket: this.bucket, path });
|
|
183
|
-
} catch (error) {
|
|
184
|
-
this.handleError('deleteFile', error);
|
|
185
|
-
throw error;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Copy file within GCP bucket (implements abstract method)
|
|
191
|
-
*
|
|
192
|
-
* REQUIRED by AbstractDataSource contract - used by moveFile() template method
|
|
193
|
-
*
|
|
194
|
-
* @param sourcePath Source file path
|
|
195
|
-
* @param destPath Destination file path
|
|
196
|
-
*/
|
|
197
|
-
async copyFileInternal(sourcePath: string, destPath: string): Promise<void> {
|
|
198
|
-
try {
|
|
199
|
-
const sourceFile = this.storage.bucket(this.bucket).file(sourcePath);
|
|
200
|
-
const destFile = this.storage.bucket(this.bucket).file(destPath);
|
|
201
|
-
|
|
202
|
-
await sourceFile.copy(destFile);
|
|
203
|
-
|
|
204
|
-
this.logger.info('File copied in GCP', {
|
|
205
|
-
bucket: this.bucket,
|
|
206
|
-
sourcePath,
|
|
207
|
-
destPath,
|
|
208
|
-
});
|
|
209
|
-
} catch (error) {
|
|
210
|
-
this.handleError('copyFileInternal', error);
|
|
211
|
-
throw error;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Validate GCP connection
|
|
217
|
-
*/
|
|
218
|
-
async validateConnection(): Promise<boolean> {
|
|
219
|
-
try {
|
|
220
|
-
const [exists] = await this.storage.bucket(this.bucket).exists();
|
|
221
|
-
return exists;
|
|
222
|
-
} catch (error) {
|
|
223
|
-
this.logger.error('GCP connection validation failed', error as Error);
|
|
224
|
-
return false;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Validate GCP configuration
|
|
230
|
-
*/
|
|
231
|
-
protected validateConfig(config: DataSourceConfig): void {
|
|
232
|
-
super.validateConfig(config);
|
|
233
|
-
|
|
234
|
-
const gcpConfig = (config as GcpStorageDataSourceConfig).gcpConfig;
|
|
235
|
-
|
|
236
|
-
if (!gcpConfig.projectId) {
|
|
237
|
-
throw new Error('GCP project ID is required');
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
if (!gcpConfig.bucket) {
|
|
241
|
-
throw new Error('GCP bucket name is required');
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (!gcpConfig.keyFilename && !gcpConfig.credentials) {
|
|
245
|
-
throw new Error('Either keyFilename or credentials must be provided');
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Cleanup resources
|
|
251
|
-
*/
|
|
252
|
-
async dispose(): Promise<void> {
|
|
253
|
-
await super.dispose();
|
|
254
|
-
// GCP Storage client doesn't require explicit disposal
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* GCP Storage Data Source Factory
|
|
260
|
-
*/
|
|
261
|
-
export class GcpStorageDataSourceFactory implements DataSourceFactory {
|
|
262
|
-
supports(type: string): boolean {
|
|
263
|
-
const supportedTypes = ['GCP_CSV', 'GCP_JSON', 'GCP_XML', 'GCP_PARQUET'];
|
|
264
|
-
return supportedTypes.includes(type.toUpperCase());
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
create(config: DataSourceConfig, logger: StructuredLogger): GcpStorageDataSource {
|
|
268
|
-
if (!this.supports(config.type)) {
|
|
269
|
-
throw new Error(`Factory does not support type: ${config.type}`);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
return new GcpStorageDataSource(config as GcpStorageDataSourceConfig, logger);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
getDefaultConfig(_type: string): Partial<GcpStorageDataSourceConfig> {
|
|
276
|
-
return {
|
|
277
|
-
type: 'GCP_CSV',
|
|
278
|
-
gcpConfig: {
|
|
279
|
-
projectId: '',
|
|
280
|
-
bucket: '',
|
|
281
|
-
keyFilename: '',
|
|
282
|
-
},
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
### Step 2: Register Factory in Index
|
|
289
|
-
|
|
290
|
-
Update `src/data-sources/index.ts`:
|
|
291
|
-
|
|
292
|
-
```typescript
|
|
293
|
-
// Add exports
|
|
294
|
-
export { GcpStorageDataSource, GcpStorageDataSourceFactory } from './gcp-storage-data-source';
|
|
295
|
-
export type { GcpStorageDataSourceConfig } from './gcp-storage-data-source';
|
|
296
|
-
|
|
297
|
-
// Update initializeDataSources()
|
|
298
|
-
export function initializeDataSources(): void {
|
|
299
|
-
const registry = DataSourceRegistry.getInstance();
|
|
300
|
-
|
|
301
|
-
// Existing registrations...
|
|
302
|
-
registry.register('S3_CSV', new S3DataSourceFactory());
|
|
303
|
-
registry.register('SFTP_CSV', new SftpDataSourceFactory());
|
|
304
|
-
|
|
305
|
-
// NEW: Register GCP Storage
|
|
306
|
-
const gcpFactory = new GcpStorageDataSourceFactory();
|
|
307
|
-
registry.register('GCP_CSV', gcpFactory);
|
|
308
|
-
registry.register('GCP_JSON', gcpFactory);
|
|
309
|
-
registry.register('GCP_XML', gcpFactory);
|
|
310
|
-
registry.register('GCP_PARQUET', gcpFactory);
|
|
311
|
-
}
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
### Step 3: Add Types to SDK Types
|
|
315
|
-
|
|
316
|
-
Update `src/types/index.ts`:
|
|
317
|
-
|
|
318
|
-
```typescript
|
|
319
|
-
export type DataSourceType =
|
|
320
|
-
| 'S3_CSV'
|
|
321
|
-
| 'S3_JSON'
|
|
322
|
-
| 'S3_XML'
|
|
323
|
-
| 'S3_PARQUET'
|
|
324
|
-
| 'SFTP_CSV'
|
|
325
|
-
| 'SFTP_JSON'
|
|
326
|
-
| 'SFTP_XML'
|
|
327
|
-
| 'SFTP_PARQUET'
|
|
328
|
-
| 'GCP_CSV' // NEW
|
|
329
|
-
| 'GCP_JSON' // NEW
|
|
330
|
-
| 'GCP_XML' // NEW
|
|
331
|
-
| 'GCP_PARQUET'; // NEW
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
### Step 4: Install Dependencies
|
|
335
|
-
|
|
336
|
-
```bash
|
|
337
|
-
npm install @google-cloud/storage
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
Update `package.json`:
|
|
341
|
-
|
|
342
|
-
```json
|
|
343
|
-
{
|
|
344
|
-
"dependencies": {
|
|
345
|
-
"@google-cloud/storage": "^7.0.0"
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
### Step 5: Add Unit Tests
|
|
351
|
-
|
|
352
|
-
Create `tests/unit/data-sources/gcp-storage-data-source.test.ts`:
|
|
353
|
-
|
|
354
|
-
```typescript
|
|
355
|
-
import { GcpStorageDataSource, GcpStorageDataSourceFactory } from '../../../src/data-sources/gcp-storage-data-source';
|
|
356
|
-
import { createConsoleLogger } from '../../../src/utils/logging';
|
|
357
|
-
|
|
358
|
-
describe('GcpStorageDataSource', () => {
|
|
359
|
-
const mockConfig = {
|
|
360
|
-
type: 'GCP_CSV' as const,
|
|
361
|
-
connectionId: 'test-gcp',
|
|
362
|
-
name: 'Test GCP Storage',
|
|
363
|
-
gcpConfig: {
|
|
364
|
-
projectId: 'test-project',
|
|
365
|
-
bucket: 'test-bucket',
|
|
366
|
-
credentials: { /* mock credentials */ },
|
|
367
|
-
},
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
const logger = createConsoleLogger();
|
|
371
|
-
|
|
372
|
-
describe('Factory', () => {
|
|
373
|
-
it('should support GCP types', () => {
|
|
374
|
-
const factory = new GcpStorageDataSourceFactory();
|
|
375
|
-
expect(factory.supports('GCP_CSV')).toBe(true);
|
|
376
|
-
expect(factory.supports('GCP_JSON')).toBe(true);
|
|
377
|
-
expect(factory.supports('S3_CSV')).toBe(false);
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
it('should create GCP data source instance', () => {
|
|
381
|
-
const factory = new GcpStorageDataSourceFactory();
|
|
382
|
-
const dataSource = factory.create(mockConfig, logger);
|
|
383
|
-
expect(dataSource).toBeInstanceOf(GcpStorageDataSource);
|
|
384
|
-
});
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
describe('Configuration Validation', () => {
|
|
388
|
-
it('should throw error if projectId missing', () => {
|
|
389
|
-
const invalidConfig = { ...mockConfig, gcpConfig: { ...mockConfig.gcpConfig, projectId: '' } };
|
|
390
|
-
expect(() => new GcpStorageDataSource(invalidConfig, logger)).toThrow('GCP project ID is required');
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
it('should throw error if bucket missing', () => {
|
|
394
|
-
const invalidConfig = { ...mockConfig, gcpConfig: { ...mockConfig.gcpConfig, bucket: '' } };
|
|
395
|
-
expect(() => new GcpStorageDataSource(invalidConfig, logger)).toThrow('GCP bucket name is required');
|
|
396
|
-
});
|
|
397
|
-
});
|
|
398
|
-
});
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
### Step 6: Update Documentation
|
|
402
|
-
|
|
403
|
-
Create `docs/02-CORE-GUIDES/data-sources/gcp-storage.md`:
|
|
404
|
-
|
|
405
|
-
```markdown
|
|
406
|
-
# GCP Storage Data Source
|
|
407
|
-
|
|
408
|
-
Upload and download files from Google Cloud Platform Storage buckets.
|
|
409
|
-
|
|
410
|
-
## Installation
|
|
411
|
-
|
|
412
|
-
```bash
|
|
413
|
-
npm install @google-cloud/storage
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
## Configuration
|
|
417
|
-
|
|
418
|
-
```typescript
|
|
419
|
-
import { GcpStorageDataSource } from '@fluentcommerce/fc-connect-sdk';
|
|
420
|
-
|
|
421
|
-
const gcpDataSource = new GcpStorageDataSource({
|
|
422
|
-
type: 'GCP_CSV',
|
|
423
|
-
connectionId: 'gcp-prod',
|
|
424
|
-
name: 'GCP Production Storage',
|
|
425
|
-
gcpConfig: {
|
|
426
|
-
projectId: 'my-project-id',
|
|
427
|
-
keyFilename: '/path/to/service-account.json',
|
|
428
|
-
bucket: 'my-bucket',
|
|
429
|
-
},
|
|
430
|
-
}, logger);
|
|
431
|
-
|
|
432
|
-
// List files
|
|
433
|
-
const files = await gcpDataSource.listFiles({ prefix: 'inventory/' });
|
|
434
|
-
|
|
435
|
-
// Download file
|
|
436
|
-
const content = await gcpDataSource.downloadFile('inventory/positions.csv');
|
|
437
|
-
|
|
438
|
-
// Upload file (REQUIRED method)
|
|
439
|
-
await gcpDataSource.uploadFile('output/file.csv', Buffer.from('data'), {
|
|
440
|
-
contentType: 'text/csv',
|
|
441
|
-
});
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
## Authentication Options
|
|
445
|
-
|
|
446
|
-
### Service Account Key File
|
|
447
|
-
|
|
448
|
-
```typescript
|
|
449
|
-
gcpConfig: {
|
|
450
|
-
projectId: 'my-project',
|
|
451
|
-
keyFilename: './service-account.json',
|
|
452
|
-
bucket: 'my-bucket',
|
|
453
|
-
}
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
### Inline Credentials
|
|
457
|
-
|
|
458
|
-
```typescript
|
|
459
|
-
gcpConfig: {
|
|
460
|
-
projectId: 'my-project',
|
|
461
|
-
credentials: {
|
|
462
|
-
client_email: 'service@project.iam.gserviceaccount.com',
|
|
463
|
-
private_key: '-----BEGIN PRIVATE KEY-----\n...',
|
|
464
|
-
},
|
|
465
|
-
bucket: 'my-bucket',
|
|
466
|
-
}
|
|
467
|
-
```
|
|
468
|
-
|
|
469
|
-
### Application Default Credentials (ADC)
|
|
470
|
-
|
|
471
|
-
When running in GCP (Cloud Run, Cloud Functions), credentials are automatic:
|
|
472
|
-
|
|
473
|
-
```typescript
|
|
474
|
-
gcpConfig: {
|
|
475
|
-
projectId: 'my-project',
|
|
476
|
-
bucket: 'my-bucket',
|
|
477
|
-
// keyFilename and credentials omitted - uses ADC
|
|
478
|
-
}
|
|
479
|
-
```
|
|
480
|
-
```
|
|
481
|
-
|
|
482
|
-
## Step 7: Test Integration
|
|
483
|
-
|
|
484
|
-
```bash
|
|
485
|
-
# Run unit tests
|
|
486
|
-
npm test -- gcp-storage-data-source.test.ts
|
|
487
|
-
|
|
488
|
-
# Run integration tests (requires real GCP credentials)
|
|
489
|
-
npm run test:integration:gcp
|
|
490
|
-
```
|
|
491
|
-
|
|
492
|
-
---
|
|
493
|
-
|
|
494
|
-
## Adding Azure Blob Storage (Similar Pattern)
|
|
495
|
-
|
|
496
|
-
Follow the same steps for Azure:
|
|
497
|
-
|
|
498
|
-
1. Create `azure-blob-data-source.ts`
|
|
499
|
-
2. Implement `AzureBlobDataSource extends AbstractDataSource`
|
|
500
|
-
3. Implement `AzureBlobDataSourceFactory implements DataSourceFactory`
|
|
501
|
-
4. Register factory with types: `AZURE_CSV`, `AZURE_JSON`, etc.
|
|
502
|
-
5. Add `@azure/storage-blob` dependency
|
|
503
|
-
6. Add tests and documentation
|
|
504
|
-
|
|
505
|
-
**Key differences:**
|
|
506
|
-
- Use `BlobServiceClient` from `@azure/storage-blob`
|
|
507
|
-
- Authentication: connection strings, SAS tokens, or DefaultAzureCredential
|
|
508
|
-
- Storage structure: containers instead of buckets
|
|
509
|
-
|
|
510
|
-
---
|
|
511
|
-
|
|
512
|
-
## Factory Pattern Benefits
|
|
513
|
-
|
|
514
|
-
### ✅ Extensibility
|
|
515
|
-
Add new data sources without modifying existing code
|
|
516
|
-
|
|
517
|
-
### ✅ Type Safety
|
|
518
|
-
Each data source has strongly-typed config interfaces
|
|
519
|
-
|
|
520
|
-
### ✅ Consistency
|
|
521
|
-
All data sources share common operations via `AbstractDataSource`
|
|
522
|
-
|
|
523
|
-
### ✅ Testability
|
|
524
|
-
Easy to mock factories for unit tests
|
|
525
|
-
|
|
526
|
-
### ✅ Registry Management
|
|
527
|
-
Centralized registration and discovery of data sources
|
|
528
|
-
|
|
529
|
-
---
|
|
530
|
-
|
|
531
|
-
## Best Practices
|
|
532
|
-
|
|
533
|
-
### 1. Retry Logic
|
|
534
|
-
Use built-in retry utilities from `AbstractDataSource`:
|
|
535
|
-
|
|
536
|
-
```typescript
|
|
537
|
-
async downloadFile(path: string): Promise<Buffer> {
|
|
538
|
-
return await this.getFileWithRetry(path, 3, 1000); // 3 retries, 1s delay
|
|
539
|
-
}
|
|
540
|
-
```
|
|
541
|
-
|
|
542
|
-
### 2. Connection Caching
|
|
543
|
-
Cache clients to avoid repeated initialization:
|
|
544
|
-
|
|
545
|
-
```typescript
|
|
546
|
-
private getClient(): StorageClient {
|
|
547
|
-
const cached = this.getCachedConnection<StorageClient>('client');
|
|
548
|
-
if (cached) return cached;
|
|
549
|
-
|
|
550
|
-
const client = new StorageClient(this.config);
|
|
551
|
-
this.setCachedConnection('client', client);
|
|
552
|
-
return client;
|
|
553
|
-
}
|
|
554
|
-
```
|
|
555
|
-
|
|
556
|
-
### 3. Cleanup Resources
|
|
557
|
-
Always implement `dispose()` for connection cleanup:
|
|
558
|
-
|
|
559
|
-
```typescript
|
|
560
|
-
async dispose(): Promise<void> {
|
|
561
|
-
await super.dispose();
|
|
562
|
-
await this.client?.close();
|
|
563
|
-
}
|
|
564
|
-
```
|
|
565
|
-
|
|
566
|
-
### 4. Error Handling
|
|
567
|
-
Use consistent error handling from base class:
|
|
568
|
-
|
|
569
|
-
```typescript
|
|
570
|
-
try {
|
|
571
|
-
return await operation();
|
|
572
|
-
} catch (error) {
|
|
573
|
-
this.handleError('operationName', error);
|
|
574
|
-
throw error;
|
|
575
|
-
}
|
|
576
|
-
```
|
|
577
|
-
|
|
578
|
-
### 5. Configuration Validation
|
|
579
|
-
Validate config in constructor:
|
|
580
|
-
|
|
581
|
-
```typescript
|
|
582
|
-
protected validateConfig(config: DataSourceConfig): void {
|
|
583
|
-
super.validateConfig(config); // Base validation
|
|
584
|
-
|
|
585
|
-
if (!config.customField) {
|
|
586
|
-
throw new DataSourceError('Custom field is required');
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
```
|
|
590
|
-
|
|
591
|
-
---
|
|
592
|
-
|
|
593
|
-
## Testing Your Data Source
|
|
594
|
-
|
|
595
|
-
### Unit Tests (Mock Client)
|
|
596
|
-
|
|
597
|
-
```typescript
|
|
598
|
-
jest.mock('@google-cloud/storage');
|
|
599
|
-
|
|
600
|
-
describe('GcpStorageDataSource', () => {
|
|
601
|
-
it('should list files', async () => {
|
|
602
|
-
const mockStorage = {
|
|
603
|
-
bucket: jest.fn().mockReturnValue({
|
|
604
|
-
getFiles: jest.fn().mockResolvedValue([mockFiles]),
|
|
605
|
-
}),
|
|
606
|
-
};
|
|
607
|
-
|
|
608
|
-
const dataSource = new GcpStorageDataSource(config, logger);
|
|
609
|
-
const files = await dataSource.listFiles();
|
|
610
|
-
expect(files).toHaveLength(3);
|
|
611
|
-
});
|
|
612
|
-
});
|
|
613
|
-
```
|
|
614
|
-
|
|
615
|
-
### Integration Tests (Real Credentials)
|
|
616
|
-
|
|
617
|
-
```typescript
|
|
618
|
-
describe('GcpStorageDataSource Integration', () => {
|
|
619
|
-
const realConfig = {
|
|
620
|
-
type: 'GCP_CSV' as const,
|
|
621
|
-
connectionId: 'test-gcp',
|
|
622
|
-
name: 'Test GCP',
|
|
623
|
-
gcpConfig: {
|
|
624
|
-
projectId: process.env.GCP_PROJECT_ID!,
|
|
625
|
-
keyFilename: process.env.GCP_KEY_FILE!,
|
|
626
|
-
bucket: process.env.GCP_TEST_BUCKET!,
|
|
627
|
-
},
|
|
628
|
-
};
|
|
629
|
-
|
|
630
|
-
it('should connect to real GCP bucket', async () => {
|
|
631
|
-
const dataSource = new GcpStorageDataSource(realConfig, logger);
|
|
632
|
-
const isValid = await dataSource.validateConnection();
|
|
633
|
-
expect(isValid).toBe(true);
|
|
634
|
-
});
|
|
635
|
-
});
|
|
636
|
-
```
|
|
637
|
-
|
|
638
|
-
---
|
|
639
|
-
|
|
640
|
-
## Summary
|
|
641
|
-
|
|
642
|
-
Adding a new data source requires:
|
|
643
|
-
|
|
644
|
-
1. ✅ Extend `AbstractDataSource`
|
|
645
|
-
2. ✅ Implement **4 required methods**:
|
|
646
|
-
- `listFiles()` - List available files
|
|
647
|
-
- `downloadFile()` - Download file content
|
|
648
|
-
- `uploadFile()` - **Upload file content (REQUIRED)**
|
|
649
|
-
- `validateConnection()` - Test connection
|
|
650
|
-
3. ✅ Implement `DataSourceFactory`
|
|
651
|
-
4. ✅ Register factory with type aliases
|
|
652
|
-
5. ✅ Add type definitions
|
|
653
|
-
6. ✅ Install dependencies
|
|
654
|
-
7. ✅ Write unit tests
|
|
655
|
-
8. ✅ Add documentation
|
|
656
|
-
9. ✅ Test integration
|
|
657
|
-
|
|
658
|
-
**Time to add new data source:** ~2-4 hours for experienced developers
|
|
659
|
-
|
|
660
|
-
**Maintenance cost:** Low - inherit retry, caching, filtering from base class
|
|
661
|
-
|
|
662
|
-
---
|
|
663
|
-
|
|
664
|
-
## ⚠️ IMPORTANT: uploadFile() is Mandatory
|
|
665
|
-
|
|
666
|
-
**`uploadFile()` is a required abstract method** in `AbstractDataSource`.
|
|
667
|
-
|
|
668
|
-
**Why?**
|
|
669
|
-
- All 13 extraction templates depend on upload functionality
|
|
670
|
-
- Extraction workflows must export data to S3/SFTP/GCP/Azure
|
|
671
|
-
- Ensures consistency across all data source implementations
|
|
672
|
-
|
|
673
|
-
**Signature:**
|
|
674
|
-
```typescript
|
|
675
|
-
abstract uploadFile(
|
|
676
|
-
path: string,
|
|
677
|
-
content: string | Buffer,
|
|
678
|
-
options?: Record<string, unknown>
|
|
679
|
-
): Promise<void>;
|
|
680
|
-
```
|
|
681
|
-
|
|
682
|
-
**Implementation Examples:**
|
|
683
|
-
- **S3**: Uses presigned PUT URLs
|
|
684
|
-
- **SFTP**: Uses ssh2-sftp-client with retry logic
|
|
685
|
-
- **GCP**: Uses `@google-cloud/storage` file.save()
|
|
686
|
-
- **Azure**: Uses `@azure/storage-blob` uploadData()
|
|
1
|
+
# Adding New Data Sources to fc-connect-sdk
|
|
2
|
+
|
|
3
|
+
This guide explains how to add new data sources (GCP Storage, Azure Blob Storage, etc.) to the SDK following the established factory pattern.
|
|
4
|
+
|
|
5
|
+
> **⚠️ IMPORTANT:**
|
|
6
|
+
>
|
|
7
|
+
> `uploadFile()` is a **required** abstract method. All data source implementations
|
|
8
|
+
> MUST implement this method or TypeScript will throw compilation errors.
|
|
9
|
+
|
|
10
|
+
## Architecture Overview
|
|
11
|
+
|
|
12
|
+
The SDK uses a **factory pattern** with abstract base classes for data source extensibility:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
AbstractDataSource (base class)
|
|
16
|
+
├── REQUIRED Contract (abstract methods - MUST implement):
|
|
17
|
+
│ ├── listFiles() - List available files
|
|
18
|
+
│ ├── downloadFile() - Download file content
|
|
19
|
+
│ ├── uploadFile() - Upload file ⚠️ **REQUIRED**
|
|
20
|
+
│ ├── deleteFile() - Delete file
|
|
21
|
+
│ ├── copyFileInternal() - Copy file
|
|
22
|
+
│ └── validateConnection() - Test connection
|
|
23
|
+
│
|
|
24
|
+
├── ⚠️ IMPORTANT:
|
|
25
|
+
│ uploadFile() is REQUIRED. Implementations without it will fail type checking.
|
|
26
|
+
│
|
|
27
|
+
├── TEMPLATE Methods (inherited - don't override):
|
|
28
|
+
│ ├── moveFile() - Uses copyFileInternal() + deleteFile()
|
|
29
|
+
│ └── archiveFile() - Uses moveFile() with timestamp
|
|
30
|
+
├── Built-in: Retry logic, connection caching, file filtering
|
|
31
|
+
└── Implementations extend this
|
|
32
|
+
|
|
33
|
+
DataSourceFactory (interface)
|
|
34
|
+
├── create(config, logger): AbstractDataSource
|
|
35
|
+
├── supports(type): boolean
|
|
36
|
+
└── getDefaultConfig(type): Partial<DataSourceConfig>
|
|
37
|
+
|
|
38
|
+
DataSourceRegistry (singleton)
|
|
39
|
+
├── Stores factories by type (S3_CSV, SFTP_CSV, etc.)
|
|
40
|
+
├── Creates instances via registered factories
|
|
41
|
+
└── Validates type support
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Current Implementations
|
|
45
|
+
|
|
46
|
+
| Data Source | File | Size | Types Supported |
|
|
47
|
+
|------------|------|------|----------------|
|
|
48
|
+
| **S3DataSource** | `s3-data-source.ts` | 33KB | S3_CSV, S3_JSON, S3_XML, S3_PARQUET |
|
|
49
|
+
| **SftpDataSource** | `sftp-data-source.ts` | 99KB | SFTP_CSV, SFTP_JSON, SFTP_XML, SFTP_PARQUET |
|
|
50
|
+
|
|
51
|
+
## Step-by-Step: Adding GCP Storage Data Source
|
|
52
|
+
|
|
53
|
+
### Step 1: Create Data Source Class
|
|
54
|
+
|
|
55
|
+
Create `src/data-sources/gcp-storage-data-source.ts`:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { AbstractDataSource, DataSourceFactory } from './abstract-data-source';
|
|
59
|
+
import { DataSourceConfig, FileMetadata, StructuredLogger } from '../types';
|
|
60
|
+
import { Storage } from '@google-cloud/storage';
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* GCP Storage configuration
|
|
64
|
+
*/
|
|
65
|
+
export interface GcpStorageConfig {
|
|
66
|
+
projectId: string;
|
|
67
|
+
keyFilename?: string; // Path to service account JSON
|
|
68
|
+
credentials?: object; // Or inline credentials
|
|
69
|
+
bucket: string;
|
|
70
|
+
prefix?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* GCP Storage Data Source Configuration
|
|
75
|
+
*/
|
|
76
|
+
export interface GcpStorageDataSourceConfig extends DataSourceConfig {
|
|
77
|
+
type: 'GCP_CSV' | 'GCP_JSON' | 'GCP_XML' | 'GCP_PARQUET';
|
|
78
|
+
gcpConfig: GcpStorageConfig;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* GCP Storage Data Source Implementation
|
|
83
|
+
*/
|
|
84
|
+
export class GcpStorageDataSource extends AbstractDataSource {
|
|
85
|
+
type = 'GCP_STORAGE';
|
|
86
|
+
private storage: Storage;
|
|
87
|
+
private bucket: string;
|
|
88
|
+
|
|
89
|
+
constructor(config: GcpStorageDataSourceConfig, logger: StructuredLogger) {
|
|
90
|
+
super(config, logger);
|
|
91
|
+
|
|
92
|
+
// Initialize GCP Storage client
|
|
93
|
+
this.storage = new Storage({
|
|
94
|
+
projectId: config.gcpConfig.projectId,
|
|
95
|
+
keyFilename: config.gcpConfig.keyFilename,
|
|
96
|
+
credentials: config.gcpConfig.credentials,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
this.bucket = config.gcpConfig.bucket;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* List files in GCP bucket
|
|
104
|
+
*/
|
|
105
|
+
async listFiles(params?: Record<string, unknown>): Promise<FileMetadata[]> {
|
|
106
|
+
try {
|
|
107
|
+
const prefix = params?.prefix as string | undefined;
|
|
108
|
+
const [files] = await this.storage.bucket(this.bucket).getFiles({ prefix });
|
|
109
|
+
|
|
110
|
+
return files.map(file => ({
|
|
111
|
+
name: file.name,
|
|
112
|
+
path: `gs://${this.bucket}/${file.name}`,
|
|
113
|
+
size: parseInt(file.metadata.size as string, 10),
|
|
114
|
+
lastModified: file.metadata.updated,
|
|
115
|
+
etag: file.metadata.etag,
|
|
116
|
+
}));
|
|
117
|
+
} catch (error) {
|
|
118
|
+
this.handleError('listFiles', error);
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Download file from GCP bucket
|
|
125
|
+
*/
|
|
126
|
+
async downloadFile(path: string, options?: Record<string, unknown>): Promise<string | Buffer> {
|
|
127
|
+
try {
|
|
128
|
+
const file = this.storage.bucket(this.bucket).file(path);
|
|
129
|
+
const [content] = await file.download();
|
|
130
|
+
|
|
131
|
+
if (options?.encoding === 'utf8') {
|
|
132
|
+
return content.toString('utf8');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return content;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
this.handleError('downloadFile', error);
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Upload file to GCP bucket
|
|
144
|
+
*
|
|
145
|
+
* REQUIRED by AbstractDataSource contract
|
|
146
|
+
*
|
|
147
|
+
* @param path Remote path in bucket
|
|
148
|
+
* @param content Content to upload (string or Buffer)
|
|
149
|
+
* @param options Optional upload parameters
|
|
150
|
+
*/
|
|
151
|
+
async uploadFile(
|
|
152
|
+
path: string,
|
|
153
|
+
content: Buffer | string,
|
|
154
|
+
options?: Record<string, unknown>
|
|
155
|
+
): Promise<void> {
|
|
156
|
+
try {
|
|
157
|
+
const file = this.storage.bucket(this.bucket).file(path);
|
|
158
|
+
await file.save(content, {
|
|
159
|
+
contentType: options?.contentType as string | undefined,
|
|
160
|
+
metadata: options?.metadata as Record<string, string> | undefined,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
this.logger.info('File uploaded to GCP', {
|
|
164
|
+
bucket: this.bucket,
|
|
165
|
+
path,
|
|
166
|
+
size: typeof content === 'string' ? content.length : content.length,
|
|
167
|
+
});
|
|
168
|
+
} catch (error) {
|
|
169
|
+
this.handleError('uploadFile', error);
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Delete file from GCP bucket
|
|
176
|
+
*
|
|
177
|
+
* REQUIRED by AbstractDataSource contract
|
|
178
|
+
*/
|
|
179
|
+
async deleteFile(path: string): Promise<void> {
|
|
180
|
+
try {
|
|
181
|
+
await this.storage.bucket(this.bucket).file(path).delete();
|
|
182
|
+
this.logger.info('File deleted from GCP', { bucket: this.bucket, path });
|
|
183
|
+
} catch (error) {
|
|
184
|
+
this.handleError('deleteFile', error);
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Copy file within GCP bucket (implements abstract method)
|
|
191
|
+
*
|
|
192
|
+
* REQUIRED by AbstractDataSource contract - used by moveFile() template method
|
|
193
|
+
*
|
|
194
|
+
* @param sourcePath Source file path
|
|
195
|
+
* @param destPath Destination file path
|
|
196
|
+
*/
|
|
197
|
+
async copyFileInternal(sourcePath: string, destPath: string): Promise<void> {
|
|
198
|
+
try {
|
|
199
|
+
const sourceFile = this.storage.bucket(this.bucket).file(sourcePath);
|
|
200
|
+
const destFile = this.storage.bucket(this.bucket).file(destPath);
|
|
201
|
+
|
|
202
|
+
await sourceFile.copy(destFile);
|
|
203
|
+
|
|
204
|
+
this.logger.info('File copied in GCP', {
|
|
205
|
+
bucket: this.bucket,
|
|
206
|
+
sourcePath,
|
|
207
|
+
destPath,
|
|
208
|
+
});
|
|
209
|
+
} catch (error) {
|
|
210
|
+
this.handleError('copyFileInternal', error);
|
|
211
|
+
throw error;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Validate GCP connection
|
|
217
|
+
*/
|
|
218
|
+
async validateConnection(): Promise<boolean> {
|
|
219
|
+
try {
|
|
220
|
+
const [exists] = await this.storage.bucket(this.bucket).exists();
|
|
221
|
+
return exists;
|
|
222
|
+
} catch (error) {
|
|
223
|
+
this.logger.error('GCP connection validation failed', error as Error);
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Validate GCP configuration
|
|
230
|
+
*/
|
|
231
|
+
protected validateConfig(config: DataSourceConfig): void {
|
|
232
|
+
super.validateConfig(config);
|
|
233
|
+
|
|
234
|
+
const gcpConfig = (config as GcpStorageDataSourceConfig).gcpConfig;
|
|
235
|
+
|
|
236
|
+
if (!gcpConfig.projectId) {
|
|
237
|
+
throw new Error('GCP project ID is required');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (!gcpConfig.bucket) {
|
|
241
|
+
throw new Error('GCP bucket name is required');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (!gcpConfig.keyFilename && !gcpConfig.credentials) {
|
|
245
|
+
throw new Error('Either keyFilename or credentials must be provided');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Cleanup resources
|
|
251
|
+
*/
|
|
252
|
+
async dispose(): Promise<void> {
|
|
253
|
+
await super.dispose();
|
|
254
|
+
// GCP Storage client doesn't require explicit disposal
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* GCP Storage Data Source Factory
|
|
260
|
+
*/
|
|
261
|
+
export class GcpStorageDataSourceFactory implements DataSourceFactory {
|
|
262
|
+
supports(type: string): boolean {
|
|
263
|
+
const supportedTypes = ['GCP_CSV', 'GCP_JSON', 'GCP_XML', 'GCP_PARQUET'];
|
|
264
|
+
return supportedTypes.includes(type.toUpperCase());
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
create(config: DataSourceConfig, logger: StructuredLogger): GcpStorageDataSource {
|
|
268
|
+
if (!this.supports(config.type)) {
|
|
269
|
+
throw new Error(`Factory does not support type: ${config.type}`);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return new GcpStorageDataSource(config as GcpStorageDataSourceConfig, logger);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
getDefaultConfig(_type: string): Partial<GcpStorageDataSourceConfig> {
|
|
276
|
+
return {
|
|
277
|
+
type: 'GCP_CSV',
|
|
278
|
+
gcpConfig: {
|
|
279
|
+
projectId: '',
|
|
280
|
+
bucket: '',
|
|
281
|
+
keyFilename: '',
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Step 2: Register Factory in Index
|
|
289
|
+
|
|
290
|
+
Update `src/data-sources/index.ts`:
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// Add exports
|
|
294
|
+
export { GcpStorageDataSource, GcpStorageDataSourceFactory } from './gcp-storage-data-source';
|
|
295
|
+
export type { GcpStorageDataSourceConfig } from './gcp-storage-data-source';
|
|
296
|
+
|
|
297
|
+
// Update initializeDataSources()
|
|
298
|
+
export function initializeDataSources(): void {
|
|
299
|
+
const registry = DataSourceRegistry.getInstance();
|
|
300
|
+
|
|
301
|
+
// Existing registrations...
|
|
302
|
+
registry.register('S3_CSV', new S3DataSourceFactory());
|
|
303
|
+
registry.register('SFTP_CSV', new SftpDataSourceFactory());
|
|
304
|
+
|
|
305
|
+
// NEW: Register GCP Storage
|
|
306
|
+
const gcpFactory = new GcpStorageDataSourceFactory();
|
|
307
|
+
registry.register('GCP_CSV', gcpFactory);
|
|
308
|
+
registry.register('GCP_JSON', gcpFactory);
|
|
309
|
+
registry.register('GCP_XML', gcpFactory);
|
|
310
|
+
registry.register('GCP_PARQUET', gcpFactory);
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Step 3: Add Types to SDK Types
|
|
315
|
+
|
|
316
|
+
Update `src/types/index.ts`:
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
export type DataSourceType =
|
|
320
|
+
| 'S3_CSV'
|
|
321
|
+
| 'S3_JSON'
|
|
322
|
+
| 'S3_XML'
|
|
323
|
+
| 'S3_PARQUET'
|
|
324
|
+
| 'SFTP_CSV'
|
|
325
|
+
| 'SFTP_JSON'
|
|
326
|
+
| 'SFTP_XML'
|
|
327
|
+
| 'SFTP_PARQUET'
|
|
328
|
+
| 'GCP_CSV' // NEW
|
|
329
|
+
| 'GCP_JSON' // NEW
|
|
330
|
+
| 'GCP_XML' // NEW
|
|
331
|
+
| 'GCP_PARQUET'; // NEW
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Step 4: Install Dependencies
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
npm install @google-cloud/storage
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Update `package.json`:
|
|
341
|
+
|
|
342
|
+
```json
|
|
343
|
+
{
|
|
344
|
+
"dependencies": {
|
|
345
|
+
"@google-cloud/storage": "^7.0.0"
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Step 5: Add Unit Tests
|
|
351
|
+
|
|
352
|
+
Create `tests/unit/data-sources/gcp-storage-data-source.test.ts`:
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
import { GcpStorageDataSource, GcpStorageDataSourceFactory } from '../../../src/data-sources/gcp-storage-data-source';
|
|
356
|
+
import { createConsoleLogger } from '../../../src/utils/logging';
|
|
357
|
+
|
|
358
|
+
describe('GcpStorageDataSource', () => {
|
|
359
|
+
const mockConfig = {
|
|
360
|
+
type: 'GCP_CSV' as const,
|
|
361
|
+
connectionId: 'test-gcp',
|
|
362
|
+
name: 'Test GCP Storage',
|
|
363
|
+
gcpConfig: {
|
|
364
|
+
projectId: 'test-project',
|
|
365
|
+
bucket: 'test-bucket',
|
|
366
|
+
credentials: { /* mock credentials */ },
|
|
367
|
+
},
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const logger = createConsoleLogger();
|
|
371
|
+
|
|
372
|
+
describe('Factory', () => {
|
|
373
|
+
it('should support GCP types', () => {
|
|
374
|
+
const factory = new GcpStorageDataSourceFactory();
|
|
375
|
+
expect(factory.supports('GCP_CSV')).toBe(true);
|
|
376
|
+
expect(factory.supports('GCP_JSON')).toBe(true);
|
|
377
|
+
expect(factory.supports('S3_CSV')).toBe(false);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
it('should create GCP data source instance', () => {
|
|
381
|
+
const factory = new GcpStorageDataSourceFactory();
|
|
382
|
+
const dataSource = factory.create(mockConfig, logger);
|
|
383
|
+
expect(dataSource).toBeInstanceOf(GcpStorageDataSource);
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
describe('Configuration Validation', () => {
|
|
388
|
+
it('should throw error if projectId missing', () => {
|
|
389
|
+
const invalidConfig = { ...mockConfig, gcpConfig: { ...mockConfig.gcpConfig, projectId: '' } };
|
|
390
|
+
expect(() => new GcpStorageDataSource(invalidConfig, logger)).toThrow('GCP project ID is required');
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it('should throw error if bucket missing', () => {
|
|
394
|
+
const invalidConfig = { ...mockConfig, gcpConfig: { ...mockConfig.gcpConfig, bucket: '' } };
|
|
395
|
+
expect(() => new GcpStorageDataSource(invalidConfig, logger)).toThrow('GCP bucket name is required');
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Step 6: Update Documentation
|
|
402
|
+
|
|
403
|
+
Create `docs/02-CORE-GUIDES/data-sources/gcp-storage.md`:
|
|
404
|
+
|
|
405
|
+
```markdown
|
|
406
|
+
# GCP Storage Data Source
|
|
407
|
+
|
|
408
|
+
Upload and download files from Google Cloud Platform Storage buckets.
|
|
409
|
+
|
|
410
|
+
## Installation
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
npm install @google-cloud/storage
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
## Configuration
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
import { GcpStorageDataSource } from '@fluentcommerce/fc-connect-sdk';
|
|
420
|
+
|
|
421
|
+
const gcpDataSource = new GcpStorageDataSource({
|
|
422
|
+
type: 'GCP_CSV',
|
|
423
|
+
connectionId: 'gcp-prod',
|
|
424
|
+
name: 'GCP Production Storage',
|
|
425
|
+
gcpConfig: {
|
|
426
|
+
projectId: 'my-project-id',
|
|
427
|
+
keyFilename: '/path/to/service-account.json',
|
|
428
|
+
bucket: 'my-bucket',
|
|
429
|
+
},
|
|
430
|
+
}, logger);
|
|
431
|
+
|
|
432
|
+
// List files
|
|
433
|
+
const files = await gcpDataSource.listFiles({ prefix: 'inventory/' });
|
|
434
|
+
|
|
435
|
+
// Download file
|
|
436
|
+
const content = await gcpDataSource.downloadFile('inventory/positions.csv');
|
|
437
|
+
|
|
438
|
+
// Upload file (REQUIRED method)
|
|
439
|
+
await gcpDataSource.uploadFile('output/file.csv', Buffer.from('data'), {
|
|
440
|
+
contentType: 'text/csv',
|
|
441
|
+
});
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
## Authentication Options
|
|
445
|
+
|
|
446
|
+
### Service Account Key File
|
|
447
|
+
|
|
448
|
+
```typescript
|
|
449
|
+
gcpConfig: {
|
|
450
|
+
projectId: 'my-project',
|
|
451
|
+
keyFilename: './service-account.json',
|
|
452
|
+
bucket: 'my-bucket',
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Inline Credentials
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
gcpConfig: {
|
|
460
|
+
projectId: 'my-project',
|
|
461
|
+
credentials: {
|
|
462
|
+
client_email: 'service@project.iam.gserviceaccount.com',
|
|
463
|
+
private_key: '-----BEGIN PRIVATE KEY-----\n...',
|
|
464
|
+
},
|
|
465
|
+
bucket: 'my-bucket',
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### Application Default Credentials (ADC)
|
|
470
|
+
|
|
471
|
+
When running in GCP (Cloud Run, Cloud Functions), credentials are automatic:
|
|
472
|
+
|
|
473
|
+
```typescript
|
|
474
|
+
gcpConfig: {
|
|
475
|
+
projectId: 'my-project',
|
|
476
|
+
bucket: 'my-bucket',
|
|
477
|
+
// keyFilename and credentials omitted - uses ADC
|
|
478
|
+
}
|
|
479
|
+
```
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## Step 7: Test Integration
|
|
483
|
+
|
|
484
|
+
```bash
|
|
485
|
+
# Run unit tests
|
|
486
|
+
npm test -- gcp-storage-data-source.test.ts
|
|
487
|
+
|
|
488
|
+
# Run integration tests (requires real GCP credentials)
|
|
489
|
+
npm run test:integration:gcp
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
## Adding Azure Blob Storage (Similar Pattern)
|
|
495
|
+
|
|
496
|
+
Follow the same steps for Azure:
|
|
497
|
+
|
|
498
|
+
1. Create `azure-blob-data-source.ts`
|
|
499
|
+
2. Implement `AzureBlobDataSource extends AbstractDataSource`
|
|
500
|
+
3. Implement `AzureBlobDataSourceFactory implements DataSourceFactory`
|
|
501
|
+
4. Register factory with types: `AZURE_CSV`, `AZURE_JSON`, etc.
|
|
502
|
+
5. Add `@azure/storage-blob` dependency
|
|
503
|
+
6. Add tests and documentation
|
|
504
|
+
|
|
505
|
+
**Key differences:**
|
|
506
|
+
- Use `BlobServiceClient` from `@azure/storage-blob`
|
|
507
|
+
- Authentication: connection strings, SAS tokens, or DefaultAzureCredential
|
|
508
|
+
- Storage structure: containers instead of buckets
|
|
509
|
+
|
|
510
|
+
---
|
|
511
|
+
|
|
512
|
+
## Factory Pattern Benefits
|
|
513
|
+
|
|
514
|
+
### ✅ Extensibility
|
|
515
|
+
Add new data sources without modifying existing code
|
|
516
|
+
|
|
517
|
+
### ✅ Type Safety
|
|
518
|
+
Each data source has strongly-typed config interfaces
|
|
519
|
+
|
|
520
|
+
### ✅ Consistency
|
|
521
|
+
All data sources share common operations via `AbstractDataSource`
|
|
522
|
+
|
|
523
|
+
### ✅ Testability
|
|
524
|
+
Easy to mock factories for unit tests
|
|
525
|
+
|
|
526
|
+
### ✅ Registry Management
|
|
527
|
+
Centralized registration and discovery of data sources
|
|
528
|
+
|
|
529
|
+
---
|
|
530
|
+
|
|
531
|
+
## Best Practices
|
|
532
|
+
|
|
533
|
+
### 1. Retry Logic
|
|
534
|
+
Use built-in retry utilities from `AbstractDataSource`:
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
async downloadFile(path: string): Promise<Buffer> {
|
|
538
|
+
return await this.getFileWithRetry(path, 3, 1000); // 3 retries, 1s delay
|
|
539
|
+
}
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### 2. Connection Caching
|
|
543
|
+
Cache clients to avoid repeated initialization:
|
|
544
|
+
|
|
545
|
+
```typescript
|
|
546
|
+
private getClient(): StorageClient {
|
|
547
|
+
const cached = this.getCachedConnection<StorageClient>('client');
|
|
548
|
+
if (cached) return cached;
|
|
549
|
+
|
|
550
|
+
const client = new StorageClient(this.config);
|
|
551
|
+
this.setCachedConnection('client', client);
|
|
552
|
+
return client;
|
|
553
|
+
}
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### 3. Cleanup Resources
|
|
557
|
+
Always implement `dispose()` for connection cleanup:
|
|
558
|
+
|
|
559
|
+
```typescript
|
|
560
|
+
async dispose(): Promise<void> {
|
|
561
|
+
await super.dispose();
|
|
562
|
+
await this.client?.close();
|
|
563
|
+
}
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
### 4. Error Handling
|
|
567
|
+
Use consistent error handling from base class:
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
try {
|
|
571
|
+
return await operation();
|
|
572
|
+
} catch (error) {
|
|
573
|
+
this.handleError('operationName', error);
|
|
574
|
+
throw error;
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### 5. Configuration Validation
|
|
579
|
+
Validate config in constructor:
|
|
580
|
+
|
|
581
|
+
```typescript
|
|
582
|
+
protected validateConfig(config: DataSourceConfig): void {
|
|
583
|
+
super.validateConfig(config); // Base validation
|
|
584
|
+
|
|
585
|
+
if (!config.customField) {
|
|
586
|
+
throw new DataSourceError('Custom field is required');
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
---
|
|
592
|
+
|
|
593
|
+
## Testing Your Data Source
|
|
594
|
+
|
|
595
|
+
### Unit Tests (Mock Client)
|
|
596
|
+
|
|
597
|
+
```typescript
|
|
598
|
+
jest.mock('@google-cloud/storage');
|
|
599
|
+
|
|
600
|
+
describe('GcpStorageDataSource', () => {
|
|
601
|
+
it('should list files', async () => {
|
|
602
|
+
const mockStorage = {
|
|
603
|
+
bucket: jest.fn().mockReturnValue({
|
|
604
|
+
getFiles: jest.fn().mockResolvedValue([mockFiles]),
|
|
605
|
+
}),
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
const dataSource = new GcpStorageDataSource(config, logger);
|
|
609
|
+
const files = await dataSource.listFiles();
|
|
610
|
+
expect(files).toHaveLength(3);
|
|
611
|
+
});
|
|
612
|
+
});
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
### Integration Tests (Real Credentials)
|
|
616
|
+
|
|
617
|
+
```typescript
|
|
618
|
+
describe('GcpStorageDataSource Integration', () => {
|
|
619
|
+
const realConfig = {
|
|
620
|
+
type: 'GCP_CSV' as const,
|
|
621
|
+
connectionId: 'test-gcp',
|
|
622
|
+
name: 'Test GCP',
|
|
623
|
+
gcpConfig: {
|
|
624
|
+
projectId: process.env.GCP_PROJECT_ID!,
|
|
625
|
+
keyFilename: process.env.GCP_KEY_FILE!,
|
|
626
|
+
bucket: process.env.GCP_TEST_BUCKET!,
|
|
627
|
+
},
|
|
628
|
+
};
|
|
629
|
+
|
|
630
|
+
it('should connect to real GCP bucket', async () => {
|
|
631
|
+
const dataSource = new GcpStorageDataSource(realConfig, logger);
|
|
632
|
+
const isValid = await dataSource.validateConnection();
|
|
633
|
+
expect(isValid).toBe(true);
|
|
634
|
+
});
|
|
635
|
+
});
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
---
|
|
639
|
+
|
|
640
|
+
## Summary
|
|
641
|
+
|
|
642
|
+
Adding a new data source requires:
|
|
643
|
+
|
|
644
|
+
1. ✅ Extend `AbstractDataSource`
|
|
645
|
+
2. ✅ Implement **4 required methods**:
|
|
646
|
+
- `listFiles()` - List available files
|
|
647
|
+
- `downloadFile()` - Download file content
|
|
648
|
+
- `uploadFile()` - **Upload file content (REQUIRED)**
|
|
649
|
+
- `validateConnection()` - Test connection
|
|
650
|
+
3. ✅ Implement `DataSourceFactory`
|
|
651
|
+
4. ✅ Register factory with type aliases
|
|
652
|
+
5. ✅ Add type definitions
|
|
653
|
+
6. ✅ Install dependencies
|
|
654
|
+
7. ✅ Write unit tests
|
|
655
|
+
8. ✅ Add documentation
|
|
656
|
+
9. ✅ Test integration
|
|
657
|
+
|
|
658
|
+
**Time to add new data source:** ~2-4 hours for experienced developers
|
|
659
|
+
|
|
660
|
+
**Maintenance cost:** Low - inherit retry, caching, filtering from base class
|
|
661
|
+
|
|
662
|
+
---
|
|
663
|
+
|
|
664
|
+
## ⚠️ IMPORTANT: uploadFile() is Mandatory
|
|
665
|
+
|
|
666
|
+
**`uploadFile()` is a required abstract method** in `AbstractDataSource`.
|
|
667
|
+
|
|
668
|
+
**Why?**
|
|
669
|
+
- All 13 extraction templates depend on upload functionality
|
|
670
|
+
- Extraction workflows must export data to S3/SFTP/GCP/Azure
|
|
671
|
+
- Ensures consistency across all data source implementations
|
|
672
|
+
|
|
673
|
+
**Signature:**
|
|
674
|
+
```typescript
|
|
675
|
+
abstract uploadFile(
|
|
676
|
+
path: string,
|
|
677
|
+
content: string | Buffer,
|
|
678
|
+
options?: Record<string, unknown>
|
|
679
|
+
): Promise<void>;
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
**Implementation Examples:**
|
|
683
|
+
- **S3**: Uses presigned PUT URLs
|
|
684
|
+
- **SFTP**: Uses ssh2-sftp-client with retry logic
|
|
685
|
+
- **GCP**: Uses `@google-cloud/storage` file.save()
|
|
686
|
+
- **Azure**: Uses `@azure/storage-blob` uploadData()
|