|
15 | 15 | from pygls.server import LanguageServer |
16 | 16 | from sqlmesh._version import __version__ |
17 | 17 | from sqlmesh.core.context import Context |
| 18 | +from sqlmesh.core import constants as c |
| 19 | +from sqlmesh.utils.date import to_timestamp |
18 | 20 | from sqlmesh.lsp.api import ( |
19 | 21 | API_FEATURE, |
20 | 22 | ApiRequest, |
21 | 23 | ApiResponseGetColumnLineage, |
22 | 24 | ApiResponseGetLineage, |
23 | 25 | ApiResponseGetModels, |
| 26 | + ApiResponseGetTableDiff, |
24 | 27 | ) |
25 | 28 | from sqlmesh.lsp.completions import get_sql_completions |
26 | 29 | from sqlmesh.lsp.context import ( |
|
33 | 36 | RENDER_MODEL_FEATURE, |
34 | 37 | SUPPORTED_METHODS_FEATURE, |
35 | 38 | FORMAT_PROJECT_FEATURE, |
| 39 | + GET_ENVIRONMENTS_FEATURE, |
36 | 40 | AllModelsRequest, |
37 | 41 | AllModelsResponse, |
38 | 42 | AllModelsForRenderRequest, |
|
45 | 49 | FormatProjectRequest, |
46 | 50 | FormatProjectResponse, |
47 | 51 | CustomMethod, |
| 52 | + GetEnvironmentsRequest, |
| 53 | + GetEnvironmentsResponse, |
| 54 | + EnvironmentInfo, |
48 | 55 | ) |
49 | 56 | from sqlmesh.lsp.hints import get_hints |
50 | 57 | from sqlmesh.lsp.reference import ( |
|
58 | 65 | from sqlmesh.lsp.uri import URI |
59 | 66 | from web.server.api.endpoints.lineage import column_lineage, model_lineage |
60 | 67 | from web.server.api.endpoints.models import get_models |
| 68 | +from web.server.api.endpoints.table_diff import get_table_diff |
61 | 69 | from typing import Union |
62 | 70 | from dataclasses import dataclass |
63 | 71 |
|
@@ -121,6 +129,7 @@ def __init__( |
121 | 129 | API_FEATURE: self._custom_api, |
122 | 130 | SUPPORTED_METHODS_FEATURE: self._custom_supported_methods, |
123 | 131 | FORMAT_PROJECT_FEATURE: self._custom_format_project, |
| 132 | + GET_ENVIRONMENTS_FEATURE: self._custom_get_environments, |
124 | 133 | } |
125 | 134 |
|
126 | 135 | # Register LSP features (e.g., formatting, hover, etc.) |
@@ -169,13 +178,67 @@ def _custom_format_project( |
169 | 178 | ls.log_trace(f"Error formatting project: {e}") |
170 | 179 | return FormatProjectResponse() |
171 | 180 |
|
| 181 | + def _custom_get_environments( |
| 182 | + self, ls: LanguageServer, params: GetEnvironmentsRequest |
| 183 | + ) -> GetEnvironmentsResponse: |
| 184 | + """Get all environments in the current project.""" |
| 185 | + try: |
| 186 | + context = self._context_get_or_load() |
| 187 | + environments = {} |
| 188 | + |
| 189 | + # Get environments from state |
| 190 | + for env in context.context.state_reader.get_environments(): |
| 191 | + environments[env.name] = EnvironmentInfo( |
| 192 | + name=env.name, |
| 193 | + snapshots=[s.fingerprint.to_identifier() for s in env.snapshots], |
| 194 | + start_at=str(to_timestamp(env.start_at)), |
| 195 | + plan_id=env.plan_id or "", |
| 196 | + ) |
| 197 | + |
| 198 | + # Add prod if not present (mirroring web/server/api/endpoints/environments.py) |
| 199 | + if c.PROD not in environments: |
| 200 | + environments[c.PROD] = EnvironmentInfo( |
| 201 | + name=c.PROD, |
| 202 | + snapshots=[], |
| 203 | + start_at=str(to_timestamp(c.EPOCH)), |
| 204 | + plan_id="", |
| 205 | + ) |
| 206 | + |
| 207 | + # Add default target environment if not present |
| 208 | + if context.context.config.default_target_environment not in environments: |
| 209 | + environments[context.context.config.default_target_environment] = EnvironmentInfo( |
| 210 | + name=context.context.config.default_target_environment, |
| 211 | + snapshots=[], |
| 212 | + start_at=str(to_timestamp(c.EPOCH)), |
| 213 | + plan_id="", |
| 214 | + ) |
| 215 | + |
| 216 | + return GetEnvironmentsResponse( |
| 217 | + environments=environments, |
| 218 | + pinned_environments=context.context.config.pinned_environments, |
| 219 | + default_target_environment=context.context.config.default_target_environment, |
| 220 | + ) |
| 221 | + except Exception as e: |
| 222 | + ls.log_trace(f"Error getting environments: {e}") |
| 223 | + return GetEnvironmentsResponse( |
| 224 | + response_error=str(e), |
| 225 | + environments={}, |
| 226 | + pinned_environments=set(), |
| 227 | + default_target_environment="", |
| 228 | + ) |
| 229 | + |
172 | 230 | def _custom_api( |
173 | 231 | self, ls: LanguageServer, request: ApiRequest |
174 | | - ) -> t.Union[ApiResponseGetModels, ApiResponseGetColumnLineage, ApiResponseGetLineage]: |
| 232 | + ) -> t.Union[ |
| 233 | + ApiResponseGetModels, |
| 234 | + ApiResponseGetColumnLineage, |
| 235 | + ApiResponseGetLineage, |
| 236 | + ApiResponseGetTableDiff, |
| 237 | + ]: |
175 | 238 | ls.log_trace(f"API request: {request}") |
176 | 239 | context = self._context_get_or_load() |
177 | 240 |
|
178 | | - parsed_url = urllib.parse.urlparse(request.url) |
| 241 | + parsed_url = urllib.parse.urlparse(request.endpoint) |
179 | 242 | path_parts = parsed_url.path.strip("/").split("/") |
180 | 243 |
|
181 | 244 | if request.method == "GET": |
@@ -203,7 +266,24 @@ def _custom_api( |
203 | 266 | ) |
204 | 267 | return ApiResponseGetColumnLineage(data=column_lineage_response) |
205 | 268 |
|
206 | | - raise NotImplementedError(f"API request not implemented: {request.url}") |
| 269 | + if path_parts[:2] == ["api", "table_diff"]: |
| 270 | + # /api/table_diff |
| 271 | + params = request.params |
| 272 | + table_diff_result = get_table_diff( |
| 273 | + source=getattr(params, "source", "") if params else "", |
| 274 | + target=getattr(params, "target", "") if params else "", |
| 275 | + on=getattr(params, "on", None) if params else None, |
| 276 | + model_or_snapshot=getattr(params, "model_or_snapshot", None) |
| 277 | + if params |
| 278 | + else None, |
| 279 | + where=getattr(params, "where", None) if params else None, |
| 280 | + temp_schema=getattr(params, "temp_schema", None) if params else None, |
| 281 | + limit=getattr(params, "limit", 20) if params else 20, |
| 282 | + context=context.context, |
| 283 | + ) |
| 284 | + return ApiResponseGetTableDiff(data=table_diff_result) |
| 285 | + |
| 286 | + raise NotImplementedError(f"API request not implemented: {request.endpoint}") |
207 | 287 |
|
208 | 288 | def _custom_supported_methods( |
209 | 289 | self, ls: LanguageServer, params: SupportedMethodsRequest |
|
0 commit comments