diff --git a/README.md b/README.md index 40bf830..71c0ecb 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Transfer your type safe Python data models to TypeScript: ![example](example.gif) +See the [docs](docs.md). + ## Similar projects * https://github.com/cs-cordero/py-ts-interfaces diff --git a/docs.md b/docs.md new file mode 100644 index 0000000..563f466 --- /dev/null +++ b/docs.md @@ -0,0 +1,67 @@ +# pydantic2zod + +Translates [pydantic](pydantic-docs.helpmanual.io/) -> [zod](zod.dev/) declarations. + +## Installation + +```sh +pip install git+https://github.com/argyle-engineering/pydantic2zod +``` + +## CLI + +The compiler must be run within the same Python environment as your project: +```sh +$ cd my-project +$ poetry run python -m pydantic2zod my_project.models +``` + +## As a library + +Translating **pydantic** declarations to **zod** out ouf the box may not work for +more sophisticated cases. Then you can use `pydantic2zod` as a library to implement +your own specific compiler: +```py +# my_project/scripts/pydantic_to_zod.py + +from pydantic2zod import Compiler + +class Compiler(pydantic2zod.Compiler) + ... + +ts_src = Compiler().parse("examples.eshop").to_zod() +print(ts_src) +``` + +Now lets say we want to omit some models as they may not be relative in your TypeScript code: +```py +class Compiler(pydantic2zod.Compiler): + IGNORE_TYPES = {"examples.eshop.Order"} +``` + +Or we can rename others: +```py +class Compiler(pydantic2zod.Compiler): + MODEL_RENAME_RULES = {"examples.eshop.Product": "Item"} +``` + +We can also manually edit the models and individual fields: +```py +class Compiler(pydantic2zod.Compiler): + MODEL_RENAME_RULES = {"examples.eshop.Product": "Item"} + + def _modify_models(self, pydantic_models: list[ClassDecl]) -> list[ClassDecl]: + for model in pydantic_models: + if model.name == "Item": + for f in model.fields: + # In pydantic declarations Product.description is optional. + # Lets make it required in zod. + if f.name == "description": + f.type = BuiltinType(name="str") + + return pydantic_models +``` + +We could even generate new models on the fly this way. + +See a more complete example at `examples/compiler_scripting.py`. diff --git a/examples/compiler_scripting.py b/examples/compiler_scripting.py new file mode 100644 index 0000000..ae58333 --- /dev/null +++ b/examples/compiler_scripting.py @@ -0,0 +1,26 @@ +import logging + +import pydantic2zod +from pydantic2zod.model import BuiltinType, ClassDecl + +logging.basicConfig(level=logging.INFO) + + +class Compiler(pydantic2zod.Compiler): + IGNORE_TYPES = {"examples.eshop.Order"} + MODEL_RENAME_RULES = {"examples.eshop.Product": "Item"} + + def _modify_models(self, pydantic_models: list[ClassDecl]) -> list[ClassDecl]: + for model in pydantic_models: + if model.name == "Item": + for f in model.fields: + # In pydantic declarations Product.description is optional. + # Lets make it required in zod. + if f.name == "description": + f.type = BuiltinType(name="str") + + return pydantic_models + + +ts_src = Compiler().parse("examples.eshop").to_zod() +print(ts_src)