sql-dialect-master 1.1.3__tar.gz → 1.1.5__tar.gz
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.
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/PKG-INFO +40 -47
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/README.md +35 -45
- sql_dialect_master-1.1.5/backend/api/auth.py +29 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/api/main.py +205 -25
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/api/middleware.py +92 -10
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/api/readiness.py +44 -13
- sql_dialect_master-1.1.5/backend/api/workers.py +50 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/cache.py +15 -3
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/config.py +9 -1
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/exceptions.py +3 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/functions_lookup.py +62 -26
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/metadata.py +2 -2
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/core_extract.py +31 -8
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/mappings.py +2 -2
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/dialect.py +3 -1
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/models.py +3 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/orchestrator.py +155 -20
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/validation.py +4 -3
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/p1_sql_scanner.py +54 -1
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/parser.py +3 -50
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/rules.py +68 -22
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/semantic_diff.py +3 -2
- sql_dialect_master-1.1.5/backend/core/sql_statements.py +30 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/transpiler.py +457 -26
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/type_mapping.py +8 -6
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/utils/validators.py +27 -41
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/pyproject.toml +6 -14
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/sql_dialect_master.egg-info/PKG-INFO +40 -47
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/sql_dialect_master.egg-info/SOURCES.txt +3 -34
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/sql_dialect_master.egg-info/requires.txt +4 -1
- sql_dialect_master-1.1.5/sql_dialect_master.egg-info/top_level.txt +1 -0
- sql_dialect_master-1.1.3/backend/frontend_entrypoint.py +0 -22
- sql_dialect_master-1.1.3/frontend/__init__.py +0 -10
- sql_dialect_master-1.1.3/frontend/app_context_v2.py +0 -201
- sql_dialect_master-1.1.3/frontend/core/__init__.py +0 -33
- sql_dialect_master-1.1.3/frontend/core/design_tokens.py +0 -131
- sql_dialect_master-1.1.3/frontend/core/escaping.py +0 -13
- sql_dialect_master-1.1.3/frontend/core/fingerprints.py +0 -24
- sql_dialect_master-1.1.3/frontend/core/navigation.py +0 -157
- sql_dialect_master-1.1.3/frontend/core/sql_inputs.py +0 -29
- sql_dialect_master-1.1.3/frontend/core/state.py +0 -667
- sql_dialect_master-1.1.3/frontend/core/styles.py +0 -523
- sql_dialect_master-1.1.3/frontend/core/themes.py +0 -75
- sql_dialect_master-1.1.3/frontend/core/type_status.py +0 -26
- sql_dialect_master-1.1.3/frontend/core/viewmodels.py +0 -519
- sql_dialect_master-1.1.3/frontend/pages/__init__.py +0 -0
- sql_dialect_master-1.1.3/frontend/pages/convert.py +0 -372
- sql_dialect_master-1.1.3/frontend/pages/diff.py +0 -170
- sql_dialect_master-1.1.3/frontend/pages/functions.py +0 -99
- sql_dialect_master-1.1.3/frontend/pages/history.py +0 -147
- sql_dialect_master-1.1.3/frontend/pages/lineage.py +0 -185
- sql_dialect_master-1.1.3/frontend/pages/nl2sql.py +0 -305
- sql_dialect_master-1.1.3/frontend/pages/query_analysis.py +0 -128
- sql_dialect_master-1.1.3/frontend/pages/runtime.py +0 -66
- sql_dialect_master-1.1.3/frontend/pages/settings.py +0 -60
- sql_dialect_master-1.1.3/frontend/pages/templates.py +0 -86
- sql_dialect_master-1.1.3/frontend/pages/types.py +0 -106
- sql_dialect_master-1.1.3/frontend/templates_v2.py +0 -53
- sql_dialect_master-1.1.3/frontend/ui/__init__.py +0 -0
- sql_dialect_master-1.1.3/frontend/ui/command_palette.py +0 -172
- sql_dialect_master-1.1.3/frontend/ui/diff.py +0 -275
- sql_dialect_master-1.1.3/frontend/ui/editor.py +0 -102
- sql_dialect_master-1.1.3/frontend/ui/status.py +0 -255
- sql_dialect_master-1.1.3/sdm_local_v2.py +0 -219
- sql_dialect_master-1.1.3/sql_dialect_master.egg-info/entry_points.txt +0 -2
- sql_dialect_master-1.1.3/sql_dialect_master.egg-info/top_level.txt +0 -3
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/LICENSE +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/__init__.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/api/__init__.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/api/rate_limit_store.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/__init__.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/column_hint_validation.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/constants.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/function_call_scanner.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/function_semantics.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/functions_db.json +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/__init__.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/aggregations.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/boolean_conditions.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/evidence.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/relations.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/templates.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/tokenizer.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_legacy.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/__init__.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/aggregations.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/clause_extract.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/intent.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/ir.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/predicates.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/renderer.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/resolution.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/suggestions.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/templates.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/p2_data_validation.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/post_processor.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/type_mapping.json +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/utils/__init__.py +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/setup.cfg +0 -0
- {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/sql_dialect_master.egg-info/dependency_links.txt +0 -0
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sql-dialect-master
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.5
|
|
4
4
|
Summary: SQL Dialect Master - Multi-database SQL conversion engine
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
7
|
License-File: LICENSE
|
|
8
8
|
Requires-Dist: sqlglot<31.0.0,>=30.18.0
|
|
9
|
-
Requires-Dist: streamlit>=1.38.0
|
|
10
9
|
Requires-Dist: fastapi>=0.115.0
|
|
11
10
|
Requires-Dist: uvicorn>=0.30.0
|
|
12
11
|
Requires-Dist: pydantic>=2.9.0
|
|
@@ -21,6 +20,10 @@ Provides-Extra: qa
|
|
|
21
20
|
Requires-Dist: ruff>=0.6; extra == "qa"
|
|
22
21
|
Requires-Dist: bandit>=1.7; extra == "qa"
|
|
23
22
|
Requires-Dist: pip-audit>=2.7; extra == "qa"
|
|
23
|
+
Requires-Dist: build>=1.2.2; extra == "qa"
|
|
24
|
+
Requires-Dist: twine>=5.1; extra == "qa"
|
|
25
|
+
Requires-Dist: setuptools>=75.0.0; extra == "qa"
|
|
26
|
+
Requires-Dist: wheel>=0.45; extra == "qa"
|
|
24
27
|
Provides-Extra: semantic
|
|
25
28
|
Requires-Dist: duckdb>=1.5.5; extra == "semantic"
|
|
26
29
|
Requires-Dist: psycopg[binary]>=3.3.5; extra == "semantic"
|
|
@@ -32,12 +35,12 @@ Dynamic: license-file
|
|
|
32
35
|
|
|
33
36
|
Enterprise-grade multi-database SQL conversion engine supporting 12 database dialects.
|
|
34
37
|
|
|
35
|
-
Current release: 1.1.
|
|
38
|
+
Current release: 1.1.5
|
|
36
39
|
|
|
37
40
|
[](https://www.python.org/downloads/)
|
|
38
41
|
[](https://opensource.org/licenses/MIT)
|
|
39
42
|
[](https://fastapi.tiangolo.com/)
|
|
40
|
-
[](https://react.dev/)
|
|
41
44
|
|
|
42
45
|
## ✨ Features
|
|
43
46
|
|
|
@@ -54,7 +57,7 @@ Current release: 1.1.3
|
|
|
54
57
|
| 🔧 **Rule Engine** | Deterministic priority ordering, compiled patterns, dialect-aware conflict detection |
|
|
55
58
|
| 🛡️ **Security Validation** | Statement-level stacked-query detection with configurable blocking policy |
|
|
56
59
|
| ⚡ **Performance** | Rule-aware cache versioning, bounded async batch conversion, and reproducible benchmark |
|
|
57
|
-
| 🎨 **Modern UI** |
|
|
60
|
+
| 🎨 **Modern UI** | React developer workspace with dark / light themes, responsive navigation, and command palette |
|
|
58
61
|
|
|
59
62
|
## 💾 Supported Databases
|
|
60
63
|
|
|
@@ -78,32 +81,38 @@ cd sql-dialect-master
|
|
|
78
81
|
python -m pip install -e .
|
|
79
82
|
```
|
|
80
83
|
|
|
81
|
-
For development and
|
|
84
|
+
For development, testing, quality checks, and local builds, use the project's
|
|
85
|
+
Python environment and install the optional tooling:
|
|
82
86
|
|
|
83
87
|
```bash
|
|
84
|
-
python -m
|
|
88
|
+
python -m venv .venv
|
|
89
|
+
.venv/bin/python -m pip install -e ".[dev,qa]"
|
|
85
90
|
```
|
|
86
91
|
|
|
87
92
|
For database-backed semantic tests:
|
|
88
93
|
|
|
89
94
|
```bash
|
|
90
|
-
python -m pip install -e ".[dev,semantic]"
|
|
95
|
+
.venv/bin/python -m pip install -e ".[dev,semantic]"
|
|
91
96
|
```
|
|
92
97
|
|
|
93
|
-
### Run
|
|
98
|
+
### Run the React UI
|
|
94
99
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
After installing the package, the same workspace can be launched from any
|
|
100
|
-
working directory with:
|
|
100
|
+
The React workspace is the product frontend and runs independently from the
|
|
101
|
+
Python package. Start the API first, then run:
|
|
101
102
|
|
|
102
103
|
```bash
|
|
103
|
-
|
|
104
|
+
cd frontend-react
|
|
105
|
+
npm install
|
|
106
|
+
npm run dev
|
|
104
107
|
```
|
|
105
108
|
|
|
106
|
-
Open http://localhost:
|
|
109
|
+
Open http://localhost:5174. The Vite development proxy forwards `/api`,
|
|
110
|
+
`/health`, and `/ready` to `http://127.0.0.1:8000`. Set `VITE_API_BASE_URL`
|
|
111
|
+
for a separately deployed API, or configure the URL and optional API key in
|
|
112
|
+
the React Settings page.
|
|
113
|
+
|
|
114
|
+
React implementation goals and gates are tracked in
|
|
115
|
+
[`docs/react-frontend-refactor-plan.md`](docs/react-frontend-refactor-plan.md).
|
|
107
116
|
|
|
108
117
|
### Run FastAPI Backend
|
|
109
118
|
|
|
@@ -113,6 +122,16 @@ uvicorn backend.api.main:app --reload
|
|
|
113
122
|
|
|
114
123
|
API docs available at http://localhost:8000/docs
|
|
115
124
|
|
|
125
|
+
Set `SDM_API_KEY` in `.env` to require credentials for `/api/*` endpoints.
|
|
126
|
+
Clients may send `X-API-Key` or `Authorization: Bearer <key>`. Health probes
|
|
127
|
+
use the separate `SDM_HEALTH_PROBE_TOKEN` setting. An empty API key preserves
|
|
128
|
+
local access.
|
|
129
|
+
|
|
130
|
+
`SDM_API_WORKERS` (default 4) and `SDM_API_QUEUE_SIZE` (default 4) bound CPU
|
|
131
|
+
work. When all slots are occupied, requests receive HTTP 503 and a
|
|
132
|
+
`Retry-After` header. `SDM_REQUEST_TIMEOUT` returns HTTP 504 when a request
|
|
133
|
+
times out; running threads retain their capacity until they finish.
|
|
134
|
+
|
|
116
135
|
## 📖 Usage Examples
|
|
117
136
|
|
|
118
137
|
### Python SDK
|
|
@@ -254,42 +273,16 @@ sql-dialect-master/
|
|
|
254
273
|
│ │ └── validators.py # Input validation
|
|
255
274
|
│ │
|
|
256
275
|
│ └── tests/ # Test suite and regression coverage
|
|
257
|
-
├── frontend/ # Streamlit UI Components (v2 architecture)
|
|
258
|
-
│ ├── core/ # Cross-cutting concerns
|
|
259
|
-
│ │ ├── design_tokens.py # Theme model (dark/light) + semantic status
|
|
260
|
-
│ │ ├── navigation.py # NavigationIntent contract
|
|
261
|
-
│ │ ├── state.py # SessionState adapter
|
|
262
|
-
│ │ ├── themes.py # Theme switching (dark/light only)
|
|
263
|
-
│ │ ├── styles.py # CSS generation from design tokens
|
|
264
|
-
│ │ ├── escaping.py # HTML-safe rendering helpers
|
|
265
|
-
│ │ └── viewmodels.py # Typed view models
|
|
266
|
-
│ ├── pages/ # One module per workspace page
|
|
267
|
-
│ │ ├── convert.py
|
|
268
|
-
│ │ ├── nl2sql.py
|
|
269
|
-
│ │ ├── diff.py
|
|
270
|
-
│ │ ├── lineage.py
|
|
271
|
-
│ │ ├── runtime.py
|
|
272
|
-
│ │ ├── functions.py
|
|
273
|
-
│ │ ├── types.py
|
|
274
|
-
│ │ ├── templates.py
|
|
275
|
-
│ │ ├── history.py
|
|
276
|
-
│ │ ├── settings.py
|
|
277
|
-
│ │ └── query_analysis.py
|
|
278
|
-
│ ├── ui/ # Reusable UI widgets
|
|
279
|
-
│ │ ├── command_palette.py
|
|
280
|
-
│ │ ├── diff.py
|
|
281
|
-
│ │ ├── editor.py
|
|
282
|
-
│ │ └── status.py
|
|
283
|
-
│ ├── app_context_v2.py # Shared application context (v2)
|
|
284
|
-
│ └── templates_v2.py # SQL templates (v2)
|
|
285
276
|
├── examples/
|
|
286
277
|
│ ├── api_client.py # API usage examples
|
|
287
278
|
│ └── basic_usage.py # SDK usage examples
|
|
288
279
|
├── scripts/
|
|
289
280
|
│ └── verify_readme_consistency.py # README source-of-truth checks
|
|
290
|
-
├──
|
|
281
|
+
├── frontend-react/ # React + TypeScript product frontend
|
|
282
|
+
│ ├── src/
|
|
283
|
+
│ ├── package.json
|
|
284
|
+
│ └── vite.config.ts
|
|
291
285
|
├── pyproject.toml # Project configuration
|
|
292
|
-
├── requirements.txt # Legacy/runtime dependency list
|
|
293
286
|
├── .env.example # Environment template
|
|
294
287
|
├── LICENSE # MIT License
|
|
295
288
|
└── README.md
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Enterprise-grade multi-database SQL conversion engine supporting 12 database dialects.
|
|
4
4
|
|
|
5
|
-
Current release: 1.1.
|
|
5
|
+
Current release: 1.1.5
|
|
6
6
|
|
|
7
7
|
[](https://www.python.org/downloads/)
|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
9
|
[](https://fastapi.tiangolo.com/)
|
|
10
|
-
[](https://react.dev/)
|
|
11
11
|
|
|
12
12
|
## ✨ Features
|
|
13
13
|
|
|
@@ -24,7 +24,7 @@ Current release: 1.1.3
|
|
|
24
24
|
| 🔧 **Rule Engine** | Deterministic priority ordering, compiled patterns, dialect-aware conflict detection |
|
|
25
25
|
| 🛡️ **Security Validation** | Statement-level stacked-query detection with configurable blocking policy |
|
|
26
26
|
| ⚡ **Performance** | Rule-aware cache versioning, bounded async batch conversion, and reproducible benchmark |
|
|
27
|
-
| 🎨 **Modern UI** |
|
|
27
|
+
| 🎨 **Modern UI** | React developer workspace with dark / light themes, responsive navigation, and command palette |
|
|
28
28
|
|
|
29
29
|
## 💾 Supported Databases
|
|
30
30
|
|
|
@@ -48,32 +48,38 @@ cd sql-dialect-master
|
|
|
48
48
|
python -m pip install -e .
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
For development and
|
|
51
|
+
For development, testing, quality checks, and local builds, use the project's
|
|
52
|
+
Python environment and install the optional tooling:
|
|
52
53
|
|
|
53
54
|
```bash
|
|
54
|
-
python -m
|
|
55
|
+
python -m venv .venv
|
|
56
|
+
.venv/bin/python -m pip install -e ".[dev,qa]"
|
|
55
57
|
```
|
|
56
58
|
|
|
57
59
|
For database-backed semantic tests:
|
|
58
60
|
|
|
59
61
|
```bash
|
|
60
|
-
python -m pip install -e ".[dev,semantic]"
|
|
62
|
+
.venv/bin/python -m pip install -e ".[dev,semantic]"
|
|
61
63
|
```
|
|
62
64
|
|
|
63
|
-
### Run
|
|
65
|
+
### Run the React UI
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
After installing the package, the same workspace can be launched from any
|
|
70
|
-
working directory with:
|
|
67
|
+
The React workspace is the product frontend and runs independently from the
|
|
68
|
+
Python package. Start the API first, then run:
|
|
71
69
|
|
|
72
70
|
```bash
|
|
73
|
-
|
|
71
|
+
cd frontend-react
|
|
72
|
+
npm install
|
|
73
|
+
npm run dev
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
Open http://localhost:
|
|
76
|
+
Open http://localhost:5174. The Vite development proxy forwards `/api`,
|
|
77
|
+
`/health`, and `/ready` to `http://127.0.0.1:8000`. Set `VITE_API_BASE_URL`
|
|
78
|
+
for a separately deployed API, or configure the URL and optional API key in
|
|
79
|
+
the React Settings page.
|
|
80
|
+
|
|
81
|
+
React implementation goals and gates are tracked in
|
|
82
|
+
[`docs/react-frontend-refactor-plan.md`](docs/react-frontend-refactor-plan.md).
|
|
77
83
|
|
|
78
84
|
### Run FastAPI Backend
|
|
79
85
|
|
|
@@ -83,6 +89,16 @@ uvicorn backend.api.main:app --reload
|
|
|
83
89
|
|
|
84
90
|
API docs available at http://localhost:8000/docs
|
|
85
91
|
|
|
92
|
+
Set `SDM_API_KEY` in `.env` to require credentials for `/api/*` endpoints.
|
|
93
|
+
Clients may send `X-API-Key` or `Authorization: Bearer <key>`. Health probes
|
|
94
|
+
use the separate `SDM_HEALTH_PROBE_TOKEN` setting. An empty API key preserves
|
|
95
|
+
local access.
|
|
96
|
+
|
|
97
|
+
`SDM_API_WORKERS` (default 4) and `SDM_API_QUEUE_SIZE` (default 4) bound CPU
|
|
98
|
+
work. When all slots are occupied, requests receive HTTP 503 and a
|
|
99
|
+
`Retry-After` header. `SDM_REQUEST_TIMEOUT` returns HTTP 504 when a request
|
|
100
|
+
times out; running threads retain their capacity until they finish.
|
|
101
|
+
|
|
86
102
|
## 📖 Usage Examples
|
|
87
103
|
|
|
88
104
|
### Python SDK
|
|
@@ -224,42 +240,16 @@ sql-dialect-master/
|
|
|
224
240
|
│ │ └── validators.py # Input validation
|
|
225
241
|
│ │
|
|
226
242
|
│ └── tests/ # Test suite and regression coverage
|
|
227
|
-
├── frontend/ # Streamlit UI Components (v2 architecture)
|
|
228
|
-
│ ├── core/ # Cross-cutting concerns
|
|
229
|
-
│ │ ├── design_tokens.py # Theme model (dark/light) + semantic status
|
|
230
|
-
│ │ ├── navigation.py # NavigationIntent contract
|
|
231
|
-
│ │ ├── state.py # SessionState adapter
|
|
232
|
-
│ │ ├── themes.py # Theme switching (dark/light only)
|
|
233
|
-
│ │ ├── styles.py # CSS generation from design tokens
|
|
234
|
-
│ │ ├── escaping.py # HTML-safe rendering helpers
|
|
235
|
-
│ │ └── viewmodels.py # Typed view models
|
|
236
|
-
│ ├── pages/ # One module per workspace page
|
|
237
|
-
│ │ ├── convert.py
|
|
238
|
-
│ │ ├── nl2sql.py
|
|
239
|
-
│ │ ├── diff.py
|
|
240
|
-
│ │ ├── lineage.py
|
|
241
|
-
│ │ ├── runtime.py
|
|
242
|
-
│ │ ├── functions.py
|
|
243
|
-
│ │ ├── types.py
|
|
244
|
-
│ │ ├── templates.py
|
|
245
|
-
│ │ ├── history.py
|
|
246
|
-
│ │ ├── settings.py
|
|
247
|
-
│ │ └── query_analysis.py
|
|
248
|
-
│ ├── ui/ # Reusable UI widgets
|
|
249
|
-
│ │ ├── command_palette.py
|
|
250
|
-
│ │ ├── diff.py
|
|
251
|
-
│ │ ├── editor.py
|
|
252
|
-
│ │ └── status.py
|
|
253
|
-
│ ├── app_context_v2.py # Shared application context (v2)
|
|
254
|
-
│ └── templates_v2.py # SQL templates (v2)
|
|
255
243
|
├── examples/
|
|
256
244
|
│ ├── api_client.py # API usage examples
|
|
257
245
|
│ └── basic_usage.py # SDK usage examples
|
|
258
246
|
├── scripts/
|
|
259
247
|
│ └── verify_readme_consistency.py # README source-of-truth checks
|
|
260
|
-
├──
|
|
248
|
+
├── frontend-react/ # React + TypeScript product frontend
|
|
249
|
+
│ ├── src/
|
|
250
|
+
│ ├── package.json
|
|
251
|
+
│ └── vite.config.ts
|
|
261
252
|
├── pyproject.toml # Project configuration
|
|
262
|
-
├── requirements.txt # Legacy/runtime dependency list
|
|
263
253
|
├── .env.example # Environment template
|
|
264
254
|
├── LICENSE # MIT License
|
|
265
255
|
└── README.md
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Optional shared API-key protection for business endpoints."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import secrets
|
|
5
|
+
|
|
6
|
+
from fastapi import HTTPException, Request
|
|
7
|
+
|
|
8
|
+
from backend.core.config import settings
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
async def require_api_access(request: Request) -> None:
|
|
12
|
+
"""Require a configured key for /api endpoints while keeping probes separate."""
|
|
13
|
+
key = settings.api_key
|
|
14
|
+
if key is None or not request.url.path.startswith("/api/"):
|
|
15
|
+
return
|
|
16
|
+
expected = key.get_secret_value()
|
|
17
|
+
if not expected:
|
|
18
|
+
return
|
|
19
|
+
supplied = request.headers.get("X-API-Key", "")
|
|
20
|
+
if not supplied:
|
|
21
|
+
scheme, _, credential = request.headers.get("Authorization", "").partition(" ")
|
|
22
|
+
if scheme.lower() == "bearer":
|
|
23
|
+
supplied = credential
|
|
24
|
+
if not supplied or not secrets.compare_digest(supplied.encode("utf-8"), expected.encode("utf-8")):
|
|
25
|
+
raise HTTPException(
|
|
26
|
+
status_code=401,
|
|
27
|
+
detail="Invalid or missing API key",
|
|
28
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
29
|
+
)
|