airbyte-agent-stripe 0.5.28__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.
Files changed (55) hide show
  1. airbyte_agent_stripe/__init__.py +237 -0
  2. airbyte_agent_stripe/_vendored/__init__.py +1 -0
  3. airbyte_agent_stripe/_vendored/connector_sdk/__init__.py +82 -0
  4. airbyte_agent_stripe/_vendored/connector_sdk/auth_strategies.py +1123 -0
  5. airbyte_agent_stripe/_vendored/connector_sdk/auth_template.py +135 -0
  6. airbyte_agent_stripe/_vendored/connector_sdk/cloud_utils/__init__.py +5 -0
  7. airbyte_agent_stripe/_vendored/connector_sdk/cloud_utils/client.py +213 -0
  8. airbyte_agent_stripe/_vendored/connector_sdk/connector_model_loader.py +957 -0
  9. airbyte_agent_stripe/_vendored/connector_sdk/constants.py +78 -0
  10. airbyte_agent_stripe/_vendored/connector_sdk/exceptions.py +23 -0
  11. airbyte_agent_stripe/_vendored/connector_sdk/executor/__init__.py +31 -0
  12. airbyte_agent_stripe/_vendored/connector_sdk/executor/hosted_executor.py +197 -0
  13. airbyte_agent_stripe/_vendored/connector_sdk/executor/local_executor.py +1524 -0
  14. airbyte_agent_stripe/_vendored/connector_sdk/executor/models.py +190 -0
  15. airbyte_agent_stripe/_vendored/connector_sdk/extensions.py +655 -0
  16. airbyte_agent_stripe/_vendored/connector_sdk/http/__init__.py +37 -0
  17. airbyte_agent_stripe/_vendored/connector_sdk/http/adapters/__init__.py +9 -0
  18. airbyte_agent_stripe/_vendored/connector_sdk/http/adapters/httpx_adapter.py +251 -0
  19. airbyte_agent_stripe/_vendored/connector_sdk/http/config.py +98 -0
  20. airbyte_agent_stripe/_vendored/connector_sdk/http/exceptions.py +119 -0
  21. airbyte_agent_stripe/_vendored/connector_sdk/http/protocols.py +114 -0
  22. airbyte_agent_stripe/_vendored/connector_sdk/http/response.py +102 -0
  23. airbyte_agent_stripe/_vendored/connector_sdk/http_client.py +686 -0
  24. airbyte_agent_stripe/_vendored/connector_sdk/logging/__init__.py +11 -0
  25. airbyte_agent_stripe/_vendored/connector_sdk/logging/logger.py +264 -0
  26. airbyte_agent_stripe/_vendored/connector_sdk/logging/types.py +92 -0
  27. airbyte_agent_stripe/_vendored/connector_sdk/observability/__init__.py +11 -0
  28. airbyte_agent_stripe/_vendored/connector_sdk/observability/models.py +19 -0
  29. airbyte_agent_stripe/_vendored/connector_sdk/observability/redactor.py +81 -0
  30. airbyte_agent_stripe/_vendored/connector_sdk/observability/session.py +94 -0
  31. airbyte_agent_stripe/_vendored/connector_sdk/performance/__init__.py +6 -0
  32. airbyte_agent_stripe/_vendored/connector_sdk/performance/instrumentation.py +57 -0
  33. airbyte_agent_stripe/_vendored/connector_sdk/performance/metrics.py +93 -0
  34. airbyte_agent_stripe/_vendored/connector_sdk/schema/__init__.py +75 -0
  35. airbyte_agent_stripe/_vendored/connector_sdk/schema/base.py +161 -0
  36. airbyte_agent_stripe/_vendored/connector_sdk/schema/components.py +238 -0
  37. airbyte_agent_stripe/_vendored/connector_sdk/schema/connector.py +131 -0
  38. airbyte_agent_stripe/_vendored/connector_sdk/schema/extensions.py +109 -0
  39. airbyte_agent_stripe/_vendored/connector_sdk/schema/operations.py +146 -0
  40. airbyte_agent_stripe/_vendored/connector_sdk/schema/security.py +213 -0
  41. airbyte_agent_stripe/_vendored/connector_sdk/secrets.py +182 -0
  42. airbyte_agent_stripe/_vendored/connector_sdk/telemetry/__init__.py +10 -0
  43. airbyte_agent_stripe/_vendored/connector_sdk/telemetry/config.py +32 -0
  44. airbyte_agent_stripe/_vendored/connector_sdk/telemetry/events.py +58 -0
  45. airbyte_agent_stripe/_vendored/connector_sdk/telemetry/tracker.py +151 -0
  46. airbyte_agent_stripe/_vendored/connector_sdk/types.py +241 -0
  47. airbyte_agent_stripe/_vendored/connector_sdk/utils.py +60 -0
  48. airbyte_agent_stripe/_vendored/connector_sdk/validation.py +822 -0
  49. airbyte_agent_stripe/connector.py +1579 -0
  50. airbyte_agent_stripe/connector_model.py +14869 -0
  51. airbyte_agent_stripe/models.py +2353 -0
  52. airbyte_agent_stripe/types.py +295 -0
  53. airbyte_agent_stripe-0.5.28.dist-info/METADATA +114 -0
  54. airbyte_agent_stripe-0.5.28.dist-info/RECORD +55 -0
  55. airbyte_agent_stripe-0.5.28.dist-info/WHEEL +4 -0
@@ -0,0 +1,93 @@
1
+ """Performance metrics tracking."""
2
+
3
+ import time
4
+ from contextlib import asynccontextmanager
5
+ from typing import Dict, Optional
6
+
7
+
8
+ class PerformanceMonitor:
9
+ """Monitor and track performance metrics for operations."""
10
+
11
+ def __init__(self):
12
+ """Initialize performance monitor."""
13
+ self._metrics: Dict[str, Dict[str, float]] = {}
14
+
15
+ def record(self, metric_name: str, duration: float):
16
+ """Record a metric.
17
+
18
+ Args:
19
+ metric_name: Name of the metric
20
+ duration: Duration in seconds
21
+ """
22
+ if metric_name not in self._metrics:
23
+ self._metrics[metric_name] = {
24
+ "count": 0,
25
+ "total": 0.0,
26
+ "min": float("inf"),
27
+ "max": 0.0,
28
+ }
29
+
30
+ metrics = self._metrics[metric_name]
31
+ metrics["count"] += 1
32
+ metrics["total"] += duration
33
+ metrics["min"] = min(metrics["min"], duration)
34
+ metrics["max"] = max(metrics["max"], duration)
35
+
36
+ def get_stats(self, metric_name: str) -> Optional[Dict[str, float]]:
37
+ """Get statistics for a metric.
38
+
39
+ Args:
40
+ metric_name: Name of the metric
41
+
42
+ Returns:
43
+ Dictionary with count, total, mean, min, max or None if metric not found
44
+ """
45
+ if metric_name not in self._metrics:
46
+ return None
47
+
48
+ metrics = self._metrics[metric_name]
49
+ return {
50
+ "count": metrics["count"],
51
+ "total": metrics["total"],
52
+ "mean": metrics["total"] / metrics["count"] if metrics["count"] > 0 else 0.0,
53
+ "min": metrics["min"] if metrics["min"] != float("inf") else 0.0,
54
+ "max": metrics["max"],
55
+ }
56
+
57
+ def get_all_stats(self) -> Dict[str, Dict[str, float]]:
58
+ """Get statistics for all metrics.
59
+
60
+ Returns:
61
+ Dictionary mapping metric names to their statistics
62
+ """
63
+ return {name: self.get_stats(name) for name in self._metrics.keys()}
64
+
65
+ def reset(self, metric_name: Optional[str] = None):
66
+ """Reset metrics.
67
+
68
+ Args:
69
+ metric_name: Specific metric to reset, or None to reset all
70
+ """
71
+ if metric_name:
72
+ if metric_name in self._metrics:
73
+ del self._metrics[metric_name]
74
+ else:
75
+ self._metrics.clear()
76
+
77
+ @asynccontextmanager
78
+ async def track(self, metric_name: str):
79
+ """Context manager for tracking operation duration.
80
+
81
+ Args:
82
+ metric_name: Name of the metric to track
83
+
84
+ Example:
85
+ async with monitor.track("api_call"):
86
+ result = await some_async_operation()
87
+ """
88
+ start_time = time.time()
89
+ try:
90
+ yield
91
+ finally:
92
+ duration = time.time() - start_time
93
+ self.record(metric_name, duration)
@@ -0,0 +1,75 @@
1
+ """
2
+ Pydantic 2 schema models for OpenAPI 3.0 connector specifications.
3
+
4
+ This package provides strongly-typed Pydantic models that mirror the OpenAPI 3.0
5
+ specification while supporting Airbyte-specific extensions.
6
+
7
+ Usage:
8
+ import yaml
9
+ from . import OpenAPIConnector
10
+
11
+ with open('connector.yaml') as f:
12
+ data = yaml.safe_load(f)
13
+
14
+ connector = OpenAPIConnector(**data)
15
+ print(connector.list_resources())
16
+ """
17
+
18
+ from .base import Contact, Info, License, Server, ServerVariable
19
+ from .components import (
20
+ Components,
21
+ Header,
22
+ MediaType,
23
+ Parameter,
24
+ RequestBody,
25
+ Response,
26
+ Schema,
27
+ )
28
+ from .connector import ExternalDocs, OpenAPIConnector, Tag
29
+ from .extensions import PaginationConfig, RateLimitConfig, RetryConfig
30
+ from .operations import Operation, PathItem
31
+ from .security import (
32
+ AirbyteAuthConfig,
33
+ AuthConfigFieldSpec,
34
+ AuthConfigOption,
35
+ OAuth2Flow,
36
+ OAuth2Flows,
37
+ SecurityRequirement,
38
+ SecurityScheme,
39
+ )
40
+
41
+ __all__ = [
42
+ # Root model
43
+ "OpenAPIConnector",
44
+ "Tag",
45
+ "ExternalDocs",
46
+ # Base models
47
+ "Info",
48
+ "Server",
49
+ "ServerVariable",
50
+ "Contact",
51
+ "License",
52
+ # Security models
53
+ "SecurityScheme",
54
+ "SecurityRequirement",
55
+ "OAuth2Flow",
56
+ "OAuth2Flows",
57
+ "AirbyteAuthConfig",
58
+ "AuthConfigOption",
59
+ "AuthConfigFieldSpec",
60
+ # Component models
61
+ "Components",
62
+ "Schema",
63
+ "Parameter",
64
+ "RequestBody",
65
+ "Response",
66
+ "MediaType",
67
+ "Header",
68
+ # Operation models
69
+ "PathItem",
70
+ "Operation",
71
+ # Extension models (for future use)
72
+ "PaginationConfig",
73
+ "RateLimitConfig",
74
+ "RetryConfig",
75
+ ]
@@ -0,0 +1,161 @@
1
+ """
2
+ Base OpenAPI 3.1 models: Info, Server, Contact, License.
3
+
4
+ References:
5
+ - https://spec.openapis.org/oas/v3.1.0#info-object
6
+ - https://spec.openapis.org/oas/v3.1.0#server-object
7
+ """
8
+
9
+ from enum import StrEnum
10
+ from typing import Dict, Optional
11
+ from uuid import UUID
12
+
13
+ from pydantic import BaseModel, ConfigDict, Field, field_validator
14
+ from pydantic_core import Url
15
+
16
+ from .extensions import RetryConfig
17
+
18
+
19
+ class ExampleQuestions(BaseModel):
20
+ """
21
+ Example questions for AI connector documentation.
22
+
23
+ Used to generate supported_questions.md and unsupported_questions.md files
24
+ that appear in the connector's README.
25
+ """
26
+
27
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
28
+
29
+ supported: list[str] = Field(
30
+ default_factory=list,
31
+ description="Example questions the connector can handle",
32
+ )
33
+ unsupported: list[str] = Field(
34
+ default_factory=list,
35
+ description="Example questions the connector cannot handle",
36
+ )
37
+
38
+
39
+ class Contact(BaseModel):
40
+ """
41
+ Contact information for the API.
42
+
43
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#contact-object
44
+ """
45
+
46
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
47
+
48
+ name: Optional[str] = None
49
+ url: Optional[str] = None
50
+ email: Optional[str] = None
51
+
52
+
53
+ class License(BaseModel):
54
+ """
55
+ License information for the API.
56
+
57
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#license-object
58
+ """
59
+
60
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
61
+
62
+ name: str
63
+ url: Optional[str] = None
64
+
65
+
66
+ class DocUrlType(StrEnum):
67
+ API_DEPRECATIONS = "api_deprecations"
68
+ API_REFERENCE = "api_reference"
69
+ API_RELEASE_HISTORY = "api_release_history"
70
+ AUTHENTICATION_GUIDE = "authentication_guide"
71
+ CHANGELOG = "changelog"
72
+ DATA_MODEL_REFERENCE = "data_model_reference"
73
+ DEVELOPER_COMMUNITY = "developer_community"
74
+ MIGRATION_GUIDE = "migration_guide"
75
+ OPENAPI_SPEC = "openapi_spec"
76
+ OTHER = "other"
77
+ PERMISSIONS_SCOPES = "permissions_scopes"
78
+ RATE_LIMITS = "rate_limits"
79
+ SQL_REFERENCE = "sql_reference"
80
+ STATUS_PAGE = "status_page"
81
+
82
+
83
+ class DocUrl(BaseModel):
84
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
85
+
86
+ url: str
87
+ type: DocUrlType
88
+ title: Optional[str] = None
89
+
90
+ @field_validator("url")
91
+ def validate_url(cls, v):
92
+ Url(v)
93
+ return v
94
+
95
+
96
+ class Info(BaseModel):
97
+ """
98
+ API metadata information.
99
+
100
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#info-object
101
+
102
+ Extensions:
103
+ - x-airbyte-connector-name: Name of the connector (Airbyte extension)
104
+ - x-airbyte-connector-id: UUID of the connector (Airbyte extension)
105
+ - x-airbyte-external-documentation-urls: List of external documentation URLs (Airbyte extension)
106
+ - x-airbyte-retry-config: Retry configuration for transient errors (Airbyte extension)
107
+ - x-airbyte-example-questions: Example questions for AI connector README (Airbyte extension)
108
+ """
109
+
110
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
111
+
112
+ title: str
113
+ version: str
114
+ description: Optional[str] = None
115
+ terms_of_service: Optional[str] = Field(None, alias="termsOfService")
116
+ contact: Optional[Contact] = None
117
+ license: Optional[License] = None
118
+
119
+ # Airbyte extension
120
+ x_airbyte_connector_name: Optional[str] = Field(None, alias="x-airbyte-connector-name")
121
+ x_airbyte_connector_id: Optional[UUID] = Field(None, alias="x-airbyte-connector-id")
122
+ x_airbyte_external_documentation_urls: list[DocUrl] = Field(..., alias="x-airbyte-external-documentation-urls")
123
+ x_airbyte_retry_config: Optional[RetryConfig] = Field(None, alias="x-airbyte-retry-config")
124
+ x_airbyte_example_questions: Optional[ExampleQuestions] = Field(None, alias="x-airbyte-example-questions")
125
+
126
+
127
+ class ServerVariable(BaseModel):
128
+ """
129
+ Variable for server URL templating.
130
+
131
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#server-variable-object
132
+ """
133
+
134
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
135
+
136
+ enum: Optional[list[str]] = None
137
+ default: str
138
+ description: Optional[str] = None
139
+
140
+
141
+ class Server(BaseModel):
142
+ """
143
+ Server URL and variable definitions.
144
+
145
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#server-object
146
+ """
147
+
148
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
149
+
150
+ url: str
151
+ description: Optional[str] = None
152
+ variables: Dict[str, ServerVariable] = Field(default_factory=dict)
153
+
154
+ @field_validator("url")
155
+ @classmethod
156
+ def validate_url(cls, v: str) -> str:
157
+ """Validate that server URL is properly formatted."""
158
+ if not v:
159
+ raise ValueError("Server URL cannot be empty")
160
+ # Allow both absolute URLs and relative paths
161
+ return v
@@ -0,0 +1,238 @@
1
+ """
2
+ Component models for OpenAPI 3.1: Schema, Parameter, RequestBody, Response, Components.
3
+
4
+ References:
5
+ - https://spec.openapis.org/oas/v3.1.0#components-object
6
+ - https://spec.openapis.org/oas/v3.1.0#schema-object
7
+ - https://spec.openapis.org/oas/v3.1.0#parameter-object
8
+ """
9
+
10
+ from typing import Any, Dict, List, Literal, Optional, Union
11
+
12
+ from pydantic import BaseModel, ConfigDict, Field
13
+
14
+ from .security import SecurityScheme
15
+
16
+
17
+ class Schema(BaseModel):
18
+ """
19
+ JSON Schema definition for data models.
20
+
21
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#schema-object
22
+
23
+ Note: Uses Dict[str, Any] for properties to support nested schemas and $ref.
24
+ Reference resolution happens at runtime in config_loader.py.
25
+
26
+ Extensions:
27
+ - x-airbyte-resource-name: Name of the resource this schema represents (Airbyte extension)
28
+ """
29
+
30
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
31
+
32
+ # Core JSON Schema fields
33
+ type: Optional[str] = None
34
+ format: Optional[str] = None
35
+ title: Optional[str] = None
36
+ description: Optional[str] = None
37
+ default: Optional[Any] = None
38
+ example: Optional[Any] = None
39
+
40
+ # Object properties
41
+ properties: Dict[str, Any] = Field(default_factory=dict) # May contain $ref
42
+ required: List[str] = Field(default_factory=list)
43
+ additional_properties: Optional[Any] = Field(None, alias="additionalProperties")
44
+
45
+ # Array properties
46
+ items: Optional[Any] = None # May be Schema or $ref
47
+
48
+ # Validation
49
+ enum: Optional[List[Any]] = None
50
+ min_length: Optional[int] = Field(None, alias="minLength")
51
+ max_length: Optional[int] = Field(None, alias="maxLength")
52
+ minimum: Optional[float] = None
53
+ maximum: Optional[float] = None
54
+ pattern: Optional[str] = None
55
+
56
+ # Composition
57
+ all_of: Optional[List[Any]] = Field(None, alias="allOf")
58
+ any_of: Optional[List[Any]] = Field(None, alias="anyOf")
59
+ one_of: Optional[List[Any]] = Field(None, alias="oneOf")
60
+ not_: Optional[Any] = Field(None, alias="not")
61
+
62
+ # Metadata
63
+ nullable: Optional[bool] = Field(None, deprecated="Use type union with null instead (OpenAPI 3.1)")
64
+ read_only: Optional[bool] = Field(None, alias="readOnly")
65
+ write_only: Optional[bool] = Field(None, alias="writeOnly")
66
+ deprecated: Optional[bool] = None
67
+
68
+ # Airbyte extension
69
+ x_airbyte_entity_name: Optional[str] = Field(None, alias="x-airbyte-entity-name")
70
+
71
+
72
+ class Parameter(BaseModel):
73
+ """
74
+ Operation parameter definition.
75
+
76
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#parameter-object
77
+ """
78
+
79
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
80
+
81
+ name: str
82
+ in_: Literal["query", "header", "path", "cookie"] = Field(alias="in")
83
+ description: Optional[str] = None
84
+ required: Optional[bool] = None
85
+ deprecated: Optional[bool] = None
86
+ allow_empty_value: Optional[bool] = Field(None, alias="allowEmptyValue")
87
+
88
+ # Schema can be inline or reference
89
+ schema_: Optional[Dict[str, Any]] = Field(None, alias="schema")
90
+
91
+ # Style and examples
92
+ style: Optional[str] = None
93
+ explode: Optional[bool] = None
94
+ example: Optional[Any] = None
95
+ examples: Optional[Dict[str, Any]] = None
96
+
97
+
98
+ class MediaType(BaseModel):
99
+ """
100
+ Media type object for request/response content.
101
+
102
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#media-type-object
103
+ """
104
+
105
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
106
+
107
+ schema_: Optional[Dict[str, Any]] = Field(None, alias="schema")
108
+ example: Optional[Any] = None
109
+ examples: Optional[Dict[str, Any]] = None
110
+ encoding: Optional[Dict[str, Any]] = None
111
+
112
+
113
+ class GraphQLBodyConfig(BaseModel):
114
+ """
115
+ GraphQL body type configuration for x-airbyte-body-type extension.
116
+
117
+ Used when x-airbyte-body-type.type = "graphql"
118
+ """
119
+
120
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
121
+
122
+ type: Literal["graphql"] = Field(..., description="Body type identifier (must be 'graphql')")
123
+ query: str = Field(
124
+ ...,
125
+ description="GraphQL query or mutation string with optional template placeholders (e.g., {{ variable }})",
126
+ )
127
+ variables: Optional[Dict[str, Any]] = Field(
128
+ None,
129
+ description="Variables to substitute in the GraphQL query using template syntax (e.g., {{ param_name }})",
130
+ )
131
+ operationName: Optional[str] = Field(None, description="Operation name for queries with multiple operations")
132
+ default_fields: Optional[Union[str, List[str]]] = Field(
133
+ None,
134
+ description="Default fields to select if not provided in request parameters. Can be a string or array of field names.",
135
+ )
136
+
137
+
138
+ # Union type for all body type configs (extensible for future types like XML, SOAP, etc.)
139
+ BodyTypeConfig = Union[GraphQLBodyConfig]
140
+
141
+
142
+ class PathOverrideConfig(BaseModel):
143
+ """
144
+ Path override configuration for x-airbyte-path-override extension.
145
+
146
+ Used when the OpenAPI path differs from the actual HTTP endpoint path.
147
+ Common for GraphQL APIs where multiple resources share the same endpoint (e.g., /graphql).
148
+
149
+ Example:
150
+ OpenAPI path: /graphql:repositories (for uniqueness)
151
+ Actual HTTP path: /graphql (configured here)
152
+ """
153
+
154
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
155
+
156
+ path: str = Field(
157
+ ...,
158
+ description=("Actual HTTP path to use for requests (e.g., '/graphql'). " "Must start with '/'"),
159
+ )
160
+
161
+
162
+ class RequestBody(BaseModel):
163
+ """
164
+ Request body definition.
165
+
166
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#request-body-object
167
+
168
+ Airbyte Extensions:
169
+ See connector_sdk.extensions for documentation:
170
+ - AIRBYTE_BODY_TYPE: Body type and configuration (nested structure)
171
+ """
172
+
173
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
174
+
175
+ description: Optional[str] = None
176
+ content: Dict[str, MediaType] = Field(default_factory=dict)
177
+ required: Optional[bool] = None
178
+
179
+ # Airbyte extensions for GraphQL support
180
+ # See connector_sdk.extensions for AIRBYTE_BODY_TYPE constant
181
+ x_airbyte_body_type: Optional[BodyTypeConfig] = Field(
182
+ None,
183
+ alias="x-airbyte-body-type", # AIRBYTE_BODY_TYPE
184
+ description=(
185
+ "Body type and configuration. Contains 'type' field (e.g., 'graphql') " "and type-specific configuration (query, variables, etc.)."
186
+ ),
187
+ )
188
+
189
+
190
+ class Header(BaseModel):
191
+ """
192
+ Header definition.
193
+
194
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#header-object
195
+ """
196
+
197
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
198
+
199
+ description: Optional[str] = None
200
+ required: Optional[bool] = None
201
+ deprecated: Optional[bool] = None
202
+ schema_: Optional[Dict[str, Any]] = Field(None, alias="schema")
203
+ example: Optional[Any] = None
204
+
205
+
206
+ class Response(BaseModel):
207
+ """
208
+ Response definition.
209
+
210
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#response-object
211
+ """
212
+
213
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
214
+
215
+ description: str
216
+ headers: Optional[Dict[str, Header]] = None
217
+ content: Optional[Dict[str, MediaType]] = None
218
+ links: Optional[Dict[str, Any]] = None
219
+
220
+
221
+ class Components(BaseModel):
222
+ """
223
+ Reusable component definitions.
224
+
225
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#components-object
226
+ """
227
+
228
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
229
+
230
+ schemas: Dict[str, Schema] = Field(default_factory=dict)
231
+ responses: Dict[str, Response] = Field(default_factory=dict)
232
+ parameters: Dict[str, Parameter] = Field(default_factory=dict)
233
+ examples: Optional[Dict[str, Any]] = None
234
+ request_bodies: Dict[str, RequestBody] = Field(default_factory=dict, alias="requestBodies")
235
+ headers: Optional[Dict[str, Header]] = None
236
+ security_schemes: Dict[str, SecurityScheme] = Field(default_factory=dict, alias="securitySchemes")
237
+ links: Optional[Dict[str, Any]] = None
238
+ callbacks: Optional[Dict[str, Any]] = None
@@ -0,0 +1,131 @@
1
+ """
2
+ Root OpenAPI 3.1 connector specification model.
3
+
4
+ References:
5
+ - https://spec.openapis.org/oas/v3.1.0#openapi-object
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Any
11
+
12
+ from pydantic import BaseModel, ConfigDict, Field, field_validator
13
+
14
+ from ..constants import OPENAPI_VERSION_PREFIX
15
+
16
+ from .base import Info, Server
17
+ from .components import Components
18
+ from .operations import PathItem
19
+ from .security import SecurityRequirement
20
+
21
+
22
+ class Tag(BaseModel):
23
+ """
24
+ Tag metadata for grouping operations.
25
+
26
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#tag-object
27
+ """
28
+
29
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
30
+
31
+ name: str
32
+ description: str | None = None
33
+ external_docs: dict[str, Any] | None = Field(None, alias="externalDocs")
34
+
35
+
36
+ class ExternalDocs(BaseModel):
37
+ """
38
+ External documentation reference.
39
+
40
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#external-documentation-object
41
+ """
42
+
43
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
44
+
45
+ description: str | None = None
46
+ url: str
47
+
48
+
49
+ class OpenAPIConnector(BaseModel):
50
+ """
51
+ Root OpenAPI 3.1 connector specification.
52
+
53
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#openapi-object
54
+
55
+ This is the top-level model that represents a complete OpenAPI 3.1 specification
56
+ for an Airbyte connector. It enforces strict validation (extra='forbid') to catch
57
+ typos and unknown extensions.
58
+ """
59
+
60
+ model_config = ConfigDict(populate_by_name=True, extra="forbid", validate_default=True)
61
+
62
+ # Required fields
63
+ openapi: str
64
+ info: Info
65
+ paths: dict[str, PathItem] = Field(default_factory=dict)
66
+
67
+ # Optional fields
68
+ servers: list[Server] = Field(default_factory=list)
69
+ components: Components | None = None
70
+ security: list[SecurityRequirement] | None = None
71
+ tags: list[Tag] | None = None
72
+ external_docs: ExternalDocs | None = Field(None, alias="externalDocs")
73
+
74
+ @field_validator("openapi")
75
+ @classmethod
76
+ def validate_openapi_version(cls, v: str) -> str:
77
+ """Validate that OpenAPI version is 3.1.x."""
78
+ if not v.startswith(OPENAPI_VERSION_PREFIX):
79
+ raise ValueError(f"OpenAPI version must be {OPENAPI_VERSION_PREFIX}x, got: {v}")
80
+ return v
81
+
82
+ def get_entity_operations(self, entity_name: str) -> list[tuple[str, str, Any]]:
83
+ """
84
+ Get all operations for a specific entity.
85
+
86
+ Args:
87
+ entity_name: The x-airbyte-entity value to filter by
88
+
89
+ Returns:
90
+ List of tuples: (path, method, operation)
91
+ """
92
+ results = []
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
108
+
109
+ def list_entities(self) -> list[str]:
110
+ """
111
+ List all unique entity names defined in x-airbyte-entity extensions.
112
+
113
+ Returns:
114
+ Sorted list of unique entity names
115
+ """
116
+ entities = set()
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)
131
+ return sorted(entities)