airbyte-agent-hubspot 0.15.28__py3-none-any.whl → 0.15.43__py3-none-any.whl
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.
- airbyte_agent_hubspot/__init__.py +101 -26
- airbyte_agent_hubspot/_vendored/connector_sdk/auth_strategies.py +2 -5
- airbyte_agent_hubspot/_vendored/connector_sdk/auth_template.py +1 -1
- airbyte_agent_hubspot/_vendored/connector_sdk/cloud_utils/client.py +26 -26
- airbyte_agent_hubspot/_vendored/connector_sdk/connector_model_loader.py +11 -4
- airbyte_agent_hubspot/_vendored/connector_sdk/constants.py +1 -1
- airbyte_agent_hubspot/_vendored/connector_sdk/executor/hosted_executor.py +10 -11
- airbyte_agent_hubspot/_vendored/connector_sdk/executor/local_executor.py +126 -17
- airbyte_agent_hubspot/_vendored/connector_sdk/extensions.py +43 -5
- airbyte_agent_hubspot/_vendored/connector_sdk/http/response.py +2 -0
- airbyte_agent_hubspot/_vendored/connector_sdk/introspection.py +262 -0
- airbyte_agent_hubspot/_vendored/connector_sdk/logging/logger.py +9 -9
- airbyte_agent_hubspot/_vendored/connector_sdk/logging/types.py +10 -10
- airbyte_agent_hubspot/_vendored/connector_sdk/observability/config.py +179 -0
- airbyte_agent_hubspot/_vendored/connector_sdk/observability/models.py +6 -6
- airbyte_agent_hubspot/_vendored/connector_sdk/observability/session.py +41 -32
- airbyte_agent_hubspot/_vendored/connector_sdk/performance/metrics.py +3 -3
- airbyte_agent_hubspot/_vendored/connector_sdk/schema/base.py +20 -18
- airbyte_agent_hubspot/_vendored/connector_sdk/schema/components.py +59 -58
- airbyte_agent_hubspot/_vendored/connector_sdk/schema/connector.py +22 -33
- airbyte_agent_hubspot/_vendored/connector_sdk/schema/extensions.py +103 -10
- airbyte_agent_hubspot/_vendored/connector_sdk/schema/operations.py +32 -32
- airbyte_agent_hubspot/_vendored/connector_sdk/schema/security.py +44 -34
- airbyte_agent_hubspot/_vendored/connector_sdk/secrets.py +2 -2
- airbyte_agent_hubspot/_vendored/connector_sdk/telemetry/events.py +9 -8
- airbyte_agent_hubspot/_vendored/connector_sdk/telemetry/tracker.py +9 -5
- airbyte_agent_hubspot/_vendored/connector_sdk/types.py +7 -3
- airbyte_agent_hubspot/connector.py +182 -87
- airbyte_agent_hubspot/connector_model.py +17 -12
- airbyte_agent_hubspot/models.py +28 -28
- airbyte_agent_hubspot/types.py +45 -45
- {airbyte_agent_hubspot-0.15.28.dist-info → airbyte_agent_hubspot-0.15.43.dist-info}/METADATA +16 -17
- {airbyte_agent_hubspot-0.15.28.dist-info → airbyte_agent_hubspot-0.15.43.dist-info}/RECORD +34 -32
- {airbyte_agent_hubspot-0.15.28.dist-info → airbyte_agent_hubspot-0.15.43.dist-info}/WHEEL +0 -0
|
@@ -7,7 +7,7 @@ References:
|
|
|
7
7
|
- https://spec.openapis.org/oas/v3.1.0#parameter-object
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
from typing import Any, Dict, List, Literal,
|
|
10
|
+
from typing import Any, Dict, List, Literal, Union
|
|
11
11
|
|
|
12
12
|
from pydantic import BaseModel, ConfigDict, Field
|
|
13
13
|
|
|
@@ -30,43 +30,44 @@ class Schema(BaseModel):
|
|
|
30
30
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
31
31
|
|
|
32
32
|
# Core JSON Schema fields
|
|
33
|
-
type:
|
|
34
|
-
format:
|
|
35
|
-
title:
|
|
36
|
-
description:
|
|
37
|
-
default:
|
|
38
|
-
example:
|
|
33
|
+
type: str | None = None
|
|
34
|
+
format: str | None = None
|
|
35
|
+
title: str | None = None
|
|
36
|
+
description: str | None = None
|
|
37
|
+
default: Any | None = None
|
|
38
|
+
example: Any | None = None
|
|
39
39
|
|
|
40
40
|
# Object properties
|
|
41
41
|
properties: Dict[str, Any] = Field(default_factory=dict) # May contain $ref
|
|
42
42
|
required: List[str] = Field(default_factory=list)
|
|
43
|
-
additional_properties:
|
|
43
|
+
additional_properties: Any | None = Field(None, alias="additionalProperties")
|
|
44
44
|
|
|
45
45
|
# Array properties
|
|
46
|
-
items:
|
|
46
|
+
items: Any | None = None # May be Schema or $ref
|
|
47
47
|
|
|
48
48
|
# Validation
|
|
49
|
-
enum:
|
|
50
|
-
min_length:
|
|
51
|
-
max_length:
|
|
52
|
-
minimum:
|
|
53
|
-
maximum:
|
|
54
|
-
pattern:
|
|
49
|
+
enum: List[Any] | None = None
|
|
50
|
+
min_length: int | None = Field(None, alias="minLength")
|
|
51
|
+
max_length: int | None = Field(None, alias="maxLength")
|
|
52
|
+
minimum: float | None = None
|
|
53
|
+
maximum: float | None = None
|
|
54
|
+
pattern: str | None = None
|
|
55
55
|
|
|
56
56
|
# Composition
|
|
57
|
-
all_of:
|
|
58
|
-
any_of:
|
|
59
|
-
one_of:
|
|
60
|
-
not_:
|
|
57
|
+
all_of: List[Any] | None = Field(None, alias="allOf")
|
|
58
|
+
any_of: List[Any] | None = Field(None, alias="anyOf")
|
|
59
|
+
one_of: List[Any] | None = Field(None, alias="oneOf")
|
|
60
|
+
not_: Any | None = Field(None, alias="not")
|
|
61
61
|
|
|
62
62
|
# Metadata
|
|
63
|
-
nullable:
|
|
64
|
-
read_only:
|
|
65
|
-
write_only:
|
|
66
|
-
deprecated:
|
|
63
|
+
nullable: bool | None = Field(None, deprecated="Use type union with null instead (OpenAPI 3.1)")
|
|
64
|
+
read_only: bool | None = Field(None, alias="readOnly")
|
|
65
|
+
write_only: bool | None = Field(None, alias="writeOnly")
|
|
66
|
+
deprecated: bool | None = None
|
|
67
67
|
|
|
68
|
-
# Airbyte
|
|
69
|
-
x_airbyte_entity_name:
|
|
68
|
+
# Airbyte extensions
|
|
69
|
+
x_airbyte_entity_name: str | None = Field(None, alias="x-airbyte-entity-name")
|
|
70
|
+
x_airbyte_stream_name: str | None = Field(None, alias="x-airbyte-stream-name")
|
|
70
71
|
|
|
71
72
|
|
|
72
73
|
class Parameter(BaseModel):
|
|
@@ -80,19 +81,19 @@ class Parameter(BaseModel):
|
|
|
80
81
|
|
|
81
82
|
name: str
|
|
82
83
|
in_: Literal["query", "header", "path", "cookie"] = Field(alias="in")
|
|
83
|
-
description:
|
|
84
|
-
required:
|
|
85
|
-
deprecated:
|
|
86
|
-
allow_empty_value:
|
|
84
|
+
description: str | None = None
|
|
85
|
+
required: bool | None = None
|
|
86
|
+
deprecated: bool | None = None
|
|
87
|
+
allow_empty_value: bool | None = Field(None, alias="allowEmptyValue")
|
|
87
88
|
|
|
88
89
|
# Schema can be inline or reference
|
|
89
|
-
schema_:
|
|
90
|
+
schema_: Dict[str, Any] | None = Field(None, alias="schema")
|
|
90
91
|
|
|
91
92
|
# Style and examples
|
|
92
|
-
style:
|
|
93
|
-
explode:
|
|
94
|
-
example:
|
|
95
|
-
examples:
|
|
93
|
+
style: str | None = None
|
|
94
|
+
explode: bool | None = None
|
|
95
|
+
example: Any | None = None
|
|
96
|
+
examples: Dict[str, Any] | None = None
|
|
96
97
|
|
|
97
98
|
|
|
98
99
|
class MediaType(BaseModel):
|
|
@@ -104,10 +105,10 @@ class MediaType(BaseModel):
|
|
|
104
105
|
|
|
105
106
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
106
107
|
|
|
107
|
-
schema_:
|
|
108
|
-
example:
|
|
109
|
-
examples:
|
|
110
|
-
encoding:
|
|
108
|
+
schema_: Dict[str, Any] | None = Field(None, alias="schema")
|
|
109
|
+
example: Any | None = None
|
|
110
|
+
examples: Dict[str, Any] | None = None
|
|
111
|
+
encoding: Dict[str, Any] | None = None
|
|
111
112
|
|
|
112
113
|
|
|
113
114
|
class GraphQLBodyConfig(BaseModel):
|
|
@@ -124,12 +125,12 @@ class GraphQLBodyConfig(BaseModel):
|
|
|
124
125
|
...,
|
|
125
126
|
description="GraphQL query or mutation string with optional template placeholders (e.g., {{ variable }})",
|
|
126
127
|
)
|
|
127
|
-
variables:
|
|
128
|
+
variables: Dict[str, Any] | None = Field(
|
|
128
129
|
None,
|
|
129
130
|
description="Variables to substitute in the GraphQL query using template syntax (e.g., {{ param_name }})",
|
|
130
131
|
)
|
|
131
|
-
operationName:
|
|
132
|
-
default_fields:
|
|
132
|
+
operationName: str | None = Field(None, description="Operation name for queries with multiple operations")
|
|
133
|
+
default_fields: Union[str, List[str]] | None = Field(
|
|
133
134
|
None,
|
|
134
135
|
description="Default fields to select if not provided in request parameters. Can be a string or array of field names.",
|
|
135
136
|
)
|
|
@@ -155,7 +156,7 @@ class PathOverrideConfig(BaseModel):
|
|
|
155
156
|
|
|
156
157
|
path: str = Field(
|
|
157
158
|
...,
|
|
158
|
-
description=("Actual HTTP path to use for requests (e.g., '/graphql').
|
|
159
|
+
description=("Actual HTTP path to use for requests (e.g., '/graphql'). Must start with '/'"),
|
|
159
160
|
)
|
|
160
161
|
|
|
161
162
|
|
|
@@ -172,17 +173,17 @@ class RequestBody(BaseModel):
|
|
|
172
173
|
|
|
173
174
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
174
175
|
|
|
175
|
-
description:
|
|
176
|
+
description: str | None = None
|
|
176
177
|
content: Dict[str, MediaType] = Field(default_factory=dict)
|
|
177
|
-
required:
|
|
178
|
+
required: bool | None = None
|
|
178
179
|
|
|
179
180
|
# Airbyte extensions for GraphQL support
|
|
180
181
|
# See connector_sdk.extensions for AIRBYTE_BODY_TYPE constant
|
|
181
|
-
x_airbyte_body_type:
|
|
182
|
+
x_airbyte_body_type: BodyTypeConfig | None = Field(
|
|
182
183
|
None,
|
|
183
184
|
alias="x-airbyte-body-type", # AIRBYTE_BODY_TYPE
|
|
184
185
|
description=(
|
|
185
|
-
"Body type and configuration. Contains 'type' field (e.g., 'graphql')
|
|
186
|
+
"Body type and configuration. Contains 'type' field (e.g., 'graphql') and type-specific configuration (query, variables, etc.)."
|
|
186
187
|
),
|
|
187
188
|
)
|
|
188
189
|
|
|
@@ -196,11 +197,11 @@ class Header(BaseModel):
|
|
|
196
197
|
|
|
197
198
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
198
199
|
|
|
199
|
-
description:
|
|
200
|
-
required:
|
|
201
|
-
deprecated:
|
|
202
|
-
schema_:
|
|
203
|
-
example:
|
|
200
|
+
description: str | None = None
|
|
201
|
+
required: bool | None = None
|
|
202
|
+
deprecated: bool | None = None
|
|
203
|
+
schema_: Dict[str, Any] | None = Field(None, alias="schema")
|
|
204
|
+
example: Any | None = None
|
|
204
205
|
|
|
205
206
|
|
|
206
207
|
class Response(BaseModel):
|
|
@@ -213,9 +214,9 @@ class Response(BaseModel):
|
|
|
213
214
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
214
215
|
|
|
215
216
|
description: str
|
|
216
|
-
headers:
|
|
217
|
-
content:
|
|
218
|
-
links:
|
|
217
|
+
headers: Dict[str, Header] | None = None
|
|
218
|
+
content: Dict[str, MediaType] | None = None
|
|
219
|
+
links: Dict[str, Any] | None = None
|
|
219
220
|
|
|
220
221
|
|
|
221
222
|
class Components(BaseModel):
|
|
@@ -230,9 +231,9 @@ class Components(BaseModel):
|
|
|
230
231
|
schemas: Dict[str, Schema] = Field(default_factory=dict)
|
|
231
232
|
responses: Dict[str, Response] = Field(default_factory=dict)
|
|
232
233
|
parameters: Dict[str, Parameter] = Field(default_factory=dict)
|
|
233
|
-
examples:
|
|
234
|
+
examples: Dict[str, Any] | None = None
|
|
234
235
|
request_bodies: Dict[str, RequestBody] = Field(default_factory=dict, alias="requestBodies")
|
|
235
|
-
headers:
|
|
236
|
+
headers: Dict[str, Header] | None = None
|
|
236
237
|
security_schemes: Dict[str, SecurityScheme] = Field(default_factory=dict, alias="securitySchemes")
|
|
237
|
-
links:
|
|
238
|
-
callbacks:
|
|
238
|
+
links: Dict[str, Any] | None = None
|
|
239
|
+
callbacks: Dict[str, Any] | None = None
|
|
@@ -7,6 +7,7 @@ References:
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
from collections.abc import Iterator
|
|
10
11
|
from typing import Any
|
|
11
12
|
|
|
12
13
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
@@ -15,7 +16,7 @@ from ..constants import OPENAPI_VERSION_PREFIX
|
|
|
15
16
|
|
|
16
17
|
from .base import Info, Server
|
|
17
18
|
from .components import Components
|
|
18
|
-
from .operations import PathItem
|
|
19
|
+
from .operations import Operation, PathItem
|
|
19
20
|
from .security import SecurityRequirement
|
|
20
21
|
|
|
21
22
|
|
|
@@ -33,6 +34,10 @@ class Tag(BaseModel):
|
|
|
33
34
|
external_docs: dict[str, Any] | None = Field(None, alias="externalDocs")
|
|
34
35
|
|
|
35
36
|
|
|
37
|
+
# HTTP methods supported by OpenAPI operations
|
|
38
|
+
HTTP_METHODS = frozenset({"get", "post", "put", "patch", "delete", "options", "head", "trace"})
|
|
39
|
+
|
|
40
|
+
|
|
36
41
|
class ExternalDocs(BaseModel):
|
|
37
42
|
"""
|
|
38
43
|
External documentation reference.
|
|
@@ -79,7 +84,7 @@ class OpenAPIConnector(BaseModel):
|
|
|
79
84
|
raise ValueError(f"OpenAPI version must be {OPENAPI_VERSION_PREFIX}x, got: {v}")
|
|
80
85
|
return v
|
|
81
86
|
|
|
82
|
-
def get_entity_operations(self, entity_name: str) -> list[tuple[str, str,
|
|
87
|
+
def get_entity_operations(self, entity_name: str) -> list[tuple[str, str, Operation]]:
|
|
83
88
|
"""
|
|
84
89
|
Get all operations for a specific entity.
|
|
85
90
|
|
|
@@ -89,22 +94,7 @@ class OpenAPIConnector(BaseModel):
|
|
|
89
94
|
Returns:
|
|
90
95
|
List of tuples: (path, method, operation)
|
|
91
96
|
"""
|
|
92
|
-
|
|
93
|
-
for path, path_item in self.paths.items():
|
|
94
|
-
for method in [
|
|
95
|
-
"get",
|
|
96
|
-
"post",
|
|
97
|
-
"put",
|
|
98
|
-
"patch",
|
|
99
|
-
"delete",
|
|
100
|
-
"options",
|
|
101
|
-
"head",
|
|
102
|
-
"trace",
|
|
103
|
-
]:
|
|
104
|
-
operation = getattr(path_item, method, None)
|
|
105
|
-
if operation and operation.x_airbyte_entity == entity_name:
|
|
106
|
-
results.append((path, method, operation))
|
|
107
|
-
return results
|
|
97
|
+
return [(path, method, op) for path, method, op in self._iter_operations() if op.x_airbyte_entity == entity_name]
|
|
108
98
|
|
|
109
99
|
def list_entities(self) -> list[str]:
|
|
110
100
|
"""
|
|
@@ -113,19 +103,18 @@ class OpenAPIConnector(BaseModel):
|
|
|
113
103
|
Returns:
|
|
114
104
|
Sorted list of unique entity names
|
|
115
105
|
"""
|
|
116
|
-
entities =
|
|
117
|
-
for path_item in self.paths.values():
|
|
118
|
-
for method in [
|
|
119
|
-
"get",
|
|
120
|
-
"post",
|
|
121
|
-
"put",
|
|
122
|
-
"patch",
|
|
123
|
-
"delete",
|
|
124
|
-
"options",
|
|
125
|
-
"head",
|
|
126
|
-
"trace",
|
|
127
|
-
]:
|
|
128
|
-
operation = getattr(path_item, method, None)
|
|
129
|
-
if operation and operation.x_airbyte_entity:
|
|
130
|
-
entities.add(operation.x_airbyte_entity)
|
|
106
|
+
entities = {op.x_airbyte_entity for _, _, op in self._iter_operations() if op.x_airbyte_entity}
|
|
131
107
|
return sorted(entities)
|
|
108
|
+
|
|
109
|
+
def _iter_operations(self) -> Iterator[tuple[str, str, Operation]]:
|
|
110
|
+
"""
|
|
111
|
+
Iterate over all operations in the spec.
|
|
112
|
+
|
|
113
|
+
Yields:
|
|
114
|
+
Tuples of (path, method, operation) for each defined operation
|
|
115
|
+
"""
|
|
116
|
+
for path, path_item in self.paths.items():
|
|
117
|
+
for method in HTTP_METHODS:
|
|
118
|
+
operation = getattr(path_item, method, None)
|
|
119
|
+
if operation:
|
|
120
|
+
yield path, method, operation
|
|
@@ -12,9 +12,9 @@ to Operation, Schema, or other models when their respective features
|
|
|
12
12
|
are implemented.
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
-
from typing import Literal
|
|
15
|
+
from typing import Literal
|
|
16
16
|
|
|
17
|
-
from pydantic import BaseModel, ConfigDict
|
|
17
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class PaginationConfig(BaseModel):
|
|
@@ -33,22 +33,22 @@ class PaginationConfig(BaseModel):
|
|
|
33
33
|
limit_param: str = "limit"
|
|
34
34
|
|
|
35
35
|
# Cursor-based pagination
|
|
36
|
-
cursor_param:
|
|
37
|
-
cursor_source:
|
|
38
|
-
cursor_path:
|
|
36
|
+
cursor_param: str | None = None
|
|
37
|
+
cursor_source: Literal["body", "headers"] | None = "body"
|
|
38
|
+
cursor_path: str | None = None
|
|
39
39
|
|
|
40
40
|
# Offset-based pagination
|
|
41
|
-
offset_param:
|
|
41
|
+
offset_param: str | None = None
|
|
42
42
|
|
|
43
43
|
# Page-based pagination
|
|
44
|
-
page_param:
|
|
44
|
+
page_param: str | None = None
|
|
45
45
|
|
|
46
46
|
# Response parsing
|
|
47
47
|
data_path: str = "data"
|
|
48
|
-
has_more_path:
|
|
48
|
+
has_more_path: str | None = None
|
|
49
49
|
|
|
50
50
|
# Limits
|
|
51
|
-
max_page_size:
|
|
51
|
+
max_page_size: int | None = None
|
|
52
52
|
default_page_size: int = 100
|
|
53
53
|
|
|
54
54
|
|
|
@@ -66,7 +66,7 @@ class RateLimitConfig(BaseModel):
|
|
|
66
66
|
|
|
67
67
|
max_requests: int
|
|
68
68
|
time_window_seconds: int
|
|
69
|
-
retry_after_header:
|
|
69
|
+
retry_after_header: str | None = "Retry-After"
|
|
70
70
|
respect_retry_after: bool = True
|
|
71
71
|
|
|
72
72
|
|
|
@@ -107,3 +107,96 @@ class RetryConfig(BaseModel):
|
|
|
107
107
|
# Header-based delay extraction
|
|
108
108
|
retry_after_header: str = "Retry-After"
|
|
109
109
|
retry_after_format: Literal["seconds", "milliseconds", "unix_timestamp"] = "seconds"
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class CacheFieldConfig(BaseModel):
|
|
113
|
+
"""
|
|
114
|
+
Field configuration for cache mapping.
|
|
115
|
+
|
|
116
|
+
Defines a single field in a cache entity, with optional name aliasing
|
|
117
|
+
to map between user-facing field names and cache storage names.
|
|
118
|
+
|
|
119
|
+
Used in x-airbyte-cache extension for api_search operations.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
123
|
+
|
|
124
|
+
name: str
|
|
125
|
+
x_airbyte_name: str | None = Field(default=None, alias="x-airbyte-name")
|
|
126
|
+
type: str | list[str]
|
|
127
|
+
description: str
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def cache_name(self) -> str:
|
|
131
|
+
"""Return cache name, falling back to name if alias not specified."""
|
|
132
|
+
return self.x_airbyte_name or self.name
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class CacheEntityConfig(BaseModel):
|
|
136
|
+
"""
|
|
137
|
+
Entity configuration for cache mapping.
|
|
138
|
+
|
|
139
|
+
Defines a cache-enabled entity with its fields and optional name aliasing
|
|
140
|
+
to map between user-facing entity names and cache storage names.
|
|
141
|
+
|
|
142
|
+
Used in x-airbyte-cache extension for api_search operations.
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
146
|
+
|
|
147
|
+
entity: str
|
|
148
|
+
x_airbyte_name: str | None = Field(default=None, alias="x-airbyte-name")
|
|
149
|
+
fields: list[CacheFieldConfig]
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def cache_name(self) -> str:
|
|
153
|
+
"""Return cache entity name, falling back to entity if alias not specified."""
|
|
154
|
+
return self.x_airbyte_name or self.entity
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class CacheConfig(BaseModel):
|
|
158
|
+
"""
|
|
159
|
+
Cache configuration extension (x-airbyte-cache).
|
|
160
|
+
|
|
161
|
+
Defines cache-enabled entities and their field mappings for api_search operations.
|
|
162
|
+
Supports optional name aliasing via x-airbyte-name for both entities and fields,
|
|
163
|
+
enabling bidirectional mapping between user-facing names and cache storage names.
|
|
164
|
+
|
|
165
|
+
This extension is added to the Info model and provides field-level mapping for
|
|
166
|
+
search operations that use cached data.
|
|
167
|
+
|
|
168
|
+
Example YAML usage:
|
|
169
|
+
info:
|
|
170
|
+
title: Stripe API
|
|
171
|
+
x-airbyte-cache:
|
|
172
|
+
entities:
|
|
173
|
+
- entity: customers
|
|
174
|
+
stream: customers
|
|
175
|
+
fields:
|
|
176
|
+
- name: email
|
|
177
|
+
type: ["null", "string"]
|
|
178
|
+
description: "Customer email address"
|
|
179
|
+
- name: customer_name
|
|
180
|
+
x-airbyte-name: name
|
|
181
|
+
type: ["null", "string"]
|
|
182
|
+
description: "Customer full name"
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
186
|
+
|
|
187
|
+
entities: list[CacheEntityConfig]
|
|
188
|
+
|
|
189
|
+
def get_entity_mapping(self, user_entity: str) -> CacheEntityConfig | None:
|
|
190
|
+
"""
|
|
191
|
+
Get entity config by user-facing name.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
user_entity: User-facing entity name to look up
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
CacheEntityConfig if found, None otherwise
|
|
198
|
+
"""
|
|
199
|
+
for entity in self.entities:
|
|
200
|
+
if entity.entity == user_entity:
|
|
201
|
+
return entity
|
|
202
|
+
return None
|
|
@@ -6,7 +6,7 @@ References:
|
|
|
6
6
|
- https://spec.openapis.org/oas/v3.1.0#path-item-object
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
from typing import Any, Dict, List
|
|
9
|
+
from typing import Any, Dict, List
|
|
10
10
|
|
|
11
11
|
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
12
12
|
|
|
@@ -34,38 +34,38 @@ class Operation(BaseModel):
|
|
|
34
34
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
35
35
|
|
|
36
36
|
# Standard OpenAPI fields
|
|
37
|
-
tags:
|
|
38
|
-
summary:
|
|
39
|
-
description:
|
|
40
|
-
external_docs:
|
|
41
|
-
operation_id:
|
|
42
|
-
parameters:
|
|
43
|
-
request_body:
|
|
37
|
+
tags: List[str] | None = None
|
|
38
|
+
summary: str | None = None
|
|
39
|
+
description: str | None = None
|
|
40
|
+
external_docs: Dict[str, Any] | None = Field(None, alias="externalDocs")
|
|
41
|
+
operation_id: str | None = Field(None, alias="operationId")
|
|
42
|
+
parameters: List[Parameter] | None = None
|
|
43
|
+
request_body: RequestBody | None = Field(None, alias="requestBody")
|
|
44
44
|
responses: Dict[str, Response] = Field(default_factory=dict)
|
|
45
|
-
callbacks:
|
|
46
|
-
deprecated:
|
|
47
|
-
security:
|
|
48
|
-
servers:
|
|
45
|
+
callbacks: Dict[str, Any] | None = None
|
|
46
|
+
deprecated: bool | None = None
|
|
47
|
+
security: List[SecurityRequirement] | None = None
|
|
48
|
+
servers: List[Any] | None = None # Can override root servers
|
|
49
49
|
|
|
50
50
|
# Airbyte extensions
|
|
51
51
|
x_airbyte_entity: str = Field(..., alias="x-airbyte-entity")
|
|
52
52
|
x_airbyte_action: ActionTypeLiteral = Field(..., alias="x-airbyte-action")
|
|
53
|
-
x_airbyte_path_override:
|
|
53
|
+
x_airbyte_path_override: PathOverrideConfig | None = Field(
|
|
54
54
|
None,
|
|
55
55
|
alias="x-airbyte-path-override",
|
|
56
|
-
description=("Override path for HTTP requests when OpenAPI path
|
|
56
|
+
description=("Override path for HTTP requests when OpenAPI path differs from actual endpoint"),
|
|
57
57
|
)
|
|
58
|
-
x_airbyte_record_extractor:
|
|
58
|
+
x_airbyte_record_extractor: str | None = Field(
|
|
59
59
|
None,
|
|
60
60
|
alias="x-airbyte-record-extractor",
|
|
61
61
|
description=(
|
|
62
62
|
"JSONPath expression to extract records from API response envelopes. "
|
|
63
63
|
"When specified, executor extracts data at this path instead of returning "
|
|
64
|
-
"full response. Returns array for list/
|
|
64
|
+
"full response. Returns array for list/api_search actions, single record for "
|
|
65
65
|
"get/create/update/delete actions."
|
|
66
66
|
),
|
|
67
67
|
)
|
|
68
|
-
x_airbyte_meta_extractor:
|
|
68
|
+
x_airbyte_meta_extractor: Dict[str, str] | None = Field(
|
|
69
69
|
None,
|
|
70
70
|
alias="x-airbyte-meta-extractor",
|
|
71
71
|
description=(
|
|
@@ -76,8 +76,8 @@ class Operation(BaseModel):
|
|
|
76
76
|
"Example: {'pagination': '$.pagination', 'request_id': '$.requestId'}"
|
|
77
77
|
),
|
|
78
78
|
)
|
|
79
|
-
x_airbyte_file_url:
|
|
80
|
-
x_airbyte_untested:
|
|
79
|
+
x_airbyte_file_url: str | None = Field(None, alias="x-airbyte-file-url")
|
|
80
|
+
x_airbyte_untested: bool | None = Field(
|
|
81
81
|
None,
|
|
82
82
|
alias="x-airbyte-untested",
|
|
83
83
|
description=(
|
|
@@ -127,20 +127,20 @@ class PathItem(BaseModel):
|
|
|
127
127
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
128
128
|
|
|
129
129
|
# Common fields for all operations
|
|
130
|
-
summary:
|
|
131
|
-
description:
|
|
132
|
-
servers:
|
|
133
|
-
parameters:
|
|
130
|
+
summary: str | None = None
|
|
131
|
+
description: str | None = None
|
|
132
|
+
servers: List[Any] | None = None
|
|
133
|
+
parameters: List[Parameter] | None = None
|
|
134
134
|
|
|
135
135
|
# HTTP methods (all optional)
|
|
136
|
-
get:
|
|
137
|
-
put:
|
|
138
|
-
post:
|
|
139
|
-
delete:
|
|
140
|
-
options:
|
|
141
|
-
head:
|
|
142
|
-
patch:
|
|
143
|
-
trace:
|
|
136
|
+
get: Operation | None = None
|
|
137
|
+
put: Operation | None = None
|
|
138
|
+
post: Operation | None = None
|
|
139
|
+
delete: Operation | None = None
|
|
140
|
+
options: Operation | None = None
|
|
141
|
+
head: Operation | None = None
|
|
142
|
+
patch: Operation | None = None
|
|
143
|
+
trace: Operation | None = None
|
|
144
144
|
|
|
145
145
|
# Reference support
|
|
146
|
-
ref:
|
|
146
|
+
ref: str | None = Field(None, alias="$ref")
|