UNPKG

@ryniaubenpm/quos-at-ullam

Version:
280 lines (230 loc) 8.71 kB
<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 @ryniaubenpm/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 `@ryniaubenpm/quos-at-ullam` to generate the required code for you🎉. ## Usage - The cli can be used with `@ryniaubenpm/quos-at-ullam --input <fileName> --output <fileName>`, or by simply running `@ryniaubenpm/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 - @ryniaubenpm/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 [@apidevtools/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 `@ryniaubenpm/quos-at-ullam -h` or `@ryniaubenpm/quos-at-ullam --help`. ``` @ryniaubenpm/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: @ryniaubenpm/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).