haveapi-go-client 0.26.5 → 0.27.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.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/haveapi-go-client.gemspec +1 -1
- data/lib/haveapi/go_client/cli.rb +8 -0
- data/lib/haveapi/go_client/generator.rb +3 -0
- data/lib/haveapi/go_client/version.rb +1 -1
- data/spec/integration/generator_spec.rb +161 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/test_server.rb +95 -0
- data/template/action.go.erb +69 -0
- data/template/types.go.erb +80 -0
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bb661e4d9dd5ab5b29d5d3b63af4b37a486848e0623a6e34ac41f53f0a0feebe
|
|
4
|
+
data.tar.gz: 485e7d815e181bf209d541a0eb63c305acd79440cba6144812263b25108369de
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c6ff55c1c5d592a79c5052df6ee2ea9311e0039b7d37068d9048d592ee2fe0b63913c9dca088387abf57a1937b015a75c4bf3c664a20aac9875f62e2d88236d3
|
|
7
|
+
data.tar.gz: 06014c3863378caf51e02c6b6be0d919f740d6659974c185915ec89a8b0a4bd07434e625481599704ead36f3565e718fd0817462d6400462a0dcda01abd1097d
|
data/Gemfile
CHANGED
data/haveapi-go-client.gemspec
CHANGED
|
@@ -22,6 +22,14 @@ module HaveAPI::GoClient
|
|
|
22
22
|
opts.on('--package PKG', 'Name of the generated Go package') do |v|
|
|
23
23
|
options[:package] = v
|
|
24
24
|
end
|
|
25
|
+
|
|
26
|
+
opts.on('--basic-user USER', 'Basic auth username for API description') do |v|
|
|
27
|
+
options[:basic_user] = v
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
opts.on('--basic-password PASSWORD', 'Basic auth password for API description') do |v|
|
|
31
|
+
options[:basic_password] = v
|
|
32
|
+
end
|
|
25
33
|
end
|
|
26
34
|
|
|
27
35
|
parser.parse!
|
|
@@ -27,6 +27,9 @@ module HaveAPI::GoClient
|
|
|
27
27
|
@package = opts[:package]
|
|
28
28
|
|
|
29
29
|
conn = HaveAPI::Client::Communicator.new(url)
|
|
30
|
+
if opts[:basic_user] && opts[:basic_password]
|
|
31
|
+
conn.authenticate(:basic, user: opts[:basic_user], password: opts[:basic_password])
|
|
32
|
+
end
|
|
30
33
|
@api = ApiVersion.new(conn.describe_api(opts[:version]))
|
|
31
34
|
end
|
|
32
35
|
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe HaveAPI::GoClient::Generator do
|
|
6
|
+
let(:base_url) { TEST_SERVER.base_url }
|
|
7
|
+
let(:root) { File.expand_path('../../../..', __dir__) }
|
|
8
|
+
let(:cwd) { File.join(root, 'clients', 'go') }
|
|
9
|
+
|
|
10
|
+
it 'generates a client that compiles and can call the API' do
|
|
11
|
+
Dir.mktmpdir('haveapi-go-client-') do |dir|
|
|
12
|
+
cmd = [
|
|
13
|
+
'bundle', 'exec', 'ruby', 'bin/haveapi-go-client',
|
|
14
|
+
base_url, dir,
|
|
15
|
+
'--module', 'example.com/haveapi-test',
|
|
16
|
+
'--package', 'client',
|
|
17
|
+
'--basic-user', 'user',
|
|
18
|
+
'--basic-password', 'pass'
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
stdout, stderr, status = Open3.capture3(*cmd, chdir: cwd)
|
|
22
|
+
expect(status).to be_success, "generator failed: #{stdout}\n#{stderr}"
|
|
23
|
+
|
|
24
|
+
File.write(File.join(dir, 'client', 'client_integration_test.go'), <<~GO)
|
|
25
|
+
package client
|
|
26
|
+
|
|
27
|
+
import "testing"
|
|
28
|
+
|
|
29
|
+
func TestProjectList(t *testing.T) {
|
|
30
|
+
c := New("#{base_url}")
|
|
31
|
+
c.SetBasicAuthentication("user", "pass")
|
|
32
|
+
|
|
33
|
+
resp, err := c.Project.List.Prepare().Call()
|
|
34
|
+
if err != nil {
|
|
35
|
+
t.Fatalf("list failed: %v", err)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if !resp.Status {
|
|
39
|
+
t.Fatalf("request failed: %s", resp.Message)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if len(resp.Output) < 2 {
|
|
43
|
+
t.Fatalf("expected at least 2 projects, got %d", len(resp.Output))
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
GO
|
|
47
|
+
|
|
48
|
+
File.write(File.join(dir, 'client', 'client_validation_test.go'), <<~GO)
|
|
49
|
+
package client
|
|
50
|
+
|
|
51
|
+
import (
|
|
52
|
+
"math"
|
|
53
|
+
"testing"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
func newValidationClient() *Client {
|
|
57
|
+
c := New("#{base_url}")
|
|
58
|
+
c.SetBasicAuthentication("user", "pass")
|
|
59
|
+
return c
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
func TestEchoRejectsNaNFloat(t *testing.T) {
|
|
63
|
+
c := newValidationClient()
|
|
64
|
+
req := c.Test.Echo.Prepare()
|
|
65
|
+
in := req.NewInput()
|
|
66
|
+
in.SetI(1)
|
|
67
|
+
in.SetF(math.NaN())
|
|
68
|
+
in.SetB(true)
|
|
69
|
+
in.SetDt("2020-01-01T00:00:00Z")
|
|
70
|
+
in.SetS("x")
|
|
71
|
+
in.SetT("y")
|
|
72
|
+
|
|
73
|
+
_, err := req.Call()
|
|
74
|
+
if err == nil {
|
|
75
|
+
t.Fatalf("expected validation error, got nil")
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
verr, ok := err.(*ValidationError)
|
|
79
|
+
if !ok {
|
|
80
|
+
t.Fatalf("expected ValidationError, got %T: %v", err, err)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if verr.Errors["f"] == nil {
|
|
84
|
+
t.Fatalf("expected float error, got %#v", verr.Errors)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
func TestEchoRejectsInvalidDatetime(t *testing.T) {
|
|
89
|
+
c := newValidationClient()
|
|
90
|
+
req := c.Test.Echo.Prepare()
|
|
91
|
+
in := req.NewInput()
|
|
92
|
+
in.SetI(1)
|
|
93
|
+
in.SetF(1.0)
|
|
94
|
+
in.SetB(true)
|
|
95
|
+
in.SetDt("not-a-date")
|
|
96
|
+
in.SetS("x")
|
|
97
|
+
in.SetT("y")
|
|
98
|
+
|
|
99
|
+
_, err := req.Call()
|
|
100
|
+
if err == nil {
|
|
101
|
+
t.Fatalf("expected validation error, got nil")
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
verr, ok := err.(*ValidationError)
|
|
105
|
+
if !ok {
|
|
106
|
+
t.Fatalf("expected ValidationError, got %T: %v", err, err)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if verr.Errors["dt"] == nil {
|
|
110
|
+
t.Fatalf("expected datetime error, got %#v", verr.Errors)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
func TestEchoResourceRejectsNegativeID(t *testing.T) {
|
|
115
|
+
c := newValidationClient()
|
|
116
|
+
req := c.Test.EchoResource.Prepare()
|
|
117
|
+
in := req.NewInput()
|
|
118
|
+
in.SetProject(-1)
|
|
119
|
+
|
|
120
|
+
_, err := req.Call()
|
|
121
|
+
if err == nil {
|
|
122
|
+
t.Fatalf("expected validation error, got nil")
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
verr, ok := err.(*ValidationError)
|
|
126
|
+
if !ok {
|
|
127
|
+
t.Fatalf("expected ValidationError, got %T: %v", err, err)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if verr.Errors["project"] == nil {
|
|
131
|
+
t.Fatalf("expected resource error, got %#v", verr.Errors)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
func TestEchoAcceptsValidInput(t *testing.T) {
|
|
136
|
+
c := newValidationClient()
|
|
137
|
+
req := c.Test.Echo.Prepare()
|
|
138
|
+
in := req.NewInput()
|
|
139
|
+
in.SetI(123)
|
|
140
|
+
in.SetF(1.5)
|
|
141
|
+
in.SetB(true)
|
|
142
|
+
in.SetDt("2020-01-01")
|
|
143
|
+
in.SetS("hello")
|
|
144
|
+
in.SetT("world")
|
|
145
|
+
|
|
146
|
+
resp, err := req.Call()
|
|
147
|
+
if err != nil {
|
|
148
|
+
t.Fatalf("echo failed: %v", err)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if !resp.Status {
|
|
152
|
+
t.Fatalf("request failed: %s", resp.Message)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
GO
|
|
156
|
+
|
|
157
|
+
go_out, go_err, go_status = Open3.capture3('go', 'test', './...', chdir: dir)
|
|
158
|
+
expect(go_status).to be_success, "go test failed: #{go_out}\n#{go_err}"
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'open3'
|
|
5
|
+
require 'tmpdir'
|
|
6
|
+
require 'haveapi/go_client'
|
|
7
|
+
|
|
8
|
+
require_relative 'support/test_server'
|
|
9
|
+
|
|
10
|
+
TEST_SERVER = ClientTestServer.new
|
|
11
|
+
|
|
12
|
+
RSpec.configure do |config|
|
|
13
|
+
config.order = :random
|
|
14
|
+
|
|
15
|
+
config.before(:suite) do
|
|
16
|
+
TEST_SERVER.start
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
config.after(:suite) do
|
|
20
|
+
TEST_SERVER.stop!
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
config.before do
|
|
24
|
+
TEST_SERVER.reset!
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
require 'net/http'
|
|
5
|
+
require 'timeout'
|
|
6
|
+
require 'uri'
|
|
7
|
+
|
|
8
|
+
class ClientTestServer
|
|
9
|
+
READY_PREFIX = 'HAVEAPI_TEST_SERVER_READY'
|
|
10
|
+
|
|
11
|
+
attr_reader :base_url
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@root = File.expand_path('../../../..', __dir__)
|
|
15
|
+
@server_script = File.join(@root, 'servers', 'ruby', 'test_support', 'client_test_server.rb')
|
|
16
|
+
@gemfile = File.join(@root, 'servers', 'ruby', 'Gemfile')
|
|
17
|
+
@cwd = File.join(@root, 'clients', 'go')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def start
|
|
21
|
+
return if @wait_thr
|
|
22
|
+
|
|
23
|
+
env = { 'BUNDLE_GEMFILE' => @gemfile }
|
|
24
|
+
cmd = ['bundle', 'exec', 'ruby', @server_script, '--port', '0']
|
|
25
|
+
@stdin, @stdout, @wait_thr = Open3.popen2e(env, *cmd, chdir: @cwd)
|
|
26
|
+
|
|
27
|
+
read_ready!
|
|
28
|
+
wait_for_health!
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def reset!
|
|
32
|
+
ensure_started!
|
|
33
|
+
|
|
34
|
+
uri = URI.join(@base_url, '/__reset')
|
|
35
|
+
req = Net::HTTP::Post.new(uri)
|
|
36
|
+
req['Content-Type'] = 'application/json'
|
|
37
|
+
res = Net::HTTP.start(uri.host, uri.port) { |http| http.request(req) }
|
|
38
|
+
|
|
39
|
+
return if res.is_a?(Net::HTTPSuccess)
|
|
40
|
+
|
|
41
|
+
raise "reset failed: #{res.code} #{res.body}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def stop!
|
|
45
|
+
return unless @wait_thr
|
|
46
|
+
|
|
47
|
+
Process.kill('TERM', @wait_thr.pid)
|
|
48
|
+
@wait_thr.value
|
|
49
|
+
rescue Errno::ESRCH
|
|
50
|
+
nil
|
|
51
|
+
ensure
|
|
52
|
+
@stdin&.close
|
|
53
|
+
@stdout&.close
|
|
54
|
+
@wait_thr = nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def ensure_started!
|
|
60
|
+
start unless @wait_thr
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def read_ready!
|
|
64
|
+
Timeout.timeout(10) do
|
|
65
|
+
while (line = @stdout.gets)
|
|
66
|
+
next unless line.include?(READY_PREFIX)
|
|
67
|
+
|
|
68
|
+
@base_url = line.split.last&.strip
|
|
69
|
+
break
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
raise 'server did not start' unless @base_url
|
|
74
|
+
rescue Timeout::Error
|
|
75
|
+
raise 'server did not start in time'
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def wait_for_health!
|
|
79
|
+
Timeout.timeout(5) do
|
|
80
|
+
loop do
|
|
81
|
+
begin
|
|
82
|
+
uri = URI.join(@base_url, '/__health')
|
|
83
|
+
res = Net::HTTP.get_response(uri)
|
|
84
|
+
return if res.is_a?(Net::HTTPSuccess)
|
|
85
|
+
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, IOError
|
|
86
|
+
# retry
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
sleep 0.05
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
rescue Timeout::Error
|
|
93
|
+
raise 'server did not become healthy in time'
|
|
94
|
+
end
|
|
95
|
+
end
|
data/template/action.go.erb
CHANGED
|
@@ -365,8 +365,77 @@ func (inv *<%= action.go_invocation_type %>) IsMetaParameterNil(param string) bo
|
|
|
365
365
|
}
|
|
366
366
|
<% end -%>
|
|
367
367
|
|
|
368
|
+
func (inv *<%= action.go_invocation_type %>) validate() error {
|
|
369
|
+
verr := NewValidationError()
|
|
370
|
+
<% if action.has_input? -%>
|
|
371
|
+
if inv.Input != nil {
|
|
372
|
+
<% action.input.parameters.each do |p| -%>
|
|
373
|
+
<% if %w(Float Datetime Resource).include?(p.type) -%>
|
|
374
|
+
if inv.IsParameterSelected("<%= p.go_name %>") {
|
|
375
|
+
if !inv.IsParameterNil("<%= p.go_name %>") {
|
|
376
|
+
<% if p.type == 'Float' -%>
|
|
377
|
+
if !isFiniteFloat64(inv.Input.<%= p.go_name %>) {
|
|
378
|
+
verr.Add("<%= p.name %>", "not a valid float")
|
|
379
|
+
}
|
|
380
|
+
<% elsif p.type == 'Datetime' -%>
|
|
381
|
+
normalized, ok := normalizeAndCheckDatetimeString(inv.Input.<%= p.go_name %>)
|
|
382
|
+
if !ok {
|
|
383
|
+
verr.Add("<%= p.name %>", "not a valid datetime")
|
|
384
|
+
} else {
|
|
385
|
+
inv.Input.<%= p.go_name %> = normalized
|
|
386
|
+
}
|
|
387
|
+
<% elsif p.type == 'Resource' -%>
|
|
388
|
+
if inv.Input.<%= p.go_name %> < 0 {
|
|
389
|
+
verr.Add("<%= p.name %>", "not a valid resource id")
|
|
390
|
+
}
|
|
391
|
+
<% end -%>
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
<% end -%>
|
|
395
|
+
<% end -%>
|
|
396
|
+
}
|
|
397
|
+
<% end -%>
|
|
398
|
+
<% if action.metadata.has_global_input? -%>
|
|
399
|
+
if inv.MetaInput != nil {
|
|
400
|
+
<% action.metadata.global.input.parameters.each do |p| -%>
|
|
401
|
+
<% if %w(Float Datetime Resource).include?(p.type) -%>
|
|
402
|
+
if inv.IsMetaParameterSelected("<%= p.go_name %>") {
|
|
403
|
+
if !inv.IsMetaParameterNil("<%= p.go_name %>") {
|
|
404
|
+
<% if p.type == 'Float' -%>
|
|
405
|
+
if !isFiniteFloat64(inv.MetaInput.<%= p.go_name %>) {
|
|
406
|
+
verr.Add("<%= p.name %>", "not a valid float")
|
|
407
|
+
}
|
|
408
|
+
<% elsif p.type == 'Datetime' -%>
|
|
409
|
+
normalized, ok := normalizeAndCheckDatetimeString(inv.MetaInput.<%= p.go_name %>)
|
|
410
|
+
if !ok {
|
|
411
|
+
verr.Add("<%= p.name %>", "not a valid datetime")
|
|
412
|
+
} else {
|
|
413
|
+
inv.MetaInput.<%= p.go_name %> = normalized
|
|
414
|
+
}
|
|
415
|
+
<% elsif p.type == 'Resource' -%>
|
|
416
|
+
if inv.MetaInput.<%= p.go_name %> < 0 {
|
|
417
|
+
verr.Add("<%= p.name %>", "not a valid resource id")
|
|
418
|
+
}
|
|
419
|
+
<% end -%>
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
<% end -%>
|
|
423
|
+
<% end -%>
|
|
424
|
+
}
|
|
425
|
+
<% end -%>
|
|
426
|
+
|
|
427
|
+
if verr.Empty() {
|
|
428
|
+
return nil
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return verr
|
|
432
|
+
}
|
|
433
|
+
|
|
368
434
|
// Call() invokes the action and returns a response from the API server
|
|
369
435
|
func (inv *<%= action.go_invocation_type %>) Call() (*<%= action.go_response_type %>, error) {
|
|
436
|
+
if err := inv.validate(); err != nil {
|
|
437
|
+
return nil, err
|
|
438
|
+
}
|
|
370
439
|
<% if action.http_method == 'GET' -%>
|
|
371
440
|
return inv.callAsQuery()
|
|
372
441
|
<% else -%>
|
data/template/types.go.erb
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
package <%= package %>
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
+
"math"
|
|
5
|
+
"sort"
|
|
4
6
|
"strconv"
|
|
7
|
+
"strings"
|
|
8
|
+
"time"
|
|
5
9
|
)
|
|
6
10
|
|
|
7
11
|
type ProgressCallbackReturn int
|
|
@@ -20,6 +24,82 @@ type BlockingOperationWatcher interface {
|
|
|
20
24
|
WatchOperation(timeout float64, updateIn float64, callback OperationProgressCallback) (*ActionActionStatePollResponse, error)
|
|
21
25
|
}
|
|
22
26
|
|
|
27
|
+
type ValidationError struct {
|
|
28
|
+
Errors map[string][]string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
func NewValidationError() *ValidationError {
|
|
32
|
+
return &ValidationError{
|
|
33
|
+
Errors: make(map[string][]string),
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
func (e *ValidationError) Add(param string, msg string) {
|
|
38
|
+
if e.Errors == nil {
|
|
39
|
+
e.Errors = make(map[string][]string)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
e.Errors[param] = append(e.Errors[param], msg)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
func (e *ValidationError) Empty() bool {
|
|
46
|
+
if e == nil {
|
|
47
|
+
return true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return len(e.Errors) == 0
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
func (e *ValidationError) Error() string {
|
|
54
|
+
if e == nil || len(e.Errors) == 0 {
|
|
55
|
+
return "validation failed"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
keys := make([]string, 0, len(e.Errors))
|
|
59
|
+
for key := range e.Errors {
|
|
60
|
+
keys = append(keys, key)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
sort.Strings(keys)
|
|
64
|
+
|
|
65
|
+
parts := make([]string, 0, len(keys))
|
|
66
|
+
for _, key := range keys {
|
|
67
|
+
messages := e.Errors[key]
|
|
68
|
+
if len(messages) == 0 {
|
|
69
|
+
parts = append(parts, key)
|
|
70
|
+
} else {
|
|
71
|
+
parts = append(parts, key+": "+strings.Join(messages, ", "))
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return "validation failed: " + strings.Join(parts, "; ")
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
func isFiniteFloat64(v float64) bool {
|
|
79
|
+
return !math.IsNaN(v) && !math.IsInf(v, 0)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
func normalizeAndCheckDatetimeString(v string) (string, bool) {
|
|
83
|
+
trimmed := strings.TrimSpace(v)
|
|
84
|
+
if trimmed == "" {
|
|
85
|
+
return trimmed, false
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if _, err := time.Parse("2006-01-02", trimmed); err == nil {
|
|
89
|
+
return trimmed, true
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if _, err := time.Parse(time.RFC3339, trimmed); err == nil {
|
|
93
|
+
return trimmed, true
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if _, err := time.Parse(time.RFC3339Nano, trimmed); err == nil {
|
|
97
|
+
return trimmed, true
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return trimmed, false
|
|
101
|
+
}
|
|
102
|
+
|
|
23
103
|
func convertInt64ToString(v int64) string {
|
|
24
104
|
return strconv.FormatInt(v, 10)
|
|
25
105
|
}
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: haveapi-go-client
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.27.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jakub Skokan
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.27.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.
|
|
25
|
+
version: 0.27.0
|
|
26
26
|
description: Go client generator
|
|
27
27
|
email:
|
|
28
28
|
- jakub.skokan@vpsfree.cz
|
|
@@ -61,6 +61,9 @@ files:
|
|
|
61
61
|
- lib/haveapi/go_client/utils.rb
|
|
62
62
|
- lib/haveapi/go_client/version.rb
|
|
63
63
|
- shell.nix
|
|
64
|
+
- spec/integration/generator_spec.rb
|
|
65
|
+
- spec/spec_helper.rb
|
|
66
|
+
- spec/support/test_server.rb
|
|
64
67
|
- template/action.go.erb
|
|
65
68
|
- template/authentication.go.erb
|
|
66
69
|
- template/authentication/basic.go.erb
|