graphxr-database-proxy 1.0.0__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 (33) hide show
  1. graphxr_database_proxy/__init__.py +16 -0
  2. graphxr_database_proxy/api/__init__.py +1 -0
  3. graphxr_database_proxy/api/database.py +266 -0
  4. graphxr_database_proxy/api/google.py +437 -0
  5. graphxr_database_proxy/api/projects.py +99 -0
  6. graphxr_database_proxy/common/util.py +38 -0
  7. graphxr_database_proxy/drivers/__init__.py +1 -0
  8. graphxr_database_proxy/drivers/base.py +56 -0
  9. graphxr_database_proxy/drivers/factory.py +36 -0
  10. graphxr_database_proxy/drivers/spanner.py +814 -0
  11. graphxr_database_proxy/main.py +110 -0
  12. graphxr_database_proxy/models/__init__.py +1 -0
  13. graphxr_database_proxy/models/google.py +50 -0
  14. graphxr_database_proxy/models/project.py +170 -0
  15. graphxr_database_proxy/proxy.py +495 -0
  16. graphxr_database_proxy/proxyForDev.py +290 -0
  17. graphxr_database_proxy/services/__init__.py +1 -0
  18. graphxr_database_proxy/services/project_service.py +150 -0
  19. graphxr_database_proxy/static/favicon.ico +0 -0
  20. graphxr_database_proxy/static/index.html +1 -0
  21. graphxr_database_proxy/static/main.7391ee9773c403483393.css +175 -0
  22. graphxr_database_proxy/static/main.7391ee9773c403483393.css.map +1 -0
  23. graphxr_database_proxy/static/main.ce3fbb85a7bc9452edb9.js +2 -0
  24. graphxr_database_proxy/static/main.ce3fbb85a7bc9452edb9.js.map +1 -0
  25. graphxr_database_proxy/static/vendors.70542a99f336a8021013.js +3 -0
  26. graphxr_database_proxy/static/vendors.70542a99f336a8021013.js.LICENSE.txt +95 -0
  27. graphxr_database_proxy/static/vendors.70542a99f336a8021013.js.map +1 -0
  28. graphxr_database_proxy-1.0.0.dist-info/METADATA +180 -0
  29. graphxr_database_proxy-1.0.0.dist-info/RECORD +33 -0
  30. graphxr_database_proxy-1.0.0.dist-info/WHEEL +5 -0
  31. graphxr_database_proxy-1.0.0.dist-info/entry_points.txt +2 -0
  32. graphxr_database_proxy-1.0.0.dist-info/licenses/LICENSE +21 -0
  33. graphxr_database_proxy-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,16 @@
1
+ """
2
+ GraphXR Database Proxy
3
+
4
+ A secure middleware for connecting GraphXR Frontend to various backend databases.
5
+ """
6
+
7
+ __version__ = "1.0.0"
8
+ __author__ = "Kineviz"
9
+ __email__ = "support@kineviz.com"
10
+
11
+ from .main import app
12
+ from .proxy import DatabaseProxy
13
+ from .models.project import Project, DatabaseConfig
14
+ from .services.project_service import ProjectService
15
+
16
+ __all__ = ["app", "DatabaseProxy", "Project", "DatabaseConfig", "ProjectService"]
@@ -0,0 +1 @@
1
+ # API package
@@ -0,0 +1,266 @@
1
+ """
2
+ Database API endpoints
3
+ """
4
+
5
+ from typing import Any, Dict
6
+ from fastapi import APIRouter, HTTPException, Depends, Path
7
+ from ..models.project import DatabaseType, QueryRequest, QueryResponse, SchemaResponse, GraphSchemaResponse, SampleDataResponse, APIInfo
8
+ from ..services.project_service import ProjectService
9
+ from ..drivers.factory import DriverFactory
10
+
11
+ router = APIRouter(prefix="/api", tags=["database"])
12
+
13
+ def get_project_service() -> ProjectService:
14
+ return ProjectService()
15
+
16
+
17
+ @router.get("/{database_type}/{project_name}", response_model=APIInfo)
18
+ async def get_database_info(
19
+ database_type: DatabaseType = Path(..., description="Database type"),
20
+ project_name: str = Path(..., description="Project name"),
21
+ service: ProjectService = Depends(get_project_service)
22
+ ):
23
+ """Get database API information"""
24
+ try:
25
+ # Find project by name
26
+ project = await service.get_project_by_name(project_name)
27
+ if not project:
28
+ raise HTTPException(status_code=404, detail="Project not found")
29
+
30
+ if project.database_type != database_type:
31
+ raise HTTPException(
32
+ status_code=400,
33
+ detail=f"Project database type {project.database_type} does not match requested type {database_type}"
34
+ )
35
+
36
+ # Create driver and get API info
37
+ driver = DriverFactory.create_driver(project)
38
+ api_info = driver.get_api_info(project.name)
39
+
40
+ return APIInfo(
41
+ type=database_type,
42
+ api_urls=api_info["api_urls"],
43
+ version=api_info.get("version")
44
+ )
45
+
46
+ except HTTPException:
47
+ raise
48
+ except Exception as e:
49
+ raise HTTPException(status_code=500, detail=str(e))
50
+
51
+
52
+ @router.post("/{database_type}/{project_name}/query", response_model=QueryResponse)
53
+ async def execute_query(
54
+ database_type: DatabaseType = Path(..., description="Database type"),
55
+ project_name: str = Path(..., description="Project name"),
56
+ query_request: QueryRequest = ...,
57
+ service: ProjectService = Depends(get_project_service)
58
+ ):
59
+ """Execute a database query"""
60
+ try:
61
+ # Find project by name
62
+ project = await service.get_project_by_name(project_name)
63
+ if not project:
64
+ raise HTTPException(status_code=404, detail="Project not found")
65
+
66
+ if project.database_type != database_type:
67
+ raise HTTPException(
68
+ status_code=400,
69
+ detail=f"Project database type {project.database_type} does not match requested type {database_type}"
70
+ )
71
+
72
+ # Create driver and execute query
73
+ driver = DriverFactory.create_driver(project)
74
+ await driver.connect()
75
+
76
+ try:
77
+ result = await driver.execute_query(
78
+ query_request.query,
79
+ query_request.parameters
80
+ )
81
+ return result
82
+ finally:
83
+ await driver.disconnect()
84
+
85
+ except HTTPException:
86
+ raise
87
+ except Exception as e:
88
+ raise HTTPException(status_code=500, detail=str(e))
89
+
90
+
91
+ @router.get("/{database_type}/{project_name}/schema", response_model=SchemaResponse)
92
+ async def get_schema(
93
+ database_type: DatabaseType = Path(..., description="Database type"),
94
+ project_name: str = Path(..., description="Project name"),
95
+ service: ProjectService = Depends(get_project_service)
96
+ ):
97
+ """Get database schema"""
98
+ try:
99
+ # Find project by name
100
+ project = await service.get_project_by_name(project_name)
101
+ if not project:
102
+ raise HTTPException(status_code=404, detail="Project not found")
103
+
104
+ if project.database_type != database_type:
105
+ raise HTTPException(
106
+ status_code=400,
107
+ detail=f"Project database type {project.database_type} does not match requested type {database_type}"
108
+ )
109
+
110
+ # Create driver and get schema
111
+ driver = DriverFactory.create_driver(project)
112
+ await driver.connect()
113
+
114
+ try:
115
+ result = await driver.get_schema()
116
+ return result
117
+ finally:
118
+ await driver.disconnect()
119
+
120
+ except HTTPException:
121
+ raise
122
+ except Exception as e:
123
+ raise HTTPException(status_code=500, detail=str(e))
124
+
125
+
126
+ @router.get("/{database_type}/{project_name}/token-status")
127
+ async def get_token_status(
128
+ database_type: DatabaseType = Path(..., description="Database type"),
129
+ project_name: str = Path(..., description="Project name"),
130
+ service: ProjectService = Depends(get_project_service)
131
+ ):
132
+ """Get OAuth token status information"""
133
+ try:
134
+ # Find project by name
135
+ project = await service.get_project_by_name(project_name)
136
+ if not project:
137
+ raise HTTPException(status_code=404, detail="Project not found")
138
+
139
+ if project.database_type != database_type:
140
+ raise HTTPException(
141
+ status_code=400,
142
+ detail=f"Project database type {project.database_type} does not match requested type {database_type}"
143
+ )
144
+
145
+ # Create driver and get token status
146
+ driver = DriverFactory.create_driver(project)
147
+ if hasattr(driver, 'get_token_status'):
148
+ token_status = driver.get_token_status()
149
+ return {
150
+ "success": True,
151
+ "data": token_status
152
+ }
153
+ else:
154
+ return {
155
+ "success": False,
156
+ "error": "Token status not available for this database type"
157
+ }
158
+
159
+ except HTTPException:
160
+ raise
161
+ except Exception as e:
162
+ raise HTTPException(status_code=500, detail=str(e))
163
+
164
+
165
+ @router.post("/{database_type}/{project_name}/test")
166
+ async def test_connection(
167
+ database_type: DatabaseType = Path(..., description="Database type"),
168
+ project_name: str = Path(..., description="Project name"),
169
+ service: ProjectService = Depends(get_project_service)
170
+ ):
171
+ """Test database connection"""
172
+ try:
173
+ # Find project by name
174
+ project = await service.get_project_by_name(project_name)
175
+ if not project:
176
+ raise HTTPException(status_code=404, detail="Project not found")
177
+
178
+ if project.database_type != database_type:
179
+ raise HTTPException(
180
+ status_code=400,
181
+ detail=f"Project database type {project.database_type} does not match requested type {database_type}"
182
+ )
183
+
184
+ # Create driver and test connection
185
+ driver = DriverFactory.create_driver(project)
186
+ is_connected = await driver.test_connection()
187
+
188
+ return {
189
+ "success": is_connected,
190
+ "message": "Connection successful" if is_connected else "Connection failed"
191
+ }
192
+
193
+ except HTTPException:
194
+ raise
195
+ except Exception as e:
196
+ raise HTTPException(status_code=500, detail=str(e))
197
+
198
+
199
+ @router.get("/{database_type}/{project_name}/graphSchema", response_model=GraphSchemaResponse)
200
+ async def get_graph_schema(
201
+ database_type: DatabaseType = Path(..., description="Database type"),
202
+ project_name: str = Path(..., description="Project name"),
203
+ service: ProjectService = Depends(get_project_service)
204
+ ):
205
+ """Get graph database schema"""
206
+ try:
207
+ # Find project by name
208
+ project = await service.get_project_by_name(project_name)
209
+ if not project:
210
+ raise HTTPException(status_code=404, detail="Project not found")
211
+
212
+ if project.database_type != database_type:
213
+ raise HTTPException(
214
+ status_code=400,
215
+ detail=f"Project database type {project.database_type} does not match requested type {database_type}"
216
+ )
217
+
218
+ # Create driver and get graph schema
219
+ driver = DriverFactory.create_driver(project)
220
+ await driver.connect()
221
+
222
+ try:
223
+ result = await driver.get_graph_schema()
224
+ return result
225
+ finally:
226
+ await driver.disconnect()
227
+
228
+ except HTTPException:
229
+ raise
230
+ except Exception as e:
231
+ raise HTTPException(status_code=500, detail=str(e))
232
+
233
+
234
+ @router.get("/{database_type}/{project_name}/sampleData", response_model=SampleDataResponse)
235
+ async def get_sample_data(
236
+ database_type: DatabaseType = Path(..., description="Database type"),
237
+ project_name: str = Path(..., description="Project name"),
238
+ service: ProjectService = Depends(get_project_service),
239
+ ):
240
+ """Get sample data from database"""
241
+ try:
242
+ # Find project by name
243
+ project = await service.get_project_by_name(project_name)
244
+ if not project:
245
+ raise HTTPException(status_code=404, detail="Project not found")
246
+
247
+ if project.database_type != database_type:
248
+ raise HTTPException(
249
+ status_code=400,
250
+ detail=f"Project database type {project.database_type} does not match requested type {database_type}"
251
+ )
252
+
253
+ # Create driver and get sample data
254
+ driver = DriverFactory.create_driver(project)
255
+ await driver.connect()
256
+
257
+ try:
258
+ result = await driver.get_sample_data()
259
+ return result
260
+ finally:
261
+ await driver.disconnect()
262
+
263
+ except HTTPException:
264
+ raise
265
+ except Exception as e:
266
+ raise HTTPException(status_code=500, detail=str(e))