jsonschema-ts 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.
- jsonschema_ts-0.1.0/.gitattributes +2 -0
- jsonschema_ts-0.1.0/.github/workflows/ci.yml +72 -0
- jsonschema_ts-0.1.0/.github/workflows/publish.yml +31 -0
- jsonschema_ts-0.1.0/.gitignore +26 -0
- jsonschema_ts-0.1.0/CONTRIBUTING.md +84 -0
- jsonschema_ts-0.1.0/LICENSE +21 -0
- jsonschema_ts-0.1.0/PKG-INFO +121 -0
- jsonschema_ts-0.1.0/README.md +95 -0
- jsonschema_ts-0.1.0/docs/app/docs/[[...slug]]/page.tsx +50 -0
- jsonschema_ts-0.1.0/docs/app/docs/layout.tsx +14 -0
- jsonschema_ts-0.1.0/docs/app/global.css +25 -0
- jsonschema_ts-0.1.0/docs/app/layout.tsx +18 -0
- jsonschema_ts-0.1.0/docs/app/page.tsx +65 -0
- jsonschema_ts-0.1.0/docs/content/docs/api.mdx +92 -0
- jsonschema_ts-0.1.0/docs/content/docs/getting-started.mdx +74 -0
- jsonschema_ts-0.1.0/docs/content/docs/index.mdx +42 -0
- jsonschema_ts-0.1.0/docs/content/docs/options-reference.mdx +49 -0
- jsonschema_ts-0.1.0/docs/content/docs/pydantic-integration.mdx +84 -0
- jsonschema_ts-0.1.0/docs/content/meta.json +9 -0
- jsonschema_ts-0.1.0/docs/lib/source.ts +8 -0
- jsonschema_ts-0.1.0/docs/next-env.d.ts +6 -0
- jsonschema_ts-0.1.0/docs/next.config.ts +10 -0
- jsonschema_ts-0.1.0/docs/package-lock.json +5503 -0
- jsonschema_ts-0.1.0/docs/package.json +27 -0
- jsonschema_ts-0.1.0/docs/postcss.config.mjs +5 -0
- jsonschema_ts-0.1.0/docs/source.config.ts +7 -0
- jsonschema_ts-0.1.0/docs/tsconfig.json +41 -0
- jsonschema_ts-0.1.0/docs/tsconfig.tsbuildinfo +1 -0
- jsonschema_ts-0.1.0/pyproject.toml +65 -0
- jsonschema_ts-0.1.0/src/jsonschema_ts/__init__.py +23 -0
- jsonschema_ts-0.1.0/src/jsonschema_ts/_converter.py +96 -0
- jsonschema_ts-0.1.0/src/jsonschema_ts/_defs_collector.py +37 -0
- jsonschema_ts-0.1.0/src/jsonschema_ts/_emitter.py +35 -0
- jsonschema_ts-0.1.0/src/jsonschema_ts/_errors.py +10 -0
- jsonschema_ts-0.1.0/src/jsonschema_ts/_options.py +12 -0
- jsonschema_ts-0.1.0/src/jsonschema_ts/_utils.py +43 -0
- jsonschema_ts-0.1.0/tests/__init__.py +0 -0
- jsonschema_ts-0.1.0/tests/fixtures/additional_props.json +9 -0
- jsonschema_ts-0.1.0/tests/fixtures/allOf.json +24 -0
- jsonschema_ts-0.1.0/tests/fixtures/anyOf.json +7 -0
- jsonschema_ts-0.1.0/tests/fixtures/circular_ref.json +25 -0
- jsonschema_ts-0.1.0/tests/fixtures/const.json +5 -0
- jsonschema_ts-0.1.0/tests/fixtures/edge_empty.json +1 -0
- jsonschema_ts-0.1.0/tests/fixtures/edge_no_title.json +6 -0
- jsonschema_ts-0.1.0/tests/fixtures/enum.json +5 -0
- jsonschema_ts-0.1.0/tests/fixtures/nested_defs.json +20 -0
- jsonschema_ts-0.1.0/tests/fixtures/nested_objects.json +26 -0
- jsonschema_ts-0.1.0/tests/fixtures/pydantic_user.json +36 -0
- jsonschema_ts-0.1.0/tests/fixtures/simple_object.json +12 -0
- jsonschema_ts-0.1.0/tests/fixtures/with_defs.json +30 -0
- jsonschema_ts-0.1.0/tests/test_converter.py +144 -0
- jsonschema_ts-0.1.0/tests/test_defs_collector.py +95 -0
- jsonschema_ts-0.1.0/tests/test_emitter.py +101 -0
- jsonschema_ts-0.1.0/tests/test_utils.py +40 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
lint:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Install Python
|
|
15
|
+
uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.11"
|
|
18
|
+
|
|
19
|
+
- name: Install dependencies
|
|
20
|
+
run: |
|
|
21
|
+
pip install --upgrade pip
|
|
22
|
+
pip install ruff
|
|
23
|
+
|
|
24
|
+
- name: Lint with ruff
|
|
25
|
+
run: ruff check src/ tests/
|
|
26
|
+
|
|
27
|
+
test:
|
|
28
|
+
needs: lint
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
strategy:
|
|
31
|
+
matrix:
|
|
32
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
33
|
+
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
|
|
37
|
+
- name: Install Python ${{ matrix.python-version }}
|
|
38
|
+
uses: actions/setup-python@v5
|
|
39
|
+
with:
|
|
40
|
+
python-version: ${{ matrix.python-version }}
|
|
41
|
+
|
|
42
|
+
- name: Install dependencies
|
|
43
|
+
run: |
|
|
44
|
+
pip install --upgrade pip
|
|
45
|
+
pip install -e ".[dev]"
|
|
46
|
+
|
|
47
|
+
- name: Run unit tests
|
|
48
|
+
run: pytest -v --cov=jsonschema_ts --cov-report=term-missing -m "not integration"
|
|
49
|
+
|
|
50
|
+
integration:
|
|
51
|
+
needs: lint
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
|
|
56
|
+
- name: Install Node.js
|
|
57
|
+
uses: actions/setup-node@v4
|
|
58
|
+
with:
|
|
59
|
+
node-version: "20"
|
|
60
|
+
|
|
61
|
+
- name: Install Python
|
|
62
|
+
uses: actions/setup-python@v5
|
|
63
|
+
with:
|
|
64
|
+
python-version: "3.11"
|
|
65
|
+
|
|
66
|
+
- name: Install dependencies
|
|
67
|
+
run: |
|
|
68
|
+
pip install --upgrade pip
|
|
69
|
+
pip install -e ".[dev]"
|
|
70
|
+
|
|
71
|
+
- name: Run integration tests
|
|
72
|
+
run: pytest -v -m integration
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install Python
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.11"
|
|
21
|
+
|
|
22
|
+
- name: Install build tools
|
|
23
|
+
run: |
|
|
24
|
+
pip install --upgrade pip
|
|
25
|
+
pip install hatchling build
|
|
26
|
+
|
|
27
|
+
- name: Build package
|
|
28
|
+
run: python -m build
|
|
29
|
+
|
|
30
|
+
- name: Publish to PyPI
|
|
31
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.venv/
|
|
8
|
+
.venv*/
|
|
9
|
+
|
|
10
|
+
# IDE
|
|
11
|
+
.idea/
|
|
12
|
+
.vscode/
|
|
13
|
+
*.swp
|
|
14
|
+
|
|
15
|
+
# OS
|
|
16
|
+
.DS_Store
|
|
17
|
+
Thumbs.db
|
|
18
|
+
|
|
19
|
+
# Specs design docs
|
|
20
|
+
specs/
|
|
21
|
+
|
|
22
|
+
# Docs site (Next.js)
|
|
23
|
+
docs/node_modules/
|
|
24
|
+
docs/.next/
|
|
25
|
+
docs/out/
|
|
26
|
+
docs/.source/
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Development Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
# Clone
|
|
7
|
+
git clone https://github.com/pyrpc/jsonschema-ts
|
|
8
|
+
cd jsonschema-ts
|
|
9
|
+
|
|
10
|
+
# Create virtualenv
|
|
11
|
+
python -m venv .venv
|
|
12
|
+
source .venv/bin/activate # or .venv\Scripts\Activate.ps1 on Windows
|
|
13
|
+
|
|
14
|
+
# Install dev dependencies
|
|
15
|
+
pip install -e ".[dev]"
|
|
16
|
+
|
|
17
|
+
# Install pre-commit hooks
|
|
18
|
+
pre-commit install
|
|
19
|
+
|
|
20
|
+
# Install docs site dependencies
|
|
21
|
+
cd docs && npm install
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Running Tests
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# All tests
|
|
28
|
+
pytest -v
|
|
29
|
+
|
|
30
|
+
# Unit tests only (no Node.js needed)
|
|
31
|
+
pytest -v -m "not integration"
|
|
32
|
+
|
|
33
|
+
# Integration tests (requires Node.js >= 18)
|
|
34
|
+
pytest -v -m integration
|
|
35
|
+
|
|
36
|
+
# Coverage report
|
|
37
|
+
pytest --cov=jsonschema_ts --cov-report=term-missing
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Code Style
|
|
41
|
+
|
|
42
|
+
- Ruff with line length 88
|
|
43
|
+
- Type hints on all public functions (3.11+ syntax)
|
|
44
|
+
- Private/internal functions prefixed with `_`
|
|
45
|
+
- Docstrings on all public API functions
|
|
46
|
+
- No em-dashes (--) in prose; use standard punctuation
|
|
47
|
+
- No emoji in code, comments, or documentation
|
|
48
|
+
|
|
49
|
+
Run linting:
|
|
50
|
+
```bash
|
|
51
|
+
ruff check .
|
|
52
|
+
ruff format --check .
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Pull Request Process
|
|
56
|
+
|
|
57
|
+
1. Create a feature branch from `main`
|
|
58
|
+
2. Write tests for any new functionality
|
|
59
|
+
3. Ensure all tests pass
|
|
60
|
+
4. Run `ruff check .` — no warnings
|
|
61
|
+
5. Open a PR with a clear description
|
|
62
|
+
|
|
63
|
+
## Release Process
|
|
64
|
+
|
|
65
|
+
1. Update version in `pyproject.toml` and `__init__.py`
|
|
66
|
+
2. Create a Git tag: `git tag v<version>`
|
|
67
|
+
3. Push tag: `git push origin v<version>`
|
|
68
|
+
4. CI publishes to PyPI automatically
|
|
69
|
+
|
|
70
|
+
## Project Structure
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
src/jsonschema_ts/ # Source code
|
|
74
|
+
__init__.py # Public API exports
|
|
75
|
+
_converter.py # convert(), convert_all(), _to_npx()
|
|
76
|
+
_defs_collector.py # collect_defs()
|
|
77
|
+
_emitter.py # assemble(), _strip_root_interface()
|
|
78
|
+
_errors.py # Exception classes
|
|
79
|
+
_options.py # Options dataclass
|
|
80
|
+
_utils.py # Utilities
|
|
81
|
+
tests/ # Tests (mirrors src structure)
|
|
82
|
+
fixtures/ # JSON Schema fixtures
|
|
83
|
+
docs/ # Next.js/Fumadocs documentation site
|
|
84
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 pyRPC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jsonschema-ts
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Convert JSON Schema to TypeScript interfaces (wraps json-schema-to-typescript)
|
|
5
|
+
Project-URL: Homepage, https://github.com/pyrpc/jsonschema-ts
|
|
6
|
+
Project-URL: Repository, https://github.com/pyrpc/jsonschema-ts
|
|
7
|
+
Project-URL: Documentation, https://github.com/pyrpc/jsonschema-ts
|
|
8
|
+
Author: pyRPC Contributors
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: codegen,json-schema,pydantic,typescript
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: ruff>=0.5.0; extra == 'dev'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# jsonschema-ts
|
|
28
|
+
|
|
29
|
+
> **Python to TypeScript converter, powered by json-schema-to-typescript**
|
|
30
|
+
|
|
31
|
+
Convert JSON Schema (from Pydantic v2 or any source) into clean TypeScript interfaces. A thin Python wrapper around the battle-tested [`json-schema-to-typescript`](https://github.com/bcherny/json-schema-to-typescript) engine.
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from jsonschema_ts import convert
|
|
35
|
+
|
|
36
|
+
schema = {
|
|
37
|
+
"type": "object",
|
|
38
|
+
"properties": {
|
|
39
|
+
"id": {"type": "integer"},
|
|
40
|
+
"name": {"type": "string"},
|
|
41
|
+
"email": {"type": "string", "format": "email"},
|
|
42
|
+
},
|
|
43
|
+
"required": ["id", "name", "email"],
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
ts = convert(schema, "User")
|
|
47
|
+
# export interface User {
|
|
48
|
+
# id: number;
|
|
49
|
+
# name: string;
|
|
50
|
+
# email: string;
|
|
51
|
+
# }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
- **Zero Python dependencies** — pure Python stdlib
|
|
57
|
+
- **Battle-tested engine** — wraps `json-schema-to-typescript`
|
|
58
|
+
- **Full JSON Schema support** — `$ref`, `$defs`, `allOf`, `anyOf`, `oneOf`, enums, tuples, circular refs, additional properties, const, and more
|
|
59
|
+
- **Pydantic v2 compatible** — works directly with `model_json_schema()` output
|
|
60
|
+
- **Batch conversion** — single npx call for all `$defs`
|
|
61
|
+
- **Clean output** — Prettier-formatted, `export interface` declarations
|
|
62
|
+
|
|
63
|
+
## Requirements
|
|
64
|
+
|
|
65
|
+
- Python ≥ 3.11
|
|
66
|
+
- Node.js ≥ 18 (with npx) — for the TypeScript generation engine
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install jsonschema-ts
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The first call to `convert()` will prompt `npx` to cache `json-schema-to-typescript`.
|
|
75
|
+
|
|
76
|
+
## Usage
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from jsonschema_ts import convert, convert_all, collect_defs
|
|
80
|
+
|
|
81
|
+
# Single schema
|
|
82
|
+
ts = convert(schema, "MyType")
|
|
83
|
+
|
|
84
|
+
# With $defs (for Pydantic models)
|
|
85
|
+
defs = collect_defs(schema)
|
|
86
|
+
model_ts = convert_all(defs)
|
|
87
|
+
|
|
88
|
+
# Full Pydantic pipeline
|
|
89
|
+
from pydantic import BaseModel
|
|
90
|
+
|
|
91
|
+
class Address(BaseModel):
|
|
92
|
+
street: str
|
|
93
|
+
city: str
|
|
94
|
+
zip: str
|
|
95
|
+
|
|
96
|
+
class User(BaseModel):
|
|
97
|
+
name: str
|
|
98
|
+
address: Address
|
|
99
|
+
|
|
100
|
+
schema = User.model_json_schema()
|
|
101
|
+
defs = collect_defs(schema)
|
|
102
|
+
models = convert_all(defs)
|
|
103
|
+
main = convert(schema, "User")
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## API
|
|
107
|
+
|
|
108
|
+
| Function | Description |
|
|
109
|
+
|---|---|
|
|
110
|
+
| `convert(schema, name)` | Convert single JSON Schema → TypeScript interface |
|
|
111
|
+
| `convert_all(defs)` | Convert all `$defs` → TypeScript interfaces (batch) |
|
|
112
|
+
| `collect_defs(*schemas)` | Extract and merge `$defs` from schemas |
|
|
113
|
+
| `ensure_npx()` | Check Node.js/npx availability |
|
|
114
|
+
|
|
115
|
+
## Why a wrapper?
|
|
116
|
+
|
|
117
|
+
`json-schema-to-typescript` has an **8-stage pipeline** (resolver → linker → normalizer → parser → optimizer → generator → formatter) with 18 normalization rules handling hundreds of edge cases. Reimplementing this in Python would take months. This package delegates the heavy lifting and focuses on what Python does best: orchestration, `$defs` collection, and output assembly.
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
MIT
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# jsonschema-ts
|
|
2
|
+
|
|
3
|
+
> **Python to TypeScript converter, powered by json-schema-to-typescript**
|
|
4
|
+
|
|
5
|
+
Convert JSON Schema (from Pydantic v2 or any source) into clean TypeScript interfaces. A thin Python wrapper around the battle-tested [`json-schema-to-typescript`](https://github.com/bcherny/json-schema-to-typescript) engine.
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from jsonschema_ts import convert
|
|
9
|
+
|
|
10
|
+
schema = {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"properties": {
|
|
13
|
+
"id": {"type": "integer"},
|
|
14
|
+
"name": {"type": "string"},
|
|
15
|
+
"email": {"type": "string", "format": "email"},
|
|
16
|
+
},
|
|
17
|
+
"required": ["id", "name", "email"],
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
ts = convert(schema, "User")
|
|
21
|
+
# export interface User {
|
|
22
|
+
# id: number;
|
|
23
|
+
# name: string;
|
|
24
|
+
# email: string;
|
|
25
|
+
# }
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Features
|
|
29
|
+
|
|
30
|
+
- **Zero Python dependencies** — pure Python stdlib
|
|
31
|
+
- **Battle-tested engine** — wraps `json-schema-to-typescript`
|
|
32
|
+
- **Full JSON Schema support** — `$ref`, `$defs`, `allOf`, `anyOf`, `oneOf`, enums, tuples, circular refs, additional properties, const, and more
|
|
33
|
+
- **Pydantic v2 compatible** — works directly with `model_json_schema()` output
|
|
34
|
+
- **Batch conversion** — single npx call for all `$defs`
|
|
35
|
+
- **Clean output** — Prettier-formatted, `export interface` declarations
|
|
36
|
+
|
|
37
|
+
## Requirements
|
|
38
|
+
|
|
39
|
+
- Python ≥ 3.11
|
|
40
|
+
- Node.js ≥ 18 (with npx) — for the TypeScript generation engine
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install jsonschema-ts
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The first call to `convert()` will prompt `npx` to cache `json-schema-to-typescript`.
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from jsonschema_ts import convert, convert_all, collect_defs
|
|
54
|
+
|
|
55
|
+
# Single schema
|
|
56
|
+
ts = convert(schema, "MyType")
|
|
57
|
+
|
|
58
|
+
# With $defs (for Pydantic models)
|
|
59
|
+
defs = collect_defs(schema)
|
|
60
|
+
model_ts = convert_all(defs)
|
|
61
|
+
|
|
62
|
+
# Full Pydantic pipeline
|
|
63
|
+
from pydantic import BaseModel
|
|
64
|
+
|
|
65
|
+
class Address(BaseModel):
|
|
66
|
+
street: str
|
|
67
|
+
city: str
|
|
68
|
+
zip: str
|
|
69
|
+
|
|
70
|
+
class User(BaseModel):
|
|
71
|
+
name: str
|
|
72
|
+
address: Address
|
|
73
|
+
|
|
74
|
+
schema = User.model_json_schema()
|
|
75
|
+
defs = collect_defs(schema)
|
|
76
|
+
models = convert_all(defs)
|
|
77
|
+
main = convert(schema, "User")
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## API
|
|
81
|
+
|
|
82
|
+
| Function | Description |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `convert(schema, name)` | Convert single JSON Schema → TypeScript interface |
|
|
85
|
+
| `convert_all(defs)` | Convert all `$defs` → TypeScript interfaces (batch) |
|
|
86
|
+
| `collect_defs(*schemas)` | Extract and merge `$defs` from schemas |
|
|
87
|
+
| `ensure_npx()` | Check Node.js/npx availability |
|
|
88
|
+
|
|
89
|
+
## Why a wrapper?
|
|
90
|
+
|
|
91
|
+
`json-schema-to-typescript` has an **8-stage pipeline** (resolver → linker → normalizer → parser → optimizer → generator → formatter) with 18 normalization rules handling hundreds of edge cases. Reimplementing this in Python would take months. This package delegates the heavy lifting and focuses on what Python does best: orchestration, `$defs` collection, and output assembly.
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
MIT
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { source } from '@/lib/source';
|
|
2
|
+
import {
|
|
3
|
+
DocsPage,
|
|
4
|
+
DocsBody,
|
|
5
|
+
DocsDescription,
|
|
6
|
+
DocsTitle,
|
|
7
|
+
} from 'fumadocs-ui/layouts/docs/page';
|
|
8
|
+
import { notFound } from 'next/navigation';
|
|
9
|
+
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
|
10
|
+
|
|
11
|
+
export default async function Page(props: {
|
|
12
|
+
params: Promise<{ slug?: string[] }>;
|
|
13
|
+
}) {
|
|
14
|
+
const params = await props.params;
|
|
15
|
+
const page = source.getPage(params.slug);
|
|
16
|
+
|
|
17
|
+
if (!page) {
|
|
18
|
+
notFound();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const MDX = page.data.body;
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<DocsPage toc={page.data.toc} full={page.data.full}>
|
|
25
|
+
<DocsTitle>{page.data.title}</DocsTitle>
|
|
26
|
+
<DocsDescription>{page.data.description}</DocsDescription>
|
|
27
|
+
<DocsBody>
|
|
28
|
+
<MDX components={{ ...defaultMdxComponents }} />
|
|
29
|
+
</DocsBody>
|
|
30
|
+
</DocsPage>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function generateStaticParams() {
|
|
35
|
+
return source.generateParams();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function generateMetadata(props: {
|
|
39
|
+
params: Promise<{ slug?: string[] }>;
|
|
40
|
+
}) {
|
|
41
|
+
const params = await props.params;
|
|
42
|
+
const page = source.getPage(params.slug);
|
|
43
|
+
|
|
44
|
+
if (!page) return {};
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
title: page.data.title,
|
|
48
|
+
description: page.data.description,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { source } from '@/lib/source';
|
|
2
|
+
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
export default function Layout({ children }: { children: ReactNode }) {
|
|
6
|
+
return (
|
|
7
|
+
<DocsLayout
|
|
8
|
+
nav={{ title: 'jsonschema-ts' }}
|
|
9
|
+
tree={source.pageTree}
|
|
10
|
+
>
|
|
11
|
+
{children}
|
|
12
|
+
</DocsLayout>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
@import 'tailwindcss';
|
|
2
|
+
@import 'fumadocs-ui/css/neutral.css';
|
|
3
|
+
@import 'fumadocs-ui/css/preset.css';
|
|
4
|
+
|
|
5
|
+
/* Remove the left gutter column so the sidebar sits flush at the viewport edge.
|
|
6
|
+
The 4-column grid places sidebar first, then main content, TOC, and right gutter. */
|
|
7
|
+
#nd-docs-layout {
|
|
8
|
+
grid-template:
|
|
9
|
+
"sidebar header toc toc"
|
|
10
|
+
"sidebar toc-popover toc toc"
|
|
11
|
+
"sidebar main toc toc" 1fr
|
|
12
|
+
/ var(--fd-sidebar-col) minmax(0, calc(
|
|
13
|
+
var(--fd-layout-width, 97rem) - var(--fd-sidebar-width) -
|
|
14
|
+
var(--fd-toc-width)
|
|
15
|
+
)) var(--fd-toc-width) minmax(min-content, 1fr) !important;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* When collapsed, keep the hover-trigger zone at the left viewport edge */
|
|
19
|
+
#nd-docs-layout[data-sidebar-collapsed="true"] [data-sidebar-placeholder] > div:first-child {
|
|
20
|
+
position: fixed !important;
|
|
21
|
+
inset: 0 auto auto 0 !important;
|
|
22
|
+
width: 16px !important;
|
|
23
|
+
height: 100dvh !important;
|
|
24
|
+
z-index: 50 !important;
|
|
25
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { RootProvider } from 'fumadocs-ui/provider/next';
|
|
3
|
+
import { Inter } from 'next/font/google';
|
|
4
|
+
import './global.css';
|
|
5
|
+
|
|
6
|
+
const inter = Inter({
|
|
7
|
+
subsets: ['latin'],
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export default function Layout({ children }: { children: ReactNode }) {
|
|
11
|
+
return (
|
|
12
|
+
<html lang="en" className={inter.className} suppressHydrationWarning>
|
|
13
|
+
<body suppressHydrationWarning>
|
|
14
|
+
<RootProvider>{children}</RootProvider>
|
|
15
|
+
</body>
|
|
16
|
+
</html>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import Link from 'next/link';
|
|
2
|
+
|
|
3
|
+
export default function HomePage() {
|
|
4
|
+
return (
|
|
5
|
+
<main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-neutral-950 to-neutral-900 px-4">
|
|
6
|
+
<div className="text-center">
|
|
7
|
+
<div className="mb-6 text-5xl font-light tracking-tighter text-neutral-500">
|
|
8
|
+
{'{ }'}
|
|
9
|
+
</div>
|
|
10
|
+
<h1 className="mb-3 text-4xl font-light text-neutral-100 sm:text-5xl">
|
|
11
|
+
jsonschema-ts
|
|
12
|
+
</h1>
|
|
13
|
+
<p className="mb-1 text-lg text-neutral-400">
|
|
14
|
+
Convert JSON Schema → TypeScript interfaces
|
|
15
|
+
</p>
|
|
16
|
+
<p className="mb-8 text-sm text-neutral-600">
|
|
17
|
+
Python · Zero deps · Battle-tested
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<div className="mb-10 flex items-center justify-center gap-4">
|
|
21
|
+
<Link
|
|
22
|
+
href="/docs"
|
|
23
|
+
className="rounded-lg border border-neutral-700 px-5 py-2.5 text-sm text-neutral-300 transition-colors hover:border-neutral-500 hover:text-white"
|
|
24
|
+
>
|
|
25
|
+
Docs
|
|
26
|
+
</Link>
|
|
27
|
+
<a
|
|
28
|
+
href="https://github.com/pyrpc/jsonschema-ts"
|
|
29
|
+
target="_blank"
|
|
30
|
+
rel="noreferrer"
|
|
31
|
+
className="rounded-lg border border-neutral-700 px-5 py-2.5 text-sm text-neutral-300 transition-colors hover:border-neutral-500 hover:text-white"
|
|
32
|
+
>
|
|
33
|
+
GitHub
|
|
34
|
+
</a>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<pre className="mx-auto mb-8 max-w-lg overflow-x-auto rounded-lg border border-neutral-800 bg-neutral-950/60 p-4 text-left text-sm leading-relaxed text-neutral-300">
|
|
38
|
+
<code>
|
|
39
|
+
<span className="text-blue-400">from</span>{' '}
|
|
40
|
+
<span className="text-amber-300">jsonschema_ts</span>{' '}
|
|
41
|
+
<span className="text-blue-400">import</span> convert{'\n\n'}
|
|
42
|
+
ts = convert(schema, <span className="text-green-300">'User'</span>)
|
|
43
|
+
{'\n'}
|
|
44
|
+
<span className="text-neutral-600">
|
|
45
|
+
{'# '}export interface User {'{'}
|
|
46
|
+
</span>
|
|
47
|
+
{'\n'}
|
|
48
|
+
<span className="text-neutral-600">
|
|
49
|
+
{'# '} name: string;
|
|
50
|
+
</span>
|
|
51
|
+
{'\n'}
|
|
52
|
+
<span className="text-neutral-600">
|
|
53
|
+
{'# '}
|
|
54
|
+
{'}'}
|
|
55
|
+
</span>
|
|
56
|
+
</code>
|
|
57
|
+
</pre>
|
|
58
|
+
|
|
59
|
+
<code className="rounded-md bg-neutral-900 px-3 py-1.5 text-sm text-neutral-500">
|
|
60
|
+
pip install jsonschema-ts
|
|
61
|
+
</code>
|
|
62
|
+
</div>
|
|
63
|
+
</main>
|
|
64
|
+
);
|
|
65
|
+
}
|