anvil-ruby 0.1.0

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.
@@ -0,0 +1,220 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Anvil E-Signature Quickstart
5
+ # Based on: https://www.useanvil.com/docs/api/e-signatures
6
+
7
+ $LOAD_PATH.unshift File.expand_path('lib', __dir__)
8
+ require 'anvil'
9
+ require 'anvil/env_loader'
10
+
11
+ # Load .env file
12
+ Anvil::EnvLoader.load(File.expand_path('.env', __dir__))
13
+
14
+ # Configure Anvil
15
+ Anvil.configure do |config|
16
+ config.api_key = ENV.fetch('ANVIL_API_KEY', nil)
17
+ config.environment = :development
18
+ end
19
+
20
+ puts '=' * 50
21
+ puts 'Anvil E-Signature Quickstart'
22
+ puts '=' * 50
23
+ puts "\nUsing API Key: #{ENV.fetch('ANVIL_API_KEY', nil)[0..10]}..."
24
+
25
+ # Since the Signature class uses GraphQL, we need to test it differently
26
+ # Let's create a test packet using the REST API directly
27
+
28
+ def create_test_etch_packet
29
+ puts "\nšŸ“ Creating a test e-signature packet..."
30
+
31
+ client = Anvil::Client.new
32
+
33
+ # GraphQL mutation for creating an Etch packet
34
+ # Note: This creates a simple test packet without files
35
+ mutation = <<~GRAPHQL
36
+ mutation CreateEtchPacket {
37
+ createEtchPacket(
38
+ name: "Test Agreement - Ruby Gem #{Time.now.to_i}",
39
+ isDraft: false,
40
+ signers: [
41
+ {
42
+ name: "Test Signer 1",
43
+ email: "test1@example.com",
44
+ signerType: "email"
45
+ }
46
+ ]
47
+ ) {
48
+ eid
49
+ name
50
+ status
51
+ createdAt
52
+ signers {
53
+ eid
54
+ name
55
+ email
56
+ status
57
+ }
58
+ }
59
+ }
60
+ GRAPHQL
61
+
62
+ begin
63
+ response = client.post('https://app.useanvil.com/graphql', {
64
+ query: mutation
65
+ })
66
+
67
+ if response.success?
68
+ data = response.data
69
+ if data[:data] && data[:data][:createEtchPacket]
70
+ packet = data[:data][:createEtchPacket]
71
+
72
+ puts 'āœ… Signature packet created successfully!'
73
+ puts "\nšŸ“‹ Packet Details:"
74
+ puts " EID: #{packet[:eid]}"
75
+ puts " Name: #{packet[:name]}"
76
+ puts " Status: #{packet[:status]}"
77
+ puts " Created: #{packet[:createdAt]}"
78
+
79
+ if packet[:signers]
80
+ puts "\nšŸ‘„ Signers:"
81
+ packet[:signers].each do |signer|
82
+ puts " - #{signer[:name]} (#{signer[:email]})"
83
+ puts " Status: #{signer[:status]}"
84
+ puts " EID: #{signer[:eid]}"
85
+ end
86
+ end
87
+
88
+ # Get signing URL
89
+ generate_signing_url(packet[:eid], packet[:signers].first[:eid])
90
+
91
+ packet
92
+ else
93
+ puts 'āŒ No packet data returned'
94
+ puts "Response: #{data.inspect}"
95
+ end
96
+ else
97
+ puts "āŒ Request failed: #{response.error_message}"
98
+ end
99
+ rescue StandardError => e
100
+ puts "āŒ Error: #{e.message}"
101
+ puts e.backtrace.first(5)
102
+ end
103
+ end
104
+
105
+ def generate_signing_url(packet_eid, signer_eid)
106
+ puts "\nšŸ”— Generating signing URL..."
107
+
108
+ client = Anvil::Client.new
109
+
110
+ mutation = <<~GRAPHQL
111
+ mutation GenerateEtchSignURL {
112
+ generateEtchSignURL(
113
+ input: {
114
+ packetEid: "#{packet_eid}"
115
+ signerEid: "#{signer_eid}"
116
+ }
117
+ ) {
118
+ url
119
+ }
120
+ }
121
+ GRAPHQL
122
+
123
+ begin
124
+ response = client.post('https://app.useanvil.com/graphql', {
125
+ query: mutation
126
+ })
127
+
128
+ if response.success?
129
+ data = response.data
130
+ if data[:data] && data[:data][:generateEtchSignURL]
131
+ url = data[:data][:generateEtchSignURL][:url]
132
+ puts 'āœ… Signing URL generated:'
133
+ puts " #{url}"
134
+ puts "\nšŸ“§ Send this URL to the signer to collect their signature"
135
+ url
136
+ else
137
+ puts 'āŒ No URL returned'
138
+ end
139
+ else
140
+ puts "āŒ Failed to generate URL: #{response.error_message}"
141
+ end
142
+ rescue StandardError => e
143
+ puts "āŒ Error: #{e.message}"
144
+ end
145
+ end
146
+
147
+ def list_etch_packets
148
+ puts "\nšŸ“‘ Listing your signature packets..."
149
+
150
+ client = Anvil::Client.new
151
+
152
+ query = <<~GRAPHQL
153
+ query ListEtchPackets {
154
+ etchPackets(limit: 5) {
155
+ eid
156
+ name
157
+ status
158
+ createdAt
159
+ completedAt
160
+ }
161
+ }
162
+ GRAPHQL
163
+
164
+ begin
165
+ response = client.post('https://app.useanvil.com/graphql', {
166
+ query: query
167
+ })
168
+
169
+ if response.success?
170
+ data = response.data
171
+ if data[:data] && data[:data][:etchPackets]
172
+ packets = data[:data][:etchPackets]
173
+
174
+ if packets.empty?
175
+ puts 'No signature packets found'
176
+ else
177
+ puts "Found #{packets.length} packet(s):"
178
+ packets.each do |packet|
179
+ puts "\n šŸ“‹ #{packet[:name]}"
180
+ puts " EID: #{packet[:eid]}"
181
+ puts " Status: #{packet[:status]}"
182
+ puts " Created: #{packet[:createdAt]}"
183
+ puts " Completed: #{packet[:completedAt] || 'Not yet'}"
184
+ end
185
+ end
186
+ end
187
+ else
188
+ puts "āŒ Failed to list packets: #{response.error_message}"
189
+ end
190
+ rescue StandardError => e
191
+ puts "āŒ Error: #{e.message}"
192
+ end
193
+ end
194
+
195
+ # Main execution
196
+ puts "\nšŸš€ Testing Anvil E-Signature API..."
197
+
198
+ # List existing packets
199
+ list_etch_packets
200
+
201
+ # Create a new test packet
202
+ create_test_etch_packet
203
+
204
+ puts "\n#{'=' * 50}"
205
+ puts 'āœ… E-Signature API test complete!'
206
+ puts '=' * 50
207
+
208
+ puts "\nšŸ“š What just happened:"
209
+ puts '1. Created a signature packet with the Anvil API'
210
+ puts '2. Added a test signer'
211
+ puts '3. Generated a signing URL'
212
+
213
+ puts "\nšŸ’” Next steps:"
214
+ puts '1. The signer would receive the URL via email (in production)'
215
+ puts '2. They click the link and sign the document'
216
+ puts '3. You receive a webhook when complete'
217
+ puts '4. You can download the signed document'
218
+
219
+ puts "\nšŸ“– Learn more:"
220
+ puts ' https://www.useanvil.com/docs/api/e-signatures'
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Test Anvil API connection and endpoints
5
+
6
+ $LOAD_PATH.unshift File.expand_path('lib', __dir__)
7
+ require 'anvil'
8
+ require 'anvil/env_loader'
9
+ require 'net/http'
10
+ require 'uri'
11
+ require 'json'
12
+
13
+ # Load .env file
14
+ Anvil::EnvLoader.load(File.expand_path('.env', __dir__))
15
+
16
+ puts '=' * 50
17
+ puts 'Anvil API Connection Test'
18
+ puts '=' * 50
19
+
20
+ api_key = ENV.fetch('ANVIL_API_KEY', nil)
21
+ puts "\nUsing API Key: #{api_key[0..10]}..."
22
+
23
+ # Test 1: Direct REST API call (we know this works)
24
+ def test_rest_api(api_key)
25
+ puts "\n1ļøāƒ£ Testing REST API (PDF Generation)..."
26
+
27
+ uri = URI('https://app.useanvil.com/api/v1/generate-pdf')
28
+ http = Net::HTTP.new(uri.host, uri.port)
29
+ http.use_ssl = true
30
+
31
+ request = Net::HTTP::Post.new(uri.path)
32
+ request.basic_auth(api_key, '')
33
+ request['Content-Type'] = 'application/json'
34
+ request.body = {
35
+ type: 'markdown',
36
+ data: [{ content: '# Test\nThis is a test.' }]
37
+ }.to_json
38
+
39
+ response = http.request(request)
40
+
41
+ if response.code == '200'
42
+ puts ' āœ… REST API works! (PDF generated)'
43
+ true
44
+ else
45
+ puts " āŒ REST API failed: #{response.code}"
46
+ puts " Response: #{response.body[0..200]}"
47
+ false
48
+ end
49
+ rescue StandardError => e
50
+ puts " āŒ Error: #{e.message}"
51
+ false
52
+ end
53
+
54
+ # Test 2: GraphQL API
55
+ def test_graphql_api(api_key)
56
+ puts "\n2ļøāƒ£ Testing GraphQL API..."
57
+
58
+ uri = URI('https://app.useanvil.com/graphql')
59
+ http = Net::HTTP.new(uri.host, uri.port)
60
+ http.use_ssl = true
61
+
62
+ request = Net::HTTP::Post.new(uri.path)
63
+ request.basic_auth(api_key, '')
64
+ request['Content-Type'] = 'application/json'
65
+
66
+ # Simple query to test GraphQL
67
+ query = {
68
+ query: <<~GRAPHQL
69
+ query {
70
+ currentUser {
71
+ eid
72
+ name
73
+ }
74
+ }
75
+ GRAPHQL
76
+ }.to_json
77
+
78
+ request.body = query
79
+
80
+ response = http.request(request)
81
+
82
+ if response.code == '200'
83
+ data = JSON.parse(response.body)
84
+ if data['data']
85
+ puts ' āœ… GraphQL API works!'
86
+ puts " User: #{data['data']['currentUser']}"
87
+ true
88
+ else
89
+ puts ' āš ļø GraphQL responded but no data'
90
+ puts " Response: #{response.body[0..200]}"
91
+ false
92
+ end
93
+ else
94
+ puts " āŒ GraphQL API failed: #{response.code}"
95
+ puts " Response: #{response.body[0..200]}"
96
+ false
97
+ end
98
+ rescue StandardError => e
99
+ puts " āŒ Error: #{e.message}"
100
+ false
101
+ end
102
+
103
+ # Test 3: Using the Ruby gem client
104
+ def test_gem_client(api_key)
105
+ puts "\n3ļøāƒ£ Testing Ruby Gem Client..."
106
+
107
+ Anvil.configure do |config|
108
+ config.api_key = api_key
109
+ config.environment = :development
110
+ end
111
+
112
+ # Test PDF generation (we know this works)
113
+ Anvil::PDF.generate_from_markdown('# Test Document')
114
+ puts ' āœ… Gem client works! (PDF generated)'
115
+ true
116
+ rescue StandardError => e
117
+ puts " āŒ Gem client error: #{e.message}"
118
+ false
119
+ end
120
+
121
+ # Run all tests
122
+ rest_ok = test_rest_api(api_key)
123
+ graphql_ok = test_graphql_api(api_key)
124
+ gem_ok = test_gem_client(api_key)
125
+
126
+ puts "\n#{'=' * 50}"
127
+ puts 'Test Results:'
128
+ puts '=' * 50
129
+ puts "REST API: #{rest_ok ? 'āœ…' : 'āŒ'}"
130
+ puts "GraphQL API: #{graphql_ok ? 'āœ…' : 'āŒ'}"
131
+ puts "Ruby Gem: #{gem_ok ? 'āœ…' : 'āŒ'}"
132
+
133
+ if graphql_ok
134
+ puts "\nāœ… GraphQL is working! We can proceed with e-signatures."
135
+ else
136
+ puts "\nāš ļø GraphQL is not working. E-signatures require GraphQL."
137
+ puts "\nPossible issues:"
138
+ puts '1. GraphQL might require a different authentication method'
139
+ puts '2. The endpoint might be different'
140
+ puts '3. Your account might not have GraphQL access'
141
+ puts "\nšŸ’” Try the REST API e-signature endpoints instead:"
142
+ puts ' POST https://app.useanvil.com/api/v1/etch-packets'
143
+ end
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Create an Anvil Etch E-Signature Packet
5
+ # Using the correct GraphQL endpoint and mutation structure
6
+
7
+ $LOAD_PATH.unshift File.expand_path('lib', __dir__)
8
+ require 'anvil'
9
+ require 'anvil/env_loader'
10
+ require 'net/http'
11
+ require 'uri'
12
+ require 'json'
13
+
14
+ # Load .env file
15
+ Anvil::EnvLoader.load(File.expand_path('.env', __dir__))
16
+
17
+ puts '=' * 50
18
+ puts 'šŸ–Šļø Anvil Etch E-Signature Test'
19
+ puts '=' * 50
20
+
21
+ api_key = ENV.fetch('ANVIL_API_KEY', nil)
22
+ puts "\nUsing API Key: #{api_key[0..10]}..."
23
+
24
+ # Test 1: Basic GraphQL query to verify connection
25
+ def test_graphql_connection(api_key)
26
+ puts "\n1ļøāƒ£ Testing GraphQL connection..."
27
+
28
+ uri = URI('https://graphql.useanvil.com/')
29
+ http = Net::HTTP.new(uri.host, uri.port)
30
+ http.use_ssl = true
31
+
32
+ request = Net::HTTP::Post.new(uri.path || '/')
33
+ request.basic_auth(api_key, '')
34
+ request['Content-Type'] = 'application/json'
35
+
36
+ query = {
37
+ query: <<~GRAPHQL
38
+ query {
39
+ currentUser {
40
+ eid
41
+ name
42
+ }
43
+ }
44
+ GRAPHQL
45
+ }
46
+
47
+ request.body = query.to_json
48
+ response = http.request(request)
49
+
50
+ if response.code == '200'
51
+ data = JSON.parse(response.body)
52
+ if data['data']
53
+ puts ' āœ… GraphQL connection works!'
54
+ puts " User: #{data['data']['currentUser']}"
55
+ return true
56
+ end
57
+ end
58
+
59
+ puts " āŒ GraphQL connection failed: #{response.code}"
60
+ puts " Response: #{response.body[0..200]}"
61
+ false
62
+ rescue StandardError => e
63
+ puts " āŒ Error: #{e.message}"
64
+ false
65
+ end
66
+
67
+ # Test 2: Create a simple Etch packet (without a template for now)
68
+ def create_simple_etch_packet(api_key)
69
+ puts "\n2ļøāƒ£ Creating a simple Etch packet..."
70
+
71
+ uri = URI('https://graphql.useanvil.com/')
72
+ http = Net::HTTP.new(uri.host, uri.port)
73
+ http.use_ssl = true
74
+
75
+ request = Net::HTTP::Post.new(uri.path || '/')
76
+ request.basic_auth(api_key, '')
77
+ request['Content-Type'] = 'application/json'
78
+
79
+ # Simple mutation - create a draft packet
80
+ mutation = {
81
+ query: <<~GRAPHQL
82
+ mutation CreateTestPacket {
83
+ createEtchPacket(
84
+ name: "Test Signature Packet #{Time.now.to_i}"
85
+ isDraft: true
86
+ isTest: true
87
+ signers: [
88
+ {
89
+ id: "signer1"
90
+ name: "Test Signer"
91
+ email: "test@example.com"
92
+ signerType: "email"
93
+ }
94
+ ]
95
+ ) {
96
+ eid
97
+ name
98
+ status
99
+ createdAt
100
+ }
101
+ }
102
+ GRAPHQL
103
+ }
104
+
105
+ request.body = mutation.to_json
106
+ response = http.request(request)
107
+ result = JSON.parse(response.body)
108
+
109
+ if response.code == '200'
110
+ if result['data'] && result['data']['createEtchPacket']
111
+ packet = result['data']['createEtchPacket']
112
+ puts ' āœ… Etch packet created!'
113
+ puts " EID: #{packet['eid']}"
114
+ puts " Name: #{packet['name']}"
115
+ puts " Status: #{packet['status']}"
116
+ return packet
117
+ elsif result['errors']
118
+ puts ' āŒ GraphQL errors:'
119
+ result['errors'].each do |error|
120
+ puts " - #{error['message']}"
121
+ end
122
+ end
123
+ else
124
+ puts " āŒ Request failed: #{response.code}"
125
+ puts " Response: #{result}"
126
+ end
127
+
128
+ nil
129
+ rescue StandardError => e
130
+ puts " āŒ Error: #{e.message}"
131
+ nil
132
+ end
133
+
134
+ # Test 3: List existing Etch packets
135
+ def list_etch_packets(api_key)
136
+ puts "\n3ļøāƒ£ Listing existing Etch packets..."
137
+
138
+ uri = URI('https://graphql.useanvil.com/')
139
+ http = Net::HTTP.new(uri.host, uri.port)
140
+ http.use_ssl = true
141
+
142
+ request = Net::HTTP::Post.new(uri.path || '/')
143
+ request.basic_auth(api_key, '')
144
+ request['Content-Type'] = 'application/json'
145
+
146
+ query = {
147
+ query: <<~GRAPHQL
148
+ query {
149
+ etchPackets(limit: 5) {
150
+ eid
151
+ name
152
+ status
153
+ createdAt
154
+ }
155
+ }
156
+ GRAPHQL
157
+ }
158
+
159
+ request.body = query.to_json
160
+ response = http.request(request)
161
+
162
+ if response.code == '200'
163
+ data = JSON.parse(response.body)
164
+ if data['data'] && data['data']['etchPackets']
165
+ packets = data['data']['etchPackets']
166
+ if packets.empty?
167
+ puts ' No Etch packets found'
168
+ else
169
+ puts " Found #{packets.length} packet(s):"
170
+ packets.each do |p|
171
+ puts " - #{p['name']} (#{p['status']})"
172
+ end
173
+ end
174
+ return true
175
+ end
176
+ end
177
+
178
+ puts ' āŒ Failed to list packets'
179
+ false
180
+ rescue StandardError => e
181
+ puts " āŒ Error: #{e.message}"
182
+ false
183
+ end
184
+
185
+ # Main execution
186
+ puts "\nšŸš€ Starting Etch e-signature tests..."
187
+
188
+ # Test GraphQL connection
189
+ if test_graphql_connection(api_key)
190
+ # Try to list existing packets
191
+ list_etch_packets(api_key)
192
+
193
+ # Try to create a new packet
194
+ packet = create_simple_etch_packet(api_key)
195
+
196
+ if packet
197
+ puts "\n#{'=' * 50}"
198
+ puts 'āœ… Success!'
199
+ puts '=' * 50
200
+ puts "\nYou've successfully created an Etch signature packet!"
201
+ puts "\nPacket ID: #{packet['eid']}"
202
+ puts "Status: #{packet['status']}"
203
+
204
+ puts "\nšŸ“š Next steps:"
205
+ puts '1. Add a PDF template or upload a document'
206
+ puts '2. Configure signature fields'
207
+ puts '3. Send to signers'
208
+ puts '4. Track signature progress'
209
+
210
+ puts "\nšŸ’” To use with a PDF template:"
211
+ puts '1. Upload a PDF template at https://app.useanvil.com'
212
+ puts "2. Get the template's castEid"
213
+ puts '3. Include it in the createEtchPacket mutation:'
214
+ puts ' files: [{ id: "file1", castEid: "your_template_eid" }]'
215
+ else
216
+ puts "\nāš ļø Couldn't create a packet, but connection works!"
217
+ puts "\nThis might be because:"
218
+ puts '1. Your account might require a PDF file/template'
219
+ puts '2. Additional fields might be required'
220
+ puts '3. Check the Anvil dashboard for more details'
221
+ end
222
+ else
223
+ puts "\nāŒ GraphQL connection failed"
224
+ puts "\nPlease check:"
225
+ puts '1. Your API key is correct'
226
+ puts '2. Your account has API access enabled'
227
+ puts '3. The GraphQL endpoint is accessible'
228
+ end
229
+
230
+ puts "\nšŸ“– Documentation: https://www.useanvil.com/docs/api/e-signatures"
data/test_gem.rb ADDED
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Quick test script for the Anvil gem
5
+
6
+ $LOAD_PATH.unshift File.expand_path('lib', __dir__)
7
+ require 'anvil'
8
+ require 'anvil/env_loader'
9
+
10
+ # Load .env file
11
+ Anvil::EnvLoader.load(File.expand_path('.env', __dir__))
12
+
13
+ # Configure Anvil (will use ANVIL_API_KEY from .env file)
14
+ Anvil.configure do |config|
15
+ config.api_key = ENV['ANVIL_API_KEY'] || 'YOUR_API_KEY_HERE'
16
+ config.environment = :development
17
+ end
18
+
19
+ puts '=' * 50
20
+ puts 'Testing Anvil Ruby Gem'
21
+ puts '=' * 50
22
+
23
+ begin
24
+ # Test 1: Generate a simple PDF from Markdown
25
+ puts "\nšŸ“„ Generating PDF from Markdown..."
26
+
27
+ pdf = Anvil::PDF.generate_from_markdown(<<~MD
28
+ # Anvil Ruby Test
29
+
30
+ This is a test of the Anvil Ruby gem!
31
+
32
+ ## Features Working
33
+
34
+ - āœ… API Configuration
35
+ - āœ… PDF Generation
36
+ - āœ… Zero dependencies
37
+
38
+ Generated at: #{Time.now}
39
+ MD
40
+ )
41
+
42
+ filename = "test_output_#{Time.now.to_i}.pdf"
43
+ pdf.save_as(filename)
44
+
45
+ puts "āœ… Success! PDF saved as: #{filename}"
46
+ puts "šŸ“ Size: #{pdf.size_human}"
47
+
48
+ # Test 2: Generate from HTML
49
+ puts "\nšŸ“„ Generating PDF from HTML..."
50
+
51
+ pdf2 = Anvil::PDF.generate_from_html(
52
+ html: '<h1>Hello from Ruby!</h1><p>The Anvil gem is working!</p>',
53
+ css: 'h1 { color: #007bff; }',
54
+ title: 'Test PDF'
55
+ )
56
+
57
+ filename2 = "test_html_#{Time.now.to_i}.pdf"
58
+ pdf2.save_as(filename2)
59
+
60
+ puts "āœ… Success! HTML PDF saved as: #{filename2}"
61
+ puts "šŸ“ Size: #{pdf2.size_human}"
62
+
63
+ puts "\nšŸŽ‰ All tests passed! Your Anvil Ruby gem is working!"
64
+ rescue Anvil::AuthenticationError => e
65
+ puts "āŒ Authentication failed: #{e.message}"
66
+ puts 'Please check your API key above'
67
+ rescue Anvil::Error => e
68
+ puts "āŒ Anvil error: #{e.message}"
69
+ rescue StandardError => e
70
+ puts "āŒ Error: #{e.message}"
71
+ puts e.backtrace.first(3)
72
+ end