envschema-dsl 0.1.0__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.
- envschema_dsl-0.1.0/PKG-INFO +197 -0
- envschema_dsl-0.1.0/README.md +173 -0
- envschema_dsl-0.1.0/pyproject.toml +45 -0
- envschema_dsl-0.1.0/src/envschema/__init__.py +23 -0
- envschema_dsl-0.1.0/src/envschema/ast.py +108 -0
- envschema_dsl-0.1.0/src/envschema/cli.py +244 -0
- envschema_dsl-0.1.0/src/envschema/env_file.py +63 -0
- envschema_dsl-0.1.0/src/envschema/expander.py +80 -0
- envschema_dsl-0.1.0/src/envschema/generators/__init__.py +0 -0
- envschema_dsl-0.1.0/src/envschema/generators/env_example.py +84 -0
- envschema_dsl-0.1.0/src/envschema/generators/pydantic_gen.py +4 -0
- envschema_dsl-0.1.0/src/envschema/generators/python/__init__.py +0 -0
- envschema_dsl-0.1.0/src/envschema/generators/python/dataclasses_gen.py +144 -0
- envschema_dsl-0.1.0/src/envschema/generators/python/pydantic_v2.py +111 -0
- envschema_dsl-0.1.0/src/envschema/generators/registry.py +92 -0
- envschema_dsl-0.1.0/src/envschema/generators/resolve.py +38 -0
- envschema_dsl-0.1.0/src/envschema/generators/ts/__init__.py +0 -0
- envschema_dsl-0.1.0/src/envschema/generators/ts/interface.py +81 -0
- envschema_dsl-0.1.0/src/envschema/generators/ts/zod_v4.py +119 -0
- envschema_dsl-0.1.0/src/envschema/generators/typescript.py +4 -0
- envschema_dsl-0.1.0/src/envschema/grammar.lark +108 -0
- envschema_dsl-0.1.0/src/envschema/lsp.py +253 -0
- envschema_dsl-0.1.0/src/envschema/parser.py +387 -0
- envschema_dsl-0.1.0/src/envschema/presets/node.js.schema +8 -0
- envschema_dsl-0.1.0/src/envschema/presets/vite.schema +7 -0
- envschema_dsl-0.1.0/src/envschema/presets_manager.py +100 -0
- envschema_dsl-0.1.0/src/envschema/py.typed +0 -0
- envschema_dsl-0.1.0/src/envschema/validator.py +327 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: envschema-dsl
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: DSL for typed .env files — schema, validation, codegen
|
|
5
|
+
Keywords: env,dotenv,schema,validation,codegen,typescript,pydantic,zod
|
|
6
|
+
Author: nike4192
|
|
7
|
+
Author-email: nike4192 <nike4192@outlook.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Requires-Dist: lark>=1.2
|
|
16
|
+
Requires-Dist: click>=8.0
|
|
17
|
+
Requires-Dist: pygls>=2.1.1
|
|
18
|
+
Requires-Dist: pytest>=8.0 ; extra == 'dev'
|
|
19
|
+
Requires-Python: >=3.12
|
|
20
|
+
Project-URL: Homepage, https://github.com/envschema/envschema
|
|
21
|
+
Project-URL: Repository, https://github.com/envschema/envschema
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# envschema
|
|
26
|
+
|
|
27
|
+
DSL for typed `.env` files — schema, validation, codegen.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install envschema
|
|
33
|
+
# or
|
|
34
|
+
uv add envschema
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
Create a `.env.schema` file:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
# Database
|
|
43
|
+
DB_HOST str @required
|
|
44
|
+
DB_PORT port = 5432
|
|
45
|
+
DB_PASSWORD str @secret @required
|
|
46
|
+
DB_NAME str = "myapp"
|
|
47
|
+
|
|
48
|
+
# App
|
|
49
|
+
NODE_ENV enum("development", "production", "test") = "development"
|
|
50
|
+
PORT int = 3000 : 0 < x < 65535
|
|
51
|
+
DEBUG bool = false
|
|
52
|
+
CORS_ORIGIN str[] = "http://localhost:3000"
|
|
53
|
+
API_KEY str @required : len(x) >= 32
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Validate your `.env` file:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
envschema validate .env.schema --env .env
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
✓ DB_HOST = db.example.com
|
|
64
|
+
✓ DB_PORT = 5432
|
|
65
|
+
✓ DB_PASSWORD = ***
|
|
66
|
+
✓ NODE_ENV = development
|
|
67
|
+
✓ PORT = 3000
|
|
68
|
+
✗ API_KEY — validation failed: len(x) >= 32 (x='short')
|
|
69
|
+
⚠ UNKNOWN_VAR — not defined in schema
|
|
70
|
+
|
|
71
|
+
Result: 5 OK, 1 errors, 1 warnings
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Generate code:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
envschema generate .env.schema -t ts # TypeScript interface
|
|
78
|
+
envschema generate .env.schema -t zod # Zod v4 schema
|
|
79
|
+
envschema generate .env.schema -t pydantic # Pydantic BaseSettings
|
|
80
|
+
envschema generate .env.schema -t dataclasses # Python dataclass (no deps)
|
|
81
|
+
envschema generate .env.schema -t env-example # .env.example
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Features
|
|
85
|
+
|
|
86
|
+
### Types
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
HOST str = "localhost" # string
|
|
90
|
+
PORT int = 3000 # integer
|
|
91
|
+
RATIO float = 0.5 # float
|
|
92
|
+
DEBUG bool = false # boolean
|
|
93
|
+
API_PORT port = 8080 # port (int 1-65535)
|
|
94
|
+
BASE_URL url # URL (any scheme://)
|
|
95
|
+
ADMIN_EMAIL email # email
|
|
96
|
+
DATA_DIR path = "/var/data" # filesystem path
|
|
97
|
+
NODE_ENV enum("dev", "prod") # enum
|
|
98
|
+
HOSTS str[] # array (comma-separated)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Type inference from defaults — `PORT = 3000` is inferred as `int`.
|
|
102
|
+
|
|
103
|
+
### Decorators
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
DB_HOST str @required # must be set
|
|
107
|
+
DB_PASSWORD str @secret @required # hidden in output
|
|
108
|
+
LOG_LEVEL str @description("Logging level") # description
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Inline Validation
|
|
112
|
+
|
|
113
|
+
Python expressions with `x` as the value:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
PORT int = 3000 : 0 < x < 65535
|
|
117
|
+
API_KEY str @required : len(x) >= 32
|
|
118
|
+
RATE_LIMIT int = 100 : 0 < x < 10000
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Block Syntax
|
|
122
|
+
|
|
123
|
+
For complex variables:
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
DATABASE_URL {
|
|
127
|
+
type = url
|
|
128
|
+
description = "PostgreSQL connection string"
|
|
129
|
+
@secret
|
|
130
|
+
@required
|
|
131
|
+
validate = "x.startswith('postgres://')"
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Type Aliases
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
type LogLevel = enum("error", "warn", "info", "debug")
|
|
139
|
+
type ExtendedEnv = NodeEnv + enum("local")
|
|
140
|
+
|
|
141
|
+
LOG_LEVEL LogLevel = "warn"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Presets
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
#include <node.js> # built-in preset (NODE_ENV, PORT, HOST)
|
|
148
|
+
#include <vite> # VITE_* variables
|
|
149
|
+
#include "shared.schema" # local file
|
|
150
|
+
|
|
151
|
+
APP_NAME str = "myapp"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
envschema presets list # list available presets
|
|
156
|
+
envschema presets load directus # download from registry
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Wildcard Expansion
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
AUTH_PROVIDERS str[] = "google,github"
|
|
163
|
+
|
|
164
|
+
AUTH_{AUTH_PROVIDERS}_DRIVER str @required
|
|
165
|
+
AUTH_{AUTH_PROVIDERS}_CLIENT_ID str @secret @required
|
|
166
|
+
AUTH_{AUTH_PROVIDERS}_CLIENT_SECRET str @secret @required
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Expands to `AUTH_GOOGLE_DRIVER`, `AUTH_GITHUB_DRIVER`, etc.
|
|
170
|
+
Default filter: `upper`. Custom: `{AUTH_PROVIDERS|lower}`.
|
|
171
|
+
|
|
172
|
+
## CLI
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
envschema parse <file> # parse and display AST
|
|
176
|
+
envschema parse <file> --json # output as JSON
|
|
177
|
+
envschema validate <schema> --env <env> # validate .env against schema
|
|
178
|
+
envschema generate <schema> -t <target> # generate code
|
|
179
|
+
envschema generators list # list available targets
|
|
180
|
+
envschema presets list # list presets
|
|
181
|
+
envschema presets load <name> # download preset
|
|
182
|
+
envschema lsp # start LSP server (stdio)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## VS Code Extension
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
cd editors/vscode/envschema
|
|
189
|
+
npx @vscode/vsce package --allow-missing-repository
|
|
190
|
+
cursor --install-extension envschema-0.1.0.vsix
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Provides syntax highlighting for `.env.schema` files.
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
MIT
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# envschema
|
|
2
|
+
|
|
3
|
+
DSL for typed `.env` files — schema, validation, codegen.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install envschema
|
|
9
|
+
# or
|
|
10
|
+
uv add envschema
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
Create a `.env.schema` file:
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
# Database
|
|
19
|
+
DB_HOST str @required
|
|
20
|
+
DB_PORT port = 5432
|
|
21
|
+
DB_PASSWORD str @secret @required
|
|
22
|
+
DB_NAME str = "myapp"
|
|
23
|
+
|
|
24
|
+
# App
|
|
25
|
+
NODE_ENV enum("development", "production", "test") = "development"
|
|
26
|
+
PORT int = 3000 : 0 < x < 65535
|
|
27
|
+
DEBUG bool = false
|
|
28
|
+
CORS_ORIGIN str[] = "http://localhost:3000"
|
|
29
|
+
API_KEY str @required : len(x) >= 32
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Validate your `.env` file:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
envschema validate .env.schema --env .env
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
✓ DB_HOST = db.example.com
|
|
40
|
+
✓ DB_PORT = 5432
|
|
41
|
+
✓ DB_PASSWORD = ***
|
|
42
|
+
✓ NODE_ENV = development
|
|
43
|
+
✓ PORT = 3000
|
|
44
|
+
✗ API_KEY — validation failed: len(x) >= 32 (x='short')
|
|
45
|
+
⚠ UNKNOWN_VAR — not defined in schema
|
|
46
|
+
|
|
47
|
+
Result: 5 OK, 1 errors, 1 warnings
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Generate code:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
envschema generate .env.schema -t ts # TypeScript interface
|
|
54
|
+
envschema generate .env.schema -t zod # Zod v4 schema
|
|
55
|
+
envschema generate .env.schema -t pydantic # Pydantic BaseSettings
|
|
56
|
+
envschema generate .env.schema -t dataclasses # Python dataclass (no deps)
|
|
57
|
+
envschema generate .env.schema -t env-example # .env.example
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Features
|
|
61
|
+
|
|
62
|
+
### Types
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
HOST str = "localhost" # string
|
|
66
|
+
PORT int = 3000 # integer
|
|
67
|
+
RATIO float = 0.5 # float
|
|
68
|
+
DEBUG bool = false # boolean
|
|
69
|
+
API_PORT port = 8080 # port (int 1-65535)
|
|
70
|
+
BASE_URL url # URL (any scheme://)
|
|
71
|
+
ADMIN_EMAIL email # email
|
|
72
|
+
DATA_DIR path = "/var/data" # filesystem path
|
|
73
|
+
NODE_ENV enum("dev", "prod") # enum
|
|
74
|
+
HOSTS str[] # array (comma-separated)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Type inference from defaults — `PORT = 3000` is inferred as `int`.
|
|
78
|
+
|
|
79
|
+
### Decorators
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
DB_HOST str @required # must be set
|
|
83
|
+
DB_PASSWORD str @secret @required # hidden in output
|
|
84
|
+
LOG_LEVEL str @description("Logging level") # description
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Inline Validation
|
|
88
|
+
|
|
89
|
+
Python expressions with `x` as the value:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
PORT int = 3000 : 0 < x < 65535
|
|
93
|
+
API_KEY str @required : len(x) >= 32
|
|
94
|
+
RATE_LIMIT int = 100 : 0 < x < 10000
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Block Syntax
|
|
98
|
+
|
|
99
|
+
For complex variables:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
DATABASE_URL {
|
|
103
|
+
type = url
|
|
104
|
+
description = "PostgreSQL connection string"
|
|
105
|
+
@secret
|
|
106
|
+
@required
|
|
107
|
+
validate = "x.startswith('postgres://')"
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Type Aliases
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
type LogLevel = enum("error", "warn", "info", "debug")
|
|
115
|
+
type ExtendedEnv = NodeEnv + enum("local")
|
|
116
|
+
|
|
117
|
+
LOG_LEVEL LogLevel = "warn"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Presets
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
#include <node.js> # built-in preset (NODE_ENV, PORT, HOST)
|
|
124
|
+
#include <vite> # VITE_* variables
|
|
125
|
+
#include "shared.schema" # local file
|
|
126
|
+
|
|
127
|
+
APP_NAME str = "myapp"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
envschema presets list # list available presets
|
|
132
|
+
envschema presets load directus # download from registry
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Wildcard Expansion
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
AUTH_PROVIDERS str[] = "google,github"
|
|
139
|
+
|
|
140
|
+
AUTH_{AUTH_PROVIDERS}_DRIVER str @required
|
|
141
|
+
AUTH_{AUTH_PROVIDERS}_CLIENT_ID str @secret @required
|
|
142
|
+
AUTH_{AUTH_PROVIDERS}_CLIENT_SECRET str @secret @required
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Expands to `AUTH_GOOGLE_DRIVER`, `AUTH_GITHUB_DRIVER`, etc.
|
|
146
|
+
Default filter: `upper`. Custom: `{AUTH_PROVIDERS|lower}`.
|
|
147
|
+
|
|
148
|
+
## CLI
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
envschema parse <file> # parse and display AST
|
|
152
|
+
envschema parse <file> --json # output as JSON
|
|
153
|
+
envschema validate <schema> --env <env> # validate .env against schema
|
|
154
|
+
envschema generate <schema> -t <target> # generate code
|
|
155
|
+
envschema generators list # list available targets
|
|
156
|
+
envschema presets list # list presets
|
|
157
|
+
envschema presets load <name> # download preset
|
|
158
|
+
envschema lsp # start LSP server (stdio)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## VS Code Extension
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
cd editors/vscode/envschema
|
|
165
|
+
npx @vscode/vsce package --allow-missing-repository
|
|
166
|
+
cursor --install-extension envschema-0.1.0.vsix
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Provides syntax highlighting for `.env.schema` files.
|
|
170
|
+
|
|
171
|
+
## License
|
|
172
|
+
|
|
173
|
+
MIT
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "envschema-dsl"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "DSL for typed .env files — schema, validation, codegen"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
authors = [
|
|
8
|
+
{ name = "nike4192", email = "nike4192@outlook.com" }
|
|
9
|
+
]
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
keywords = ["env", "dotenv", "schema", "validation", "codegen", "typescript", "pydantic", "zod"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 3 - Alpha",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Programming Language :: Python :: 3.12",
|
|
17
|
+
"Topic :: Software Development :: Code Generators",
|
|
18
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
19
|
+
]
|
|
20
|
+
dependencies = [
|
|
21
|
+
"lark>=1.2",
|
|
22
|
+
"click>=8.0",
|
|
23
|
+
"pygls>=2.1.1",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.optional-dependencies]
|
|
27
|
+
dev = [
|
|
28
|
+
"pytest>=8.0",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/envschema/envschema"
|
|
33
|
+
Repository = "https://github.com/envschema/envschema"
|
|
34
|
+
|
|
35
|
+
[project.scripts]
|
|
36
|
+
envschema = "envschema.cli:cli"
|
|
37
|
+
|
|
38
|
+
[tool.uv.build-backend]
|
|
39
|
+
module-name = "envschema"
|
|
40
|
+
# PyPI name: envschema-dsl (envschema was taken)
|
|
41
|
+
# Import: from envschema import ...
|
|
42
|
+
|
|
43
|
+
[build-system]
|
|
44
|
+
requires = ["uv_build>=0.11.3,<0.12.0"]
|
|
45
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""EnvSchema — DSL for typed .env files."""
|
|
2
|
+
|
|
3
|
+
from .ast import (
|
|
4
|
+
ArrayType, Comment, Decorator, EnumType, Expansion, Include,
|
|
5
|
+
Schema, SimpleType, TypeAlias, TypeRef, UnionType, Variable,
|
|
6
|
+
)
|
|
7
|
+
from .parser import parse, parse_file
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"ArrayType",
|
|
11
|
+
"Comment",
|
|
12
|
+
"Decorator",
|
|
13
|
+
"EnumType",
|
|
14
|
+
"Include",
|
|
15
|
+
"Schema",
|
|
16
|
+
"SimpleType",
|
|
17
|
+
"TypeAlias",
|
|
18
|
+
"TypeRef",
|
|
19
|
+
"UnionType",
|
|
20
|
+
"Variable",
|
|
21
|
+
"parse",
|
|
22
|
+
"parse_file",
|
|
23
|
+
]
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""AST node definitions for EnvSchema DSL."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from enum import Enum
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SimpleType(Enum):
|
|
10
|
+
STR = "str"
|
|
11
|
+
INT = "int"
|
|
12
|
+
FLOAT = "float"
|
|
13
|
+
BOOL = "bool"
|
|
14
|
+
PORT = "port"
|
|
15
|
+
URL = "url"
|
|
16
|
+
EMAIL = "email"
|
|
17
|
+
PATH = "path"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class EnumType:
|
|
22
|
+
values: list[str]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class TypeRef:
|
|
27
|
+
"""Reference to a named type (from type alias or preset)."""
|
|
28
|
+
name: str
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class UnionType:
|
|
33
|
+
"""Union of types: TypeA + TypeB."""
|
|
34
|
+
types: list[SimpleType | EnumType | TypeRef]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class ArrayType:
|
|
39
|
+
element_type: SimpleType | EnumType | TypeRef
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class Decorator:
|
|
44
|
+
name: str
|
|
45
|
+
arg: str | None = None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class Expansion:
|
|
50
|
+
"""Wildcard expansion marker — {PROVIDERS} or {PROVIDERS|upper}."""
|
|
51
|
+
source: str # Variable name to expand from (e.g., "PROVIDERS")
|
|
52
|
+
filter: str | None = None # Optional filter (e.g., "upper")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass
|
|
56
|
+
class Include:
|
|
57
|
+
"""#include directive."""
|
|
58
|
+
target: str # preset name or file path
|
|
59
|
+
is_local: bool = False # True for "path", False for <preset>
|
|
60
|
+
line: int | None = None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class TypeAlias:
|
|
65
|
+
"""type Name = expr."""
|
|
66
|
+
name: str
|
|
67
|
+
value: SimpleType | EnumType | TypeRef | UnionType
|
|
68
|
+
line: int | None = None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass
|
|
72
|
+
class Variable:
|
|
73
|
+
name: str
|
|
74
|
+
type: SimpleType | EnumType | ArrayType | TypeRef | None = None
|
|
75
|
+
default: str | int | float | bool | None = None
|
|
76
|
+
decorators: list[Decorator] = field(default_factory=list)
|
|
77
|
+
validation: str | None = None
|
|
78
|
+
expansion: Expansion | None = None
|
|
79
|
+
line: int | None = None
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def is_required(self) -> bool:
|
|
83
|
+
return any(d.name == "required" for d in self.decorators)
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def is_secret(self) -> bool:
|
|
87
|
+
return any(d.name == "secret" for d in self.decorators)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclass
|
|
91
|
+
class Comment:
|
|
92
|
+
text: str
|
|
93
|
+
line: int | None = None
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@dataclass
|
|
97
|
+
class Schema:
|
|
98
|
+
variables: list[Variable] = field(default_factory=list)
|
|
99
|
+
comments: list[Comment] = field(default_factory=list)
|
|
100
|
+
includes: list[Include] = field(default_factory=list)
|
|
101
|
+
type_aliases: list[TypeAlias] = field(default_factory=list)
|
|
102
|
+
|
|
103
|
+
def resolve_type(self, name: str) -> SimpleType | EnumType | UnionType | None:
|
|
104
|
+
"""Look up a type alias by name."""
|
|
105
|
+
for alias in self.type_aliases:
|
|
106
|
+
if alias.name == name:
|
|
107
|
+
return alias.value
|
|
108
|
+
return None
|