@apollo-deploy/tesseract 1.9.0 → 2.0.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.
- package/README.md +218 -110
- package/dist/adapters/csharp/index.d.ts +5 -8
- package/dist/adapters/csharp/index.d.ts.map +1 -1
- package/dist/adapters/csharp/index.js +314 -74
- package/dist/adapters/csharp/index.js.map +1 -1
- package/dist/adapters/documentation.d.ts +17 -0
- package/dist/adapters/documentation.d.ts.map +1 -0
- package/dist/adapters/documentation.js +268 -0
- package/dist/adapters/documentation.js.map +1 -0
- package/dist/adapters/go/index.d.ts +5 -8
- package/dist/adapters/go/index.d.ts.map +1 -1
- package/dist/adapters/go/index.js +197 -101
- package/dist/adapters/go/index.js.map +1 -1
- package/dist/adapters/kotlin/index.d.ts +5 -9
- package/dist/adapters/kotlin/index.d.ts.map +1 -1
- package/dist/adapters/kotlin/index.js +280 -212
- package/dist/adapters/kotlin/index.js.map +1 -1
- package/dist/adapters/php/index.d.ts +5 -15
- package/dist/adapters/php/index.d.ts.map +1 -1
- package/dist/adapters/php/index.js +362 -90
- package/dist/adapters/php/index.js.map +1 -1
- package/dist/adapters/python/index.d.ts +5 -8
- package/dist/adapters/python/index.d.ts.map +1 -1
- package/dist/adapters/python/index.js +240 -109
- package/dist/adapters/python/index.js.map +1 -1
- package/dist/adapters/ruby/index.d.ts +3 -3
- package/dist/adapters/ruby/index.d.ts.map +1 -1
- package/dist/adapters/ruby/index.js +235 -46
- package/dist/adapters/ruby/index.js.map +1 -1
- package/dist/adapters/rust/index.d.ts +5 -9
- package/dist/adapters/rust/index.d.ts.map +1 -1
- package/dist/adapters/rust/index.js +237 -169
- package/dist/adapters/rust/index.js.map +1 -1
- package/dist/adapters/shared.d.ts +7 -0
- package/dist/adapters/shared.d.ts.map +1 -0
- package/dist/adapters/shared.js +68 -0
- package/dist/adapters/shared.js.map +1 -0
- package/dist/adapters/type-utils.d.ts +13 -0
- package/dist/adapters/type-utils.d.ts.map +1 -0
- package/dist/adapters/type-utils.js +105 -0
- package/dist/adapters/type-utils.js.map +1 -0
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/typescript/emitter/emitSchema.d.ts +2 -2
- package/dist/adapters/typescript/emitter/emitSchema.js +39 -27
- package/dist/adapters/typescript/emitter/emitSchema.js.map +1 -1
- package/dist/adapters/typescript/emitter/emitTypeScriptModels.d.ts +2 -2
- package/dist/adapters/typescript/emitter/emitTypeScriptModels.js +15 -15
- package/dist/adapters/typescript/emitter/importCollector.d.ts +2 -4
- package/dist/adapters/typescript/emitter/importCollector.d.ts.map +1 -1
- package/dist/adapters/typescript/emitter/importCollector.js +40 -50
- package/dist/adapters/typescript/emitter/importCollector.js.map +1 -1
- package/dist/adapters/typescript/emitter/parsers.d.ts +1 -1
- package/dist/adapters/typescript/emitter/parsers.js +13 -13
- package/dist/adapters/typescript/emitter/typeHoister.d.ts +1 -1
- package/dist/adapters/typescript/emitter/typeHoister.d.ts.map +1 -1
- package/dist/adapters/typescript/emitter/typeHoister.js +12 -20
- package/dist/adapters/typescript/emitter/typeHoister.js.map +1 -1
- package/dist/adapters/typescript/index.d.ts +3 -3
- package/dist/adapters/typescript/index.d.ts.map +1 -1
- package/dist/adapters/typescript/index.js +148 -166
- package/dist/adapters/typescript/index.js.map +1 -1
- package/dist/adapters/typescript/shared.d.ts +2 -2
- package/dist/adapters/typescript/shared.js +12 -12
- package/dist/cli.js +50 -37
- package/dist/cli.js.map +1 -1
- package/dist/collector.d.ts +13 -3
- package/dist/collector.d.ts.map +1 -1
- package/dist/collector.js +69 -32
- package/dist/collector.js.map +1 -1
- package/dist/elysia.js +2 -2
- package/dist/elysia.js.map +1 -1
- package/dist/express.d.ts.map +1 -1
- package/dist/express.js.map +1 -1
- package/dist/fastify.d.ts +7 -0
- package/dist/fastify.d.ts.map +1 -1
- package/dist/fastify.js +39 -20
- package/dist/fastify.js.map +1 -1
- package/dist/helpers/handlebars.d.ts +7 -16
- package/dist/helpers/handlebars.d.ts.map +1 -1
- package/dist/helpers/handlebars.js +127 -177
- package/dist/helpers/handlebars.js.map +1 -1
- package/dist/hono.d.ts.map +1 -1
- package/dist/hono.js.map +1 -1
- package/dist/index.d.ts +14 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -30
- package/dist/index.js.map +1 -1
- package/dist/koa.d.ts.map +1 -1
- package/dist/koa.js.map +1 -1
- package/dist/nestjs.d.ts.map +1 -1
- package/dist/nestjs.js +41 -14
- package/dist/nestjs.js.map +1 -1
- package/dist/pipeline/enrich.d.ts +2 -13
- package/dist/pipeline/enrich.d.ts.map +1 -1
- package/dist/pipeline/enrich.js +157 -212
- package/dist/pipeline/enrich.js.map +1 -1
- package/dist/pipeline/intake.d.ts +3 -3
- package/dist/pipeline/intake.d.ts.map +1 -1
- package/dist/pipeline/intake.js +342 -238
- package/dist/pipeline/intake.js.map +1 -1
- package/dist/pipeline/write.d.ts +1 -14
- package/dist/pipeline/write.d.ts.map +1 -1
- package/dist/pipeline/write.js +73 -113
- package/dist/pipeline/write.js.map +1 -1
- package/dist/types/config.d.ts +14 -26
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +16 -12
- package/dist/types/config.js.map +1 -1
- package/dist/types/ir.d.ts +12 -8
- package/dist/types/ir.d.ts.map +1 -1
- package/dist/types/manifest.d.ts +10 -11
- package/dist/types/manifest.d.ts.map +1 -1
- package/dist/types/manifest.js +54 -14
- package/dist/types/manifest.js.map +1 -1
- package/dist/types/sdk-module.d.ts +2 -2
- package/dist/types/sdk-module.js +1 -1
- package/dist/utils/format.d.ts +1 -3
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/format.js +3 -10
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/naming.d.ts.map +1 -1
- package/dist/utils/naming.js +174 -184
- package/dist/utils/naming.js.map +1 -1
- package/dist/utils/npm-token.d.ts +1 -17
- package/dist/utils/npm-token.d.ts.map +1 -1
- package/dist/utils/npm-token.js +27 -76
- package/dist/utils/npm-token.js.map +1 -1
- package/dist/utils/version.d.ts +14 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +60 -0
- package/dist/utils/version.js.map +1 -0
- package/package.json +4 -3
- package/templates/csharp/client.hbs +26 -49
- package/templates/csharp/csproj.hbs +7 -0
- package/templates/csharp/domain.hbs +48 -130
- package/templates/csharp/errors.hbs +17 -25
- package/templates/csharp/readme.hbs +31 -44
- package/templates/csharp/transport.hbs +238 -136
- package/templates/csharp/types.hbs +30 -76
- package/templates/go/client.hbs +44 -109
- package/templates/go/domain.hbs +83 -25
- package/templates/go/go-mod.hbs +1 -4
- package/templates/go/readme.hbs +32 -29
- package/templates/go/transport.hbs +174 -173
- package/templates/go/types.hbs +17 -53
- package/templates/go/utils.hbs +3 -2
- package/templates/kotlin/build-gradle.hbs +1 -1
- package/templates/kotlin/client.hbs +18 -15
- package/templates/kotlin/domain.hbs +54 -51
- package/templates/kotlin/errors.hbs +1 -1
- package/templates/kotlin/readme.hbs +35 -137
- package/templates/kotlin/transport.hbs +140 -123
- package/templates/kotlin/types.hbs +30 -81
- package/templates/php/client.hbs +8 -46
- package/templates/php/composer.hbs +2 -1
- package/templates/php/domain.hbs +86 -117
- package/templates/php/errors.hbs +1 -1
- package/templates/php/readme.hbs +42 -49
- package/templates/php/transport.hbs +192 -145
- package/templates/php/types.hbs +63 -60
- package/templates/python/client.hbs +15 -2
- package/templates/python/domain.hbs +50 -108
- package/templates/python/pyproject.hbs +5 -0
- package/templates/python/readme.hbs +47 -30
- package/templates/python/resources-init.hbs +1 -1
- package/templates/python/transport.hbs +167 -53
- package/templates/python/types.hbs +22 -58
- package/templates/ruby/client.hbs +10 -6
- package/templates/ruby/domain.hbs +48 -67
- package/templates/ruby/errors.hbs +3 -3
- package/templates/ruby/gemspec.hbs +3 -10
- package/templates/ruby/index.hbs +3 -3
- package/templates/ruby/readme.hbs +33 -70
- package/templates/ruby/transport.hbs +129 -103
- package/templates/ruby/types.hbs +11 -16
- package/templates/ruby/version.hbs +1 -1
- package/templates/rust/cargo.hbs +2 -0
- package/templates/rust/client.hbs +10 -1
- package/templates/rust/domain.hbs +69 -52
- package/templates/rust/error.hbs +3 -1
- package/templates/rust/lib.hbs +4 -5
- package/templates/rust/readme.hbs +33 -46
- package/templates/rust/transport.hbs +170 -159
- package/templates/rust/types.hbs +34 -111
- package/templates/typescript/domain-class.hbs +14 -6
- package/templates/typescript/domain.hbs +13 -5
- package/templates/typescript/package-json.hbs +3 -1
- package/templates/typescript/readme.hbs +42 -42
- package/templates/typescript/transport.hbs +46 -8
- package/templates/typescript/types-errors.hbs +1 -1
- package/dist/adapters/typescript/model-emitter.d.ts +0 -13
- package/dist/adapters/typescript/model-emitter.d.ts.map +0 -1
- package/dist/adapters/typescript/model-emitter.js +0 -415
- package/dist/adapters/typescript/model-emitter.js.map +0 -1
|
@@ -6,43 +6,61 @@ import (
|
|
|
6
6
|
"encoding/json"
|
|
7
7
|
"fmt"
|
|
8
8
|
"io"
|
|
9
|
-
"math"
|
|
10
9
|
"math/rand"
|
|
10
|
+
"net"
|
|
11
11
|
"net/http"
|
|
12
12
|
"net/url"
|
|
13
|
+
"strconv"
|
|
13
14
|
"strings"
|
|
14
15
|
"time"
|
|
15
16
|
)
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
var retryableMethods = map[string]struct{}{
|
|
19
|
+
http.MethodGet: {}, http.MethodHead: {}, http.MethodOptions: {},
|
|
20
|
+
http.MethodPut: {}, http.MethodDelete: {},
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
var retryableStatuses = map[int]struct{}{
|
|
24
|
+
http.StatusRequestTimeout: {}, 425: {}, http.StatusTooManyRequests: {},
|
|
25
|
+
http.StatusInternalServerError: {}, http.StatusBadGateway: {},
|
|
26
|
+
http.StatusServiceUnavailable: {}, http.StatusGatewayTimeout: {},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// TransportConfig configures the HTTP transport.
|
|
18
30
|
type TransportConfig struct {
|
|
19
|
-
BaseURL
|
|
31
|
+
BaseURL string
|
|
20
32
|
{{#each securitySchemes}}
|
|
21
33
|
{{pascalCase configKey}} string
|
|
22
34
|
{{/each}}
|
|
23
|
-
Timeout
|
|
24
|
-
MaxRetries
|
|
25
|
-
|
|
35
|
+
Timeout time.Duration
|
|
36
|
+
MaxRetries int
|
|
37
|
+
RetryUnsafeRequests bool
|
|
38
|
+
Headers map[string]string
|
|
39
|
+
UserAgent string
|
|
26
40
|
}
|
|
27
41
|
|
|
28
|
-
// Transport
|
|
29
|
-
// serialization, retries, and error normalization.
|
|
42
|
+
// Transport handles authentication, serialization, retries, and errors.
|
|
30
43
|
type Transport struct {
|
|
31
44
|
config TransportConfig
|
|
32
45
|
httpClient *http.Client
|
|
33
46
|
}
|
|
34
47
|
|
|
35
|
-
// NewTransport creates a new Transport with the given configuration.
|
|
36
48
|
func NewTransport(cfg TransportConfig) *Transport {
|
|
49
|
+
if cfg.Timeout <= 0 {
|
|
50
|
+
cfg.Timeout = 15 * time.Second
|
|
51
|
+
}
|
|
52
|
+
if cfg.MaxRetries < 0 {
|
|
53
|
+
cfg.MaxRetries = 0
|
|
54
|
+
}
|
|
55
|
+
if cfg.UserAgent == "" {
|
|
56
|
+
cfg.UserAgent = "{{pkgName}}-go-sdk/{{packageVersion}}"
|
|
57
|
+
}
|
|
37
58
|
return &Transport{
|
|
38
59
|
config: cfg,
|
|
39
|
-
httpClient: &http.Client{
|
|
40
|
-
Timeout: cfg.Timeout,
|
|
41
|
-
},
|
|
60
|
+
httpClient: &http.Client{Timeout: cfg.Timeout},
|
|
42
61
|
}
|
|
43
62
|
}
|
|
44
63
|
|
|
45
|
-
// request holds all the parameters for a single HTTP call.
|
|
46
64
|
type request struct {
|
|
47
65
|
Method string
|
|
48
66
|
Path string
|
|
@@ -52,125 +70,107 @@ type request struct {
|
|
|
52
70
|
Headers map[string]string
|
|
53
71
|
}
|
|
54
72
|
|
|
55
|
-
// Execute performs an HTTP request and unmarshals the response body into result.
|
|
56
|
-
// result must be a non-nil pointer.
|
|
57
73
|
func (t *Transport) Execute(ctx context.Context, req request, result interface{}) error {
|
|
58
|
-
|
|
74
|
+
body, err := t.executeWithRetries(ctx, req)
|
|
75
|
+
if err != nil {
|
|
76
|
+
return err
|
|
77
|
+
}
|
|
78
|
+
if result == nil || len(body) == 0 {
|
|
79
|
+
return nil
|
|
80
|
+
}
|
|
81
|
+
if err := json.Unmarshal(body, result); err != nil {
|
|
82
|
+
return fmt.Errorf("failed to unmarshal response: %w", err)
|
|
83
|
+
}
|
|
84
|
+
return nil
|
|
59
85
|
}
|
|
60
86
|
|
|
61
|
-
// ExecuteRaw performs an HTTP request and returns the raw response body bytes.
|
|
62
87
|
func (t *Transport) ExecuteRaw(ctx context.Context, req request) ([]byte, error) {
|
|
63
|
-
return t.
|
|
88
|
+
return t.executeWithRetries(ctx, req)
|
|
64
89
|
}
|
|
65
90
|
|
|
66
|
-
|
|
67
|
-
|
|
91
|
+
func (t *Transport) executeWithRetries(ctx context.Context, req request) ([]byte, error) {
|
|
92
|
+
canRetry := t.canRetry(req)
|
|
68
93
|
var lastErr error
|
|
69
94
|
|
|
70
|
-
for attempt := 0; attempt <=
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
select {
|
|
75
|
-
case <-ctx.Done():
|
|
76
|
-
return ctx.Err()
|
|
77
|
-
case <-time.After(backoff + jitter):
|
|
78
|
-
}
|
|
95
|
+
for attempt := 0; attempt <= t.config.MaxRetries; attempt++ {
|
|
96
|
+
resp, body, err := t.doRequest(ctx, req)
|
|
97
|
+
if err == nil && resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
|
98
|
+
return body, nil
|
|
79
99
|
}
|
|
80
100
|
|
|
81
|
-
|
|
101
|
+
var retryAfter time.Duration
|
|
82
102
|
if err != nil {
|
|
83
103
|
lastErr = err
|
|
84
|
-
if !
|
|
85
|
-
return err
|
|
104
|
+
if !canRetry || !isRetryableNetworkError(err) || attempt >= t.config.MaxRetries {
|
|
105
|
+
return nil, normalizeNetworkError(err)
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
lastErr = parseErrorResponse(resp, body)
|
|
109
|
+
if !canRetry || !isRetryableStatus(resp.StatusCode) || attempt >= t.config.MaxRetries {
|
|
110
|
+
return nil, lastErr
|
|
86
111
|
}
|
|
87
|
-
|
|
112
|
+
retryAfter = parseRetryAfter(resp.Header.Get("Retry-After"))
|
|
88
113
|
}
|
|
89
114
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
115
|
+
delay := retryAfter
|
|
116
|
+
if delay <= 0 {
|
|
117
|
+
capDelay := 400 * time.Millisecond * time.Duration(1<<attempt)
|
|
118
|
+
if capDelay > 30*time.Second {
|
|
119
|
+
capDelay = 30 * time.Second
|
|
120
|
+
}
|
|
121
|
+
if capDelay > 0 {
|
|
122
|
+
delay = time.Duration(rand.Int63n(int64(capDelay) + 1))
|
|
95
123
|
}
|
|
96
|
-
return nil
|
|
97
124
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
125
|
+
select {
|
|
126
|
+
case <-ctx.Done():
|
|
127
|
+
return nil, ctx.Err()
|
|
128
|
+
case <-time.After(delay):
|
|
102
129
|
}
|
|
103
|
-
|
|
104
|
-
return parseErrorResponse(resp, body)
|
|
105
130
|
}
|
|
106
131
|
|
|
107
|
-
return lastErr
|
|
132
|
+
return nil, lastErr
|
|
108
133
|
}
|
|
109
134
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return nil, ctx.Err()
|
|
121
|
-
case <-time.After(backoff + jitter):
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
resp, body, err := t.doRequest(ctx, req)
|
|
126
|
-
if err != nil {
|
|
127
|
-
lastErr = err
|
|
128
|
-
if !isRetryable(err) {
|
|
129
|
-
return nil, err
|
|
130
|
-
}
|
|
131
|
-
continue
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
|
135
|
-
return body, nil
|
|
135
|
+
func (t *Transport) canRetry(req request) bool {
|
|
136
|
+
if t.config.RetryUnsafeRequests {
|
|
137
|
+
return true
|
|
138
|
+
}
|
|
139
|
+
if _, ok := retryableMethods[strings.ToUpper(req.Method)]; ok {
|
|
140
|
+
return true
|
|
141
|
+
}
|
|
142
|
+
for name, value := range t.config.Headers {
|
|
143
|
+
if strings.EqualFold(name, "X-Idempotency-Key") && value != "" {
|
|
144
|
+
return true
|
|
136
145
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
146
|
+
}
|
|
147
|
+
for name, value := range req.Headers {
|
|
148
|
+
if strings.EqualFold(name, "X-Idempotency-Key") && value != "" {
|
|
149
|
+
return true
|
|
141
150
|
}
|
|
142
|
-
|
|
143
|
-
return nil, parseErrorResponse(resp, body)
|
|
144
151
|
}
|
|
145
|
-
|
|
146
|
-
return nil, lastErr
|
|
152
|
+
return false
|
|
147
153
|
}
|
|
148
154
|
|
|
149
|
-
// doRequest builds and executes a single HTTP request.
|
|
150
155
|
func (t *Transport) doRequest(ctx context.Context, req request) (*http.Response, []byte, error) {
|
|
151
|
-
// Build URL
|
|
152
156
|
base, err := url.Parse(t.config.BaseURL)
|
|
153
157
|
if err != nil {
|
|
154
158
|
return nil, nil, fmt.Errorf("invalid base URL: %w", err)
|
|
155
159
|
}
|
|
156
|
-
|
|
157
160
|
rel, err := url.Parse(req.Path)
|
|
158
161
|
if err != nil {
|
|
159
162
|
return nil, nil, fmt.Errorf("invalid request path: %w", err)
|
|
160
163
|
}
|
|
161
|
-
|
|
162
164
|
fullURL := base.ResolveReference(rel)
|
|
163
|
-
|
|
164
165
|
if len(req.Query) > 0 {
|
|
165
166
|
fullURL.RawQuery = req.Query.Encode()
|
|
166
167
|
}
|
|
167
168
|
|
|
168
|
-
// Build body
|
|
169
169
|
var bodyReader io.Reader
|
|
170
170
|
if req.Body != nil {
|
|
171
|
-
bodyBytes,
|
|
172
|
-
if
|
|
173
|
-
return nil, nil, fmt.Errorf("failed to marshal request body: %w",
|
|
171
|
+
bodyBytes, marshalErr := json.Marshal(req.Body)
|
|
172
|
+
if marshalErr != nil {
|
|
173
|
+
return nil, nil, fmt.Errorf("failed to marshal request body: %w", marshalErr)
|
|
174
174
|
}
|
|
175
175
|
bodyReader = bytes.NewReader(bodyBytes)
|
|
176
176
|
}
|
|
@@ -180,12 +180,13 @@ func (t *Transport) doRequest(ctx context.Context, req request) (*http.Response,
|
|
|
180
180
|
return nil, nil, fmt.Errorf("failed to create request: %w", err)
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
for key, value := range t.config.Headers {
|
|
184
|
+
httpReq.Header.Set(key, value)
|
|
185
|
+
}
|
|
186
|
+
httpReq.Header.Set("Accept", "application/json")
|
|
187
|
+
if httpReq.Header.Get("User-Agent") == "" {
|
|
188
|
+
httpReq.Header.Set("User-Agent", t.config.UserAgent)
|
|
186
189
|
}
|
|
187
|
-
|
|
188
|
-
// Set auth headers
|
|
189
190
|
{{#each securitySchemes}}
|
|
190
191
|
{{#if (eq type "apiKey")}}
|
|
191
192
|
{{#if (eq in "header")}}
|
|
@@ -195,9 +196,9 @@ func (t *Transport) doRequest(ctx context.Context, req request) (*http.Response,
|
|
|
195
196
|
{{/if}}
|
|
196
197
|
{{#if (eq in "query")}}
|
|
197
198
|
if t.config.{{pascalCase configKey}} != "" {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
httpReq.URL.RawQuery =
|
|
199
|
+
query := httpReq.URL.Query()
|
|
200
|
+
query.Set("{{paramName}}", t.config.{{pascalCase configKey}})
|
|
201
|
+
httpReq.URL.RawQuery = query.Encode()
|
|
201
202
|
}
|
|
202
203
|
{{/if}}
|
|
203
204
|
{{/if}}
|
|
@@ -218,16 +219,13 @@ func (t *Transport) doRequest(ctx context.Context, req request) (*http.Response,
|
|
|
218
219
|
{{/if}}
|
|
219
220
|
{{/each}}
|
|
220
221
|
|
|
221
|
-
// Set content type
|
|
222
222
|
if req.ContentType != "" {
|
|
223
223
|
httpReq.Header.Set("Content-Type", req.ContentType)
|
|
224
224
|
} else if req.Body != nil {
|
|
225
225
|
httpReq.Header.Set("Content-Type", "application/json")
|
|
226
226
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
for k, v := range req.Headers {
|
|
230
|
-
httpReq.Header.Set(k, v)
|
|
227
|
+
for key, value := range req.Headers {
|
|
228
|
+
httpReq.Header.Set(key, value)
|
|
231
229
|
}
|
|
232
230
|
|
|
233
231
|
resp, err := t.httpClient.Do(httpReq)
|
|
@@ -235,38 +233,34 @@ func (t *Transport) doRequest(ctx context.Context, req request) (*http.Response,
|
|
|
235
233
|
return nil, nil, err
|
|
236
234
|
}
|
|
237
235
|
defer resp.Body.Close()
|
|
238
|
-
|
|
239
236
|
body, err := io.ReadAll(resp.Body)
|
|
240
237
|
if err != nil {
|
|
241
238
|
return resp, nil, fmt.Errorf("failed to read response body: %w", err)
|
|
242
239
|
}
|
|
243
|
-
|
|
244
240
|
return resp, body, nil
|
|
245
241
|
}
|
|
246
242
|
|
|
247
|
-
// Stream
|
|
243
|
+
// Stream opens a streaming response. Reconnection is left to the caller because
|
|
244
|
+
// replaying a partially consumed stream can duplicate events.
|
|
248
245
|
func (t *Transport) Stream(ctx context.Context, req request) (*http.Response, error) {
|
|
249
246
|
base, err := url.Parse(t.config.BaseURL)
|
|
250
247
|
if err != nil {
|
|
251
248
|
return nil, fmt.Errorf("invalid base URL: %w", err)
|
|
252
249
|
}
|
|
253
|
-
|
|
254
250
|
rel, err := url.Parse(req.Path)
|
|
255
251
|
if err != nil {
|
|
256
252
|
return nil, fmt.Errorf("invalid request path: %w", err)
|
|
257
253
|
}
|
|
258
|
-
|
|
259
254
|
fullURL := base.ResolveReference(rel)
|
|
260
|
-
|
|
261
255
|
if len(req.Query) > 0 {
|
|
262
256
|
fullURL.RawQuery = req.Query.Encode()
|
|
263
257
|
}
|
|
264
258
|
|
|
265
259
|
var bodyReader io.Reader
|
|
266
260
|
if req.Body != nil {
|
|
267
|
-
bodyBytes,
|
|
268
|
-
if
|
|
269
|
-
return nil, fmt.Errorf("failed to marshal request body: %w",
|
|
261
|
+
bodyBytes, marshalErr := json.Marshal(req.Body)
|
|
262
|
+
if marshalErr != nil {
|
|
263
|
+
return nil, fmt.Errorf("failed to marshal request body: %w", marshalErr)
|
|
270
264
|
}
|
|
271
265
|
bodyReader = bytes.NewReader(bodyBytes)
|
|
272
266
|
}
|
|
@@ -275,105 +269,112 @@ func (t *Transport) Stream(ctx context.Context, req request) (*http.Response, er
|
|
|
275
269
|
if err != nil {
|
|
276
270
|
return nil, fmt.Errorf("failed to create request: %w", err)
|
|
277
271
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
httpReq.Header.Set(k, v)
|
|
272
|
+
for key, value := range t.config.Headers {
|
|
273
|
+
httpReq.Header.Set(key, value)
|
|
281
274
|
}
|
|
282
|
-
|
|
275
|
+
httpReq.Header.Set("Accept", "text/event-stream")
|
|
276
|
+
httpReq.Header.Set("User-Agent", t.config.UserAgent)
|
|
283
277
|
{{#each securitySchemes}}
|
|
284
278
|
{{#if (eq type "apiKey")}}
|
|
285
279
|
{{#if (eq in "header")}}
|
|
286
|
-
if t.config.{{pascalCase configKey}} != "" {
|
|
287
|
-
httpReq.Header.Set("{{paramName}}", t.config.{{pascalCase configKey}})
|
|
288
|
-
}
|
|
280
|
+
if t.config.{{pascalCase configKey}} != "" { httpReq.Header.Set("{{paramName}}", t.config.{{pascalCase configKey}}) }
|
|
289
281
|
{{/if}}
|
|
290
282
|
{{/if}}
|
|
291
|
-
{{#if (and (eq type "http") (eq scheme "bearer"))}}
|
|
292
|
-
if t.config.{{pascalCase configKey}} != "" {
|
|
293
|
-
httpReq.Header.Set("Authorization", "Bearer "+t.config.{{pascalCase configKey}})
|
|
294
|
-
}
|
|
295
|
-
{{/if}}
|
|
296
|
-
{{#if (eq type "oauth2")}}
|
|
297
|
-
if t.config.{{pascalCase configKey}} != "" {
|
|
298
|
-
httpReq.Header.Set("Authorization", "Bearer "+t.config.{{pascalCase configKey}})
|
|
299
|
-
}
|
|
283
|
+
{{#if (or (and (eq type "http") (eq scheme "bearer")) (eq type "oauth2") (eq type "openIdConnect"))}}
|
|
284
|
+
if t.config.{{pascalCase configKey}} != "" { httpReq.Header.Set("Authorization", "Bearer "+t.config.{{pascalCase configKey}}) }
|
|
300
285
|
{{/if}}
|
|
301
286
|
{{/each}}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
httpReq.Header.Set("Content-Type", req.ContentType)
|
|
305
|
-
} else if req.Body != nil {
|
|
306
|
-
httpReq.Header.Set("Content-Type", "application/json")
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
for k, v := range req.Headers {
|
|
310
|
-
httpReq.Header.Set(k, v)
|
|
287
|
+
for key, value := range req.Headers {
|
|
288
|
+
httpReq.Header.Set(key, value)
|
|
311
289
|
}
|
|
312
290
|
|
|
313
291
|
resp, err := t.httpClient.Do(httpReq)
|
|
314
292
|
if err != nil {
|
|
315
|
-
return nil, err
|
|
293
|
+
return nil, normalizeNetworkError(err)
|
|
316
294
|
}
|
|
317
|
-
|
|
318
295
|
if resp.StatusCode >= 400 {
|
|
319
296
|
body, _ := io.ReadAll(resp.Body)
|
|
320
297
|
resp.Body.Close()
|
|
321
298
|
return nil, parseErrorResponse(resp, body)
|
|
322
299
|
}
|
|
323
|
-
|
|
324
300
|
return resp, nil
|
|
325
301
|
}
|
|
326
302
|
|
|
327
|
-
|
|
303
|
+
func (t *Transport) CloseIdleConnections() {
|
|
304
|
+
t.httpClient.CloseIdleConnections()
|
|
305
|
+
}
|
|
328
306
|
|
|
329
|
-
|
|
330
|
-
|
|
307
|
+
func isRetryableStatus(status int) bool {
|
|
308
|
+
_, ok := retryableStatuses[status]
|
|
309
|
+
return ok
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
func isRetryableNetworkError(err error) bool {
|
|
331
313
|
if err == nil {
|
|
332
314
|
return false
|
|
333
315
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
strings.Contains(
|
|
316
|
+
if netErr, ok := err.(net.Error); ok {
|
|
317
|
+
return netErr.Timeout() || netErr.Temporary()
|
|
318
|
+
}
|
|
319
|
+
message := strings.ToLower(err.Error())
|
|
320
|
+
return strings.Contains(message, "connection reset") ||
|
|
321
|
+
strings.Contains(message, "connection refused") ||
|
|
322
|
+
strings.Contains(message, "unexpected eof") ||
|
|
323
|
+
strings.Contains(message, "temporary failure")
|
|
340
324
|
}
|
|
341
325
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
if rid := resp.Header.Get("X-Request-ID"); rid != "" {
|
|
346
|
-
requestID = rid
|
|
347
|
-
} else if rid := resp.Header.Get("x-request-id"); rid != "" {
|
|
348
|
-
requestID = rid
|
|
326
|
+
func normalizeNetworkError(err error) error {
|
|
327
|
+
if err == nil {
|
|
328
|
+
return nil
|
|
349
329
|
}
|
|
330
|
+
return &SDKError{Status: 0, Code: "network_error", Message: err.Error()}
|
|
331
|
+
}
|
|
350
332
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
Message: strings.TrimSpace(string(body)),
|
|
333
|
+
func parseRetryAfter(value string) time.Duration {
|
|
334
|
+
if value == "" {
|
|
335
|
+
return 0
|
|
355
336
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
337
|
+
if seconds, err := strconv.ParseFloat(value, 64); err == nil && seconds >= 0 {
|
|
338
|
+
delay := time.Duration(seconds * float64(time.Second))
|
|
339
|
+
if delay > 30*time.Second {
|
|
340
|
+
return 30 * time.Second
|
|
341
|
+
}
|
|
342
|
+
return delay
|
|
362
343
|
}
|
|
363
|
-
if err :=
|
|
364
|
-
|
|
365
|
-
|
|
344
|
+
if when, err := http.ParseTime(value); err == nil {
|
|
345
|
+
delay := time.Until(when)
|
|
346
|
+
if delay > 30*time.Second {
|
|
347
|
+
return 30 * time.Second
|
|
366
348
|
}
|
|
367
|
-
if
|
|
368
|
-
|
|
369
|
-
} else if envelope.Error != "" {
|
|
370
|
-
sdkErr.Message = envelope.Error
|
|
349
|
+
if delay > 0 {
|
|
350
|
+
return delay
|
|
371
351
|
}
|
|
372
352
|
}
|
|
353
|
+
return 0
|
|
354
|
+
}
|
|
373
355
|
|
|
356
|
+
func parseErrorResponse(resp *http.Response, body []byte) error {
|
|
357
|
+
requestID := resp.Header.Get("X-Request-ID")
|
|
358
|
+
if requestID == "" {
|
|
359
|
+
requestID = resp.Header.Get("Request-ID")
|
|
360
|
+
}
|
|
361
|
+
sdkErr := &SDKError{
|
|
362
|
+
Status: resp.StatusCode, RequestID: requestID,
|
|
363
|
+
Code: "http_error", Message: strings.TrimSpace(string(body)),
|
|
364
|
+
}
|
|
365
|
+
var envelope struct {
|
|
366
|
+
Code string `json:"code"`
|
|
367
|
+
Message string `json:"message"`
|
|
368
|
+
Error string `json:"error"`
|
|
369
|
+
RequestID string `json:"request_id"`
|
|
370
|
+
}
|
|
371
|
+
if err := json.Unmarshal(body, &envelope); err == nil {
|
|
372
|
+
if envelope.Code != "" { sdkErr.Code = envelope.Code } else if envelope.Error != "" { sdkErr.Code = envelope.Error }
|
|
373
|
+
if envelope.Message != "" { sdkErr.Message = envelope.Message }
|
|
374
|
+
if envelope.RequestID != "" { sdkErr.RequestID = envelope.RequestID }
|
|
375
|
+
}
|
|
374
376
|
if sdkErr.Message == "" {
|
|
375
377
|
sdkErr.Message = fmt.Sprintf("HTTP %d: %s", resp.StatusCode, resp.Status)
|
|
376
378
|
}
|
|
377
|
-
|
|
378
379
|
return sdkErr
|
|
379
380
|
}
|
package/templates/go/types.hbs
CHANGED
|
@@ -1,69 +1,35 @@
|
|
|
1
1
|
package {{pkgName}}
|
|
2
2
|
|
|
3
|
-
{{#if
|
|
4
|
-
import
|
|
5
|
-
"time"
|
|
6
|
-
)
|
|
3
|
+
{{#if needsTime}}
|
|
4
|
+
import "time"
|
|
7
5
|
{{/if}}
|
|
8
6
|
|
|
9
7
|
{{#each schemas}}
|
|
10
|
-
{{#if
|
|
11
|
-
{{
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
{{#if external}}
|
|
9
|
+
// {{name}} is supplied by an external schema package in the source manifest.
|
|
10
|
+
type {{name}} = interface{}
|
|
11
|
+
|
|
12
|
+
{{else if isEnum}}
|
|
13
|
+
// {{name}}{{#if description}} {{description}}{{/if}}
|
|
14
|
+
type {{name}} {{enumType}}
|
|
14
15
|
|
|
15
16
|
const (
|
|
16
17
|
{{#each enumValues}}
|
|
17
|
-
{{pascalCase ../name}}{{pascalCase
|
|
18
|
+
{{pascalCase ../name}}{{pascalCase name}} {{../name}} = {{{value}}}
|
|
18
19
|
{{/each}}
|
|
19
20
|
)
|
|
20
21
|
|
|
21
22
|
{{else if isUnionType}}
|
|
22
|
-
// {{name}}
|
|
23
|
-
type {{name}}
|
|
24
|
-
value interface{}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
{{#each unionMembers}}
|
|
28
|
-
// New{{../name}}From{{this}} creates a {{../name}} from a {{this}} value.
|
|
29
|
-
func New{{../name}}From{{this}}(v {{this}}) {{../name}} {
|
|
30
|
-
return {{../name}}{value: v}
|
|
31
|
-
}
|
|
32
|
-
{{/each}}
|
|
33
|
-
|
|
34
|
-
// Value returns the underlying value.
|
|
35
|
-
func (u {{name}}) Value() interface{} {
|
|
36
|
-
return u.value
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// UnmarshalJSON implements json.Unmarshaler for {{name}}.
|
|
40
|
-
func (u *{{name}}) UnmarshalJSON(data []byte) error {
|
|
41
|
-
{{#each unionMembers}}
|
|
42
|
-
var v{{@index}} {{this}}
|
|
43
|
-
if err := json.Unmarshal(data, &v{{@index}}); err == nil {
|
|
44
|
-
u.value = v{{@index}}
|
|
45
|
-
return nil
|
|
46
|
-
}
|
|
47
|
-
{{/each}}
|
|
48
|
-
return fmt.Errorf("unable to unmarshal {{name}} from %s", string(data))
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// MarshalJSON implements json.Marshaler for {{name}}.
|
|
52
|
-
func (u {{name}}) MarshalJSON() ([]byte, error) {
|
|
53
|
-
return json.Marshal(u.value)
|
|
54
|
-
}
|
|
23
|
+
// {{name}}{{#if description}} {{description}}{{/if}}
|
|
24
|
+
type {{name}} interface{}
|
|
55
25
|
|
|
56
26
|
{{else if isIntersectionType}}
|
|
57
|
-
// {{name}}
|
|
58
|
-
type {{name}}
|
|
59
|
-
{{#each intersectionMembers}}
|
|
60
|
-
{{this}}
|
|
61
|
-
{{/each}}
|
|
62
|
-
}
|
|
27
|
+
// {{name}}{{#if description}} {{description}}{{/if}}
|
|
28
|
+
type {{name}} map[string]interface{}
|
|
63
29
|
|
|
64
30
|
{{else if isTypeAlias}}
|
|
65
|
-
// {{name}}
|
|
66
|
-
type {{name}} = {{
|
|
31
|
+
// {{name}}{{#if description}} {{description}}{{/if}}
|
|
32
|
+
type {{name}} = {{aliasType}}
|
|
67
33
|
|
|
68
34
|
{{else}}
|
|
69
35
|
{{#if description}}
|
|
@@ -71,10 +37,8 @@ type {{name}} = {{additionalPropertiesType}}
|
|
|
71
37
|
{{/if}}
|
|
72
38
|
type {{name}} struct {
|
|
73
39
|
{{#each properties}}
|
|
74
|
-
{{pascalCase name}} {{#if
|
|
40
|
+
{{pascalCase name}} {{#if optional}}*{{/if}}{{targetType}} `json:"{{name}}{{#if optional}},omitempty{{/if}}"`{{#if description}} // {{description}}{{/if}}
|
|
75
41
|
{{/each}}
|
|
76
42
|
}
|
|
77
|
-
{{/if}}
|
|
78
|
-
|
|
79
43
|
{{/if}}
|
|
80
44
|
{{/each}}
|
package/templates/go/utils.hbs
CHANGED
|
@@ -11,9 +11,10 @@ import (
|
|
|
11
11
|
// replacements is pairs of (placeholder, value).
|
|
12
12
|
func buildPath(template string, replacements ...string) string {
|
|
13
13
|
for i := 0; i < len(replacements); i += 2 {
|
|
14
|
-
|
|
14
|
+
name := replacements[i]
|
|
15
15
|
value := url.PathEscape(replacements[i+1])
|
|
16
|
-
template = strings.Replace(template,
|
|
16
|
+
template = strings.Replace(template, ":"+name, value, 1)
|
|
17
|
+
template = strings.Replace(template, "${"+name+"}", value, 1)
|
|
17
18
|
}
|
|
18
19
|
return template
|
|
19
20
|
}
|