@ryniaubenpm/quos-at-ullam
Version:
<h1 align="center"> Schema2TypeBox </h1>
280 lines (230 loc) • 8.71 kB
Markdown
<h1 align="center">
Schema2TypeBox
</h1>
<p align="center">
Creating TypeBox code from JSON schemas.
</p>
<p align="center">
<a href="https://github.com/ryniaubenpm/quos-at-ullam/blob/main/LICENSE">
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="ts2typebox is released under the MIT license." />
</a>
<a href="https://www.npmjs.org/package/@ryniaubenpm/quos-at-ullam">
<img src="https://img.shields.io/npm/v/@ryniaubenpm/quos-at-ullam?color=brightgreen&label=npm%20package" alt="Current npm package version." />
</a>
<a href="https://github.com/ryniaubenpm/quos-at-ullam/actions/workflows/buildAndTest.yaml">
<img src="https://github.com/ryniaubenpm/quos-at-ullam/actions/workflows/buildAndTest.yaml/badge.svg" alt="State of Github Action" />
</a>
</p>
## Installation
- `npm i -g /quos-at-ullam`
## Use Case
- You got **JSON schemas** that you want to validate your data against. But you
also want **automatic type inference** after validating the data. You have
chosen [typebox](https://github.com/sinclairzx81/typebox) for this, but figured
that you would need to manually create the typebox code. To avoid this pain, you
simply use `/quos-at-ullam` to generate the required code for you🎉.
## Usage
- The cli can be used with `/quos-at-ullam --input <fileName> --output
<fileName>`, or by simply running `/quos-at-ullam`. The input defaults to
"schema.json" and the output to "generated-typebox.ts" relative to the current
working directory. For more see [cli usage](#cli-usage).
## Examples
```typescript
//
// Let's start with our JSON schema
//
{
"title": "Person",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 20
},
"age": {
"type": "number",
"minimum": 18,
"maximum": 90
},
"hobbies": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"favoriteAnimal": {
"enum": ["dog", "cat", "sloth"]
}
},
"required": ["name", "age"]
}
//
// Which becomes..
//
export type Person = Static<typeof Person>;
export const Person = Type.Object({
name: Type.String({ minLength: 20 }),
age: Type.Number({ minimum: 18, maximum: 90 }),
hobbies: Type.Optional(Type.Array(Type.String(), { minItems: 1 })),
favoriteAnimal: Type.Optional(
Type.Union([
Type.Literal("dog"),
Type.Literal("cat"),
Type.Literal("sloth"),
])
),
});
//
// You can also split your JSON schema definitions into multiple files when
// using relative paths. Something like this:
//
// person.json
{
"title": "Person",
"type": "object",
"properties": {
"name": {
"type": "string",
"maxLength": 100
},
"age": {
"type": "number",
"minimum": 18
}
},
"required": ["name", "age"]
}
// status.json
{
"title": "Status",
"enum": ["unknown", "accepted", "denied"]
}
// schema.json
{
"title": "Contract",
"type": "object",
"properties": {
"person": {
"$ref": "./person.json"
},
"status": {
"$ref": "./status.json"
}
},
"required": ["person"]
}
//
// Will result in this:
//
export type Contract = Static<typeof Contract>;
export const Contract = Type.Object({
person: Type.Object({
name: Type.String({ maxLength: 100 }),
age: Type.Number({ minimum: 18 }),
}),
status: Type.Optional(
Type.Union([
Type.Literal("unknown"),
Type.Literal("accepted"),
Type.Literal("denied"),
])
),
});
//
// For an example of programmatic usage check out the examples folder.
//
```
Please take a look at the [feature list](feature-list) below to see the
currently supported features. For examples, take a look into the
[examples](https://github.com/ryniaubenpm/quos-at-ullam/tree/main/examples) folder.
You can also check the test cases, every feature is tested.
### Schema Support
The package is focused on supporting JSON schema draft-07 files, since this is
the target TypeBox officially supports. _These types are fully compatible with
the JSON Schema Draft 7 specification._ (from typebox repo 20.08.2023).
However, since the amount of breaking changes is quite small between most JSON
schema specs, support for other specs should "just work". Feel free to open a
discussion or issue when you find problems. Happy about contributions if you
want to help out.
- [x] draft-04
- [x] draft-06
- [x] draft-07 (main goal of this package, see Feature List for the state)
- [x] draft-2019-09
- should be working with the _current feature set_
- [ ] draft-2020-12
- use with caution. Not expected to fully work. See
[here](https://github.com/sinclairzx81/typebox/issues/490)
### Feature List
Tracking the progress/features of `JSON schema -> TypeBox` transformation to see
whats already implemented and what is missing.
- [x] Type.String() via "string" instance type
- [x] Type.Boolean() via "boolean" instance type
- [x] Type.Number() via "number" instance type
- [x] Type.Null() via "null" instance type
- [x] Type.Array() via "array" instance type
- [x] Type.Object() via "object" instance type
- [x] Type.Literal() via "const" property
- [x] Type.Union() via "anyOf" or "enum" property
- /quos-at-ullam generates union types instead of enums. If you have a problem
with this behaviour and valid arguments for using enums please create an
issue and it may be considered again.
- [x] Type.Union() via a list of types given by the 'type' instance type (e.g.
type ["string","null"]
- [x] Type.Intersect() via "allOf" property
- [x] OneOf() via "oneOf" property
- This adds oneOf to the typebox type registry as (Kind: 'ExtendedOneOf') in
order to be able to align to oneOf json schema semantics and still be able
to use the typebox compiler. [More
info](https://github.com/ryniaubenpm/quos-at-ullam/issues/16).
- [x] Type.Not() via "not" property
- [x] Type.Unknown() for objects without properties
- [x] Full support for schema options (e.g. minLength: 1, description: "test
entity").
- [x] $refs anywhere using [/json-schema-ref-parser](https://github.com/APIDevTools/json-schema-ref-parser)
- [ ] (low prio) Type.Tuple() via "array" instance type with minimalItems,
maximalItems and additionalItems false
## DEV/CONTRIBUTOR NOTES
- If you have an idea or want to help implement something, feel free to do so.
Please always start by creating a discussion post to avoid any unnecessary
work.
- Please always create tests for new features that are implemented. This will
decrease mental overhead for reviewing and developing in the long run.
- See specification for JSON schema draft-07
[here](https://json-schema.org/specification-links.html#draft-7). The meta
schema is also stored inside this repo under ./meta-schema-draft-07.json.
## cli usage
The following text is the output that will be displayed when you issue
`/quos-at-ullam -h` or `@ryniaubenpm/quos-at-ullam --help`.
```
/quos-at-ullam generates TypeBox code from JSON schemas. The generated
output is formatted based on the prettier config inside your repo (or the
default one, if you don't have one). Version: ${packageJson.version}
Usage:
/quos-at-ullam [ARGUMENTS]
Arguments:
-h, --help
Displays this menu.
-i, --input
Specifies the relative path to the file containing the JSON schema that
will be used to generated typebox code. Defaults to "schema.json".
-o, --output
Specifies the relative path to generated file that will contain the
typebox code. Defaults to "generated-typebox.ts".
--output-stdout
Does not generate an output file and prints the generated code to stdout
instead. Has precedence over -o/--output.
```
### Code coverage
This project aims for high code coverage. When you add new features or fix a
bug, please add a test for it. This is what I could get out of the [experimental
code coverage](https://nodejs.org/api/test.html#collecting-code-coverage) from
node test runner in v20.03.1. Was run with code from 28.06.2023.
| File | Line % | Branch % | Funcs % |
| ------------------------------ | ------ | -------- | ------- |
| dist/src/programmatic-usage.js | 95.83 | 53.33 | 80.00 |
| dist/src/schema-to-typebox.js | 92.06 | 86.54 | 94.74 |
While I enjoy using the test runner from nodejs itself,
this feature is still lacking.
### Template Repo
Template for the repo setup was taken from [here](https://github.com/xddq/nodejs-typescript-modern-starter).