multiwoven-integrations 0.1.41 → 0.1.42

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82b67da3db5fd718642d785a6c88d95aab50098e900ace51d275839b0282ce1d
4
- data.tar.gz: 5e749c3149f853de00482ddb1899b622a062cf96b3ee22dfd428e0fa94a68ca9
3
+ metadata.gz: eee51b7ba03e877f2765da694f9ca7b4ede8e44e07ca74931d808f79fb828c06
4
+ data.tar.gz: 21a23a656e09175222172eea24e562c95ccc97e7bebe92443cc60678d68050bf
5
5
  SHA512:
6
- metadata.gz: 18fc7eb3472d27029851e6768cec57b9d1cf0c13dd462938a76d7ecc3770f041be0f5c5de3609d5270869358e5080af969bca7296ee11bfb41244b40aa05bcf5
7
- data.tar.gz: aaa27f548de6c20a6444644fe784ee708b7f6b8f9113812ab046d8b72ea161e114e16cc5d524a196aa479c707d3055143952658fd018a026e484905a2b30b7c4
6
+ metadata.gz: 388d743e298e3296fbd9bd12e5d29037d72bf4912f93ae8ae8b9d7f5285dbb2d39f39f1500f6ee3b6214e186564287eec8c3fe14d66f55cc53861585e3929e33
7
+ data.tar.gz: e527726e1e69c57c07d7d6ab28194f2a84dfbbffb941f61e2b5fca927cecf486edcb7fa2cecbbcc8ccc1713c396e1723161e5ea55f0cc8d310ce2d888f6de845
@@ -95,7 +95,8 @@ module Multiwoven
95
95
  request_rate_limit: stream_json["request_rate_limit"].to_i,
96
96
  request_rate_limit_unit: stream_json["request_rate_limit_unit"] || "minute",
97
97
  request_rate_concurrency: stream_json["request_rate_concurrency"].to_i,
98
- supported_sync_modes: stream_json["supported_sync_modes"]
98
+ supported_sync_modes: stream_json["supported_sync_modes"],
99
+ schema_mode: stream_json["schema_mode"]
99
100
  )
100
101
  end
101
102
  end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Multiwoven::Integrations::Destination
4
+ module Sftp
5
+ include Multiwoven::Integrations::Core
6
+ class Client < DestinationConnector
7
+ prepend Multiwoven::Integrations::Core::Fullrefresher
8
+ prepend Multiwoven::Integrations::Core::RateLimiter
9
+
10
+ def check_connection(connection_config)
11
+ connection_config = connection_config.with_indifferent_access
12
+ with_sftp_client(connection_config) do |sftp|
13
+ stream = SecureRandom.uuid
14
+ test_path = "/path/to/test/#{stream}"
15
+ test_file_operations(sftp, test_path)
16
+ return success_status
17
+ end
18
+ rescue StandardError => e
19
+ handle_exception("SFTP:CHECK_CONNECTION:EXCEPTION", "error", e)
20
+ failure_status(e)
21
+ end
22
+
23
+ def discover(_connection_config = nil)
24
+ catalog_json = read_json(CATALOG_SPEC_PATH)
25
+
26
+ catalog = build_catalog(catalog_json)
27
+
28
+ catalog.to_multiwoven_message
29
+ rescue StandardError => e
30
+ handle_exception(
31
+ "SFTP:DISCOVER:EXCEPTION",
32
+ "error",
33
+ e
34
+ )
35
+ end
36
+
37
+ def write(sync_config, records, _action = "insert")
38
+ connection_config = sync_config.destination.connection_specification.with_indifferent_access
39
+ file_path = generate_file_path(sync_config)
40
+ csv_content = generate_csv_content(records)
41
+ write_success = 0
42
+ write_failure = 0
43
+ # 10000 records in single
44
+ with_sftp_client(connection_config) do |sftp|
45
+ sftp.file.open(file_path, "w") { |file| file.puts(csv_content) }
46
+ write_success += records.size
47
+ rescue StandardError => e
48
+ handle_exception("SFTP:RECORD:WRITE:EXCEPTION", "error", e)
49
+ write_failure += records.size
50
+ end
51
+ tracking_message(write_success, write_failure)
52
+ rescue StandardError => e
53
+ handle_exception(
54
+ "SFTP:WRITE:EXCEPTION",
55
+ "error",
56
+ e
57
+ )
58
+ end
59
+
60
+ def clear_all_records(sync_config)
61
+ connection_specification = sync_config.destination.connection_specification.with_indifferent_access
62
+ with_sftp_client(connection_specification) do |sftp|
63
+ files = sftp.dir.glob(connection_specification[:destination_path], "*")
64
+
65
+ files.each do |file|
66
+ sftp.remove!(File.join(connection_specification[:destination_path], file.name))
67
+ end
68
+ if sftp.dir.entries(connection_specification[:destination_path]).size == 2
69
+ control_message("Successfully cleared data.", "succeeded")
70
+ else
71
+ control_message("Failed to clear data.", "failed")
72
+ end
73
+ end
74
+ rescue StandardError => e
75
+ control_message(e.message, "failed")
76
+ end
77
+
78
+ private
79
+
80
+ def generate_file_path(sync_config)
81
+ timestamp = Time.now.strftime("%Y%m%d-%H%M%S")
82
+ file_name = "#{sync_config.stream.name}_#{timestamp}.csv"
83
+ File.join(sync_config.destination.connection_specification[:destination_path], file_name)
84
+ end
85
+
86
+ def generate_csv_content(records)
87
+ CSV.generate do |csv|
88
+ headers = records.first.keys
89
+ csv << headers
90
+ records.each { |record| csv << record.values_at(*headers) }
91
+ end
92
+ end
93
+
94
+ def tracking_message(success, failure)
95
+ Multiwoven::Integrations::Protocol::TrackingMessage.new(
96
+ success: success, failed: failure
97
+ ).to_multiwoven_message
98
+ end
99
+
100
+ def with_sftp_client(connection_config, &block)
101
+ Net::SFTP.start(
102
+ connection_config[:host],
103
+ connection_config[:username],
104
+ password: connection_config[:password],
105
+ port: connection_config.fetch(:port, 22), &block
106
+ )
107
+ end
108
+
109
+ def test_file_operations(sftp, test_path)
110
+ sftp.file.open(test_path, "w") { |file| file.puts("connection_check") }
111
+ sftp.remove!(test_path)
112
+ end
113
+
114
+ def control_message(message, status)
115
+ ControlMessage.new(
116
+ type: "full_refresh",
117
+ emitted_at: Time.now.to_i,
118
+ status: ConnectionStatusType[status],
119
+ meta: { detail: message }
120
+ ).to_multiwoven_message
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,16 @@
1
+ {
2
+ "request_rate_limit": 600,
3
+ "request_rate_limit_unit": "minute",
4
+ "request_rate_concurrency": 10,
5
+ "streams": [
6
+ {
7
+ "name": "sftp",
8
+ "batch_support": true,
9
+ "batch_size": 10000,
10
+ "action": "create",
11
+ "schema_mode": ["schemaless"],
12
+ "json_schema": {},
13
+ "supported_sync_modes": ["full_refresh","incremental"]
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "data": {
3
+ "name": "Sftp",
4
+ "title": "SFTP",
5
+ "connector_type": "destination",
6
+ "connectorSubtype": "file",
7
+ "category": "File Storage",
8
+ "documentation_url": "https://docs.mutliwoven.com",
9
+ "github_issue_label": "destination-sftp",
10
+ "icon": "icon.svg",
11
+ "license": "MIT",
12
+ "release_stage": "alpha",
13
+ "support_level": "community",
14
+ "tags": ["language:ruby", "multiwoven"]
15
+ }
16
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "documentation_url": "https://docs.multiwoven.com/integrations/destination/klaviyo",
3
+ "stream_type": "static",
4
+ "connection_specification": {
5
+ "$schema": "http://json-schema.org/draft-07/schema#",
6
+ "title": "SFTP",
7
+ "required": ["host", "username", "password", "destination_path"],
8
+ "properties": {
9
+ "host": {
10
+ "title": "Host",
11
+ "description": "Hostname of the SFTP server.",
12
+ "type": "string",
13
+ "order": 0
14
+ },
15
+ "port": {
16
+ "title": "Port",
17
+ "description": "Port of the SFTP server.",
18
+ "type": "integer",
19
+ "minimum": 0,
20
+ "maximum": 65536,
21
+ "default": 22,
22
+ "order": 1
23
+ },
24
+ "username": {
25
+ "title": "User Name",
26
+ "description": "Username to use to access the SFTP server.",
27
+ "type": "string",
28
+ "order": 2
29
+ },
30
+ "password": {
31
+ "title": "Password",
32
+ "description": "Password associated with the username.",
33
+ "type": "string",
34
+ "order": 3
35
+ },
36
+ "destination_path": {
37
+ "title": "Destination path",
38
+ "type": "string",
39
+ "description": "Path to the directory where files will be written.",
40
+ "order": 4
41
+ }
42
+ }
43
+ }
44
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="250" height="250" fill="none"><g clip-path="url(#a)"><path fill="#615EFF" d="M200.745 218.706a12.051 12.051 0 0 1-3.483 8.475 11.837 11.837 0 0 1-8.4 3.514H62.072c-3.15 0-6.173-1.261-8.403-3.507a12.053 12.053 0 0 1-3.49-8.472V31.485a12.08 12.08 0 0 1 .903-4.593 11.996 11.996 0 0 1 2.578-3.894 11.875 11.875 0 0 1 3.86-2.6 11.791 11.791 0 0 1 4.552-.912h81.371l57.302 58.96v140.26Z"/><path fill="#fff" d="M83.868 156.832c-.142-1.429-.75-2.539-1.822-3.33-1.074-.792-2.53-1.187-4.37-1.187-1.25 0-2.305.177-3.166.531-.861.343-1.522.821-1.981 1.435a3.457 3.457 0 0 0-.673 2.09c-.023.65.112 1.217.407 1.701.307.484.725.903 1.256 1.258.53.342 1.144.643 1.84.903a19.02 19.02 0 0 0 2.229.638l3.255.779c1.58.354 3.03.827 4.352 1.417 1.32.591 2.464 1.317 3.431 2.179a9.057 9.057 0 0 1 2.247 3.047c.542 1.169.82 2.509.831 4.021-.011 2.22-.578 4.145-1.698 5.775-1.109 1.617-2.712 2.875-4.811 3.773-2.088.885-4.606 1.328-7.554 1.328-2.925 0-5.472-.449-7.642-1.346-2.158-.898-3.845-2.226-5.06-3.986-1.202-1.771-1.833-3.962-1.892-6.572h7.412c.082 1.217.43 2.232 1.044 3.047.625.803 1.456 1.411 2.494 1.825 1.05.401 2.235.602 3.555.602 1.298 0 2.424-.189 3.38-.567.966-.378 1.715-.903 2.246-1.576.53-.673.796-1.447.796-2.321 0-.815-.242-1.5-.725-2.055-.472-.555-1.168-1.027-2.088-1.417-.908-.39-2.022-.744-3.343-1.063l-3.945-.992c-3.054-.744-5.466-1.907-7.235-3.489-1.77-1.583-2.648-3.714-2.636-6.395-.012-2.196.572-4.116 1.751-5.757 1.192-1.641 2.825-2.923 4.9-3.844 2.076-.921 4.435-1.382 7.076-1.382 2.69 0 5.036.461 7.04 1.382 2.018.921 3.586 2.203 4.706 3.844 1.12 1.641 1.699 3.543 1.734 5.704h-7.341Zm12.988 25.844v-36.278h23.988v6.324h-16.328v8.645h14.736v6.324h-14.736v14.985h-7.66Zm27.76-29.954v-6.324h29.754v6.324h-11.091v29.954h-7.571v-29.954h-11.092Zm34.654 29.954v-36.278h14.294c2.748 0 5.089.526 7.023 1.577 1.934 1.039 3.408 2.486 4.422 4.34 1.026 1.842 1.539 3.968 1.539 6.377s-.519 4.535-1.557 6.377c-1.037 1.842-2.541 3.277-4.51 4.304-1.958 1.028-4.329 1.541-7.112 1.541h-9.11v-6.146h7.872c1.474 0 2.689-.254 3.644-.762.967-.52 1.686-1.234 2.158-2.143.484-.921.725-1.978.725-3.171 0-1.205-.241-2.256-.725-3.153-.472-.91-1.191-1.612-2.158-2.108-.967-.508-2.194-.762-3.679-.762h-5.166v30.007h-7.66Z"/><path fill="#1A194D" d="m149.75 76.907 50.996 49.177V78.101h-45.173a11.33 11.33 0 0 1-5.643-1.433l-.18.24Z" opacity=".3"/><path fill="#C5C4FF" d="M200.746 78.35h-45.297a11.836 11.836 0 0 1-8.399-3.514 12.055 12.055 0 0 1-3.484-8.475v-47.2l57.18 59.189Z"/></g><defs><clipPath id="a"><path fill="#fff" d="M50 19h151v212H50z"/></clipPath></defs></svg>
@@ -24,6 +24,7 @@ module Multiwoven
24
24
  )
25
25
  LogLevel = Types::String.enum("fatal", "error", "warn", "info", "debug", "trace")
26
26
  RequestRateLimitingUnit = Types::String.default("minute").enum("minute", "hour", "day")
27
+ SchemaMode = Types::String.enum("schema", "schemaless")
27
28
 
28
29
  class ProtocolModel < Dry::Struct
29
30
  extend Multiwoven::Integrations::Core::Utils
@@ -124,6 +125,7 @@ module Multiwoven
124
125
  attribute? :request_rate_limit, Types::Integer
125
126
  attribute? :request_rate_limit_unit, RequestRateLimitingUnit
126
127
  attribute? :request_rate_concurrency, Types::Integer
128
+ attribute? :schema_mode, Types::Array.of(SchemaMode).optional.default(["schema"])
127
129
 
128
130
  def rate_limit_unit_seconds
129
131
  case request_rate_limit_unit
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Multiwoven
4
4
  module Integrations
5
- VERSION = "0.1.41"
5
+ VERSION = "0.1.42"
6
6
 
7
7
  ENABLED_SOURCES = %w[
8
8
  Snowflake
@@ -23,6 +23,7 @@ module Multiwoven
23
23
  Airtable
24
24
  Stripe
25
25
  SalesforceConsumerGoodsCloud
26
+ Sftp
26
27
  ].freeze
27
28
  end
28
29
  end
@@ -19,6 +19,9 @@ require "hubspot-api-client"
19
19
  require "google/apis/sheets_v4"
20
20
  require "stringio"
21
21
  require "stripe"
22
+ require "net/sftp"
23
+ require "csv"
24
+ require "securerandom"
22
25
 
23
26
  # Service
24
27
  require_relative "integrations/config"
@@ -54,6 +57,7 @@ require_relative "integrations/destination/google_sheets/client"
54
57
  require_relative "integrations/destination/airtable/client"
55
58
  require_relative "integrations/destination/stripe/client"
56
59
  require_relative "integrations/destination/salesforce_consumer_goods_cloud/client"
60
+ require_relative "integrations/destination/sftp/client"
57
61
 
58
62
  module Multiwoven
59
63
  module Integrations
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: multiwoven-integrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.41
4
+ version: 0.1.42
5
5
  platform: ruby
6
6
  authors:
7
7
  - Subin T P
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-03-24 00:00:00.000000000 Z
11
+ date: 2024-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: csv
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: dry-schema
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +150,20 @@ dependencies:
136
150
  - - ">="
137
151
  - !ruby/object:Gem::Version
138
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: net-sftp
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
139
167
  - !ruby/object:Gem::Dependency
140
168
  name: pg
141
169
  requirement: !ruby/object:Gem::Requirement
@@ -395,6 +423,11 @@ files:
395
423
  - lib/multiwoven/integrations/destination/salesforce_crm/config/meta.json
396
424
  - lib/multiwoven/integrations/destination/salesforce_crm/config/spec.json
397
425
  - lib/multiwoven/integrations/destination/salesforce_crm/icon.svg
426
+ - lib/multiwoven/integrations/destination/sftp/client.rb
427
+ - lib/multiwoven/integrations/destination/sftp/config/catalog.json
428
+ - lib/multiwoven/integrations/destination/sftp/config/meta.json
429
+ - lib/multiwoven/integrations/destination/sftp/config/spec.json
430
+ - lib/multiwoven/integrations/destination/sftp/icon.svg
398
431
  - lib/multiwoven/integrations/destination/slack/client.rb
399
432
  - lib/multiwoven/integrations/destination/slack/config/catalog.json
400
433
  - lib/multiwoven/integrations/destination/slack/config/meta.json