├── .github └── workflows │ ├── buildAndTest.yaml │ └── publish.yaml ├── .gitignore ├── .nvmrc ├── .vimspector.json ├── .vimspector.session ├── .yarn └── releases │ └── yarn-3.5.1.cjs ├── .yarnrc.yml ├── LICENSE ├── README.md ├── changelog.md ├── examples ├── basic │ ├── README.md │ ├── generated-types.ts │ └── types.ts ├── disable-autogen-comment │ ├── README.md │ ├── generated-types.ts │ └── types.ts ├── json-schema-options │ ├── README.md │ ├── generated-types.ts │ └── types.ts ├── programmatic-usage │ ├── .gitignore │ ├── README.md │ ├── generated-typebox.ts │ ├── index.ts │ ├── package.json │ ├── types.ts │ └── yarn.lock ├── skip-type-generation │ ├── .ts2typeboxrc.cjs │ ├── README.md │ ├── generated-schemas.ts │ ├── index.ts │ └── types.ts └── transform-value-transform-type │ ├── .ts2typeboxrc.cjs │ ├── README.md │ ├── generated-types.ts │ └── types.ts ├── git-hooks └── pre-commit ├── package.json ├── src ├── cli │ ├── cli.ts │ └── index.ts ├── codeOptions.cjs ├── index.ts ├── jsdoc.ts └── programmatic-usage.ts ├── test └── index.ts ├── tsconfig.json └── yarn.lock /.github/workflows/buildAndTest.yaml: -------------------------------------------------------------------------------- 1 | name: build and test codebase 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | build-and-test: 7 | runs-on: ${{ matrix.os }} 8 | 9 | strategy: 10 | matrix: 11 | node-version: [18.x, 20.x] 12 | os: [ubuntu-latest, macos-latest] 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: Use Node.js ${{ matrix.node-version }} 17 | uses: actions/setup-node@v3 18 | with: 19 | node-version: ${{ matrix.node-version }} 20 | - name: Install Dependencies 21 | run: yarn --immutable 22 | - name: Build 23 | run: yarn build 24 | - name: Test 25 | run: npm test 26 | -------------------------------------------------------------------------------- /.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | # src: https://github.com/JS-DevTools/npm-publish 2 | on: 3 | push: 4 | branches: main 5 | 6 | jobs: 7 | publish: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: actions/setup-node@v3 12 | with: 13 | node-version-file: ".nvmrc" 14 | - name: Use yarn via corepack 15 | run: corepack enable 16 | - name: Install Dependencies 17 | run: yarn --immutable 18 | - name: Compile 19 | run: yarn build 20 | - uses: JS-DevTools/npm-publish@v3 21 | with: 22 | token: ${{ secrets.NPM_TOKEN }} 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Taken from https://github.com/github/gitignore/blob/main/Node.gitignore 2 | # and added custom ignores 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | *.lcov 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | node_modules/ 46 | jspm_packages/ 47 | 48 | # Snowpack dependency directory (https://snowpack.dev/) 49 | web_modules/ 50 | 51 | # TypeScript cache 52 | *.tsbuildinfo 53 | 54 | # Optional npm cache directory 55 | .npm 56 | 57 | # Optional eslint cache 58 | .eslintcache 59 | 60 | # Optional stylelint cache 61 | .stylelintcache 62 | 63 | # Microbundle cache 64 | .rpt2_cache/ 65 | .rts2_cache_cjs/ 66 | .rts2_cache_es/ 67 | .rts2_cache_umd/ 68 | 69 | # Optional REPL history 70 | .node_repl_history 71 | 72 | # Output of 'npm pack' 73 | *.tgz 74 | 75 | # Yarn Integrity file 76 | .yarn-integrity 77 | 78 | # dotenv environment variable files 79 | .env 80 | .env.development.local 81 | .env.test.local 82 | .env.production.local 83 | .env.local 84 | 85 | # parcel-bundler cache (https://parceljs.org/) 86 | .cache 87 | .parcel-cache 88 | 89 | # Next.js build output 90 | .next 91 | out 92 | 93 | # Nuxt.js build / generate output 94 | .nuxt 95 | dist 96 | 97 | # Gatsby files 98 | .cache/ 99 | # Comment in the public line in if your project uses Gatsby and not Next.js 100 | # https://nextjs.org/blog/next-9-1#public-directory-support 101 | # public 102 | 103 | # vuepress build output 104 | .vuepress/dist 105 | 106 | # vuepress v2.x temp and cache directory 107 | .temp 108 | .cache 109 | 110 | # Docusaurus cache and generated files 111 | .docusaurus 112 | 113 | # Serverless directories 114 | .serverless/ 115 | 116 | # FuseBox cache 117 | .fusebox/ 118 | 119 | # DynamoDB Local files 120 | .dynamodb/ 121 | 122 | # TernJS port file 123 | .tern-port 124 | 125 | # Stores VSCode versions used for testing VSCode extensions 126 | .vscode-test 127 | 128 | # yarn v2 129 | .yarn/cache 130 | .yarn/unplugged 131 | .yarn/build-state.yml 132 | .yarn/install-state.gz 133 | .pnp.* 134 | 135 | # custom added ignores below 136 | bundle 137 | dist 138 | node_modules 139 | TODO 140 | schema.json 141 | 142 | node_modules 143 | dist 144 | TODO 145 | coverage 146 | /generated-types.ts 147 | /types.ts 148 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 18.16.0 2 | -------------------------------------------------------------------------------- /.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "run": { 4 | "adapter": "vscode-node", 5 | "breakpoints": { 6 | "exception": { 7 | "all": "N", 8 | "uncaught": "Y" 9 | } 10 | }, 11 | "configuration": { 12 | "request": "launch", 13 | "protocol": "auto", 14 | "stopOnEntry": false, 15 | "console": "integratedTerminal", 16 | "program": "${workspaceRoot}/src/index.ts", 17 | "outFiles": ["${workspaceRoot}/dist/**/*.js"], 18 | "env": { "TS_NODE_BASEURL": "./dist" }, 19 | "runtimeArgs": ["-r", "tsconfig-paths/register"], 20 | "cwd": "${workspaceRoot}" 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.vimspector.session: -------------------------------------------------------------------------------- 1 | {"breakpoints": {"line": {"/home/xddq/progproj/gitlab-freedom/ts2typebox/src/typescript-to-typebox.ts": [{"state": "ENABLED", "line": 129, "options": {}, "is_instruction_breakpoint": null}, {"state": "ENABLED", "line": 113, "options": {}, "is_instruction_breakpoint": null}, {"state": "ENABLED", "line": 112, "options": {}, "is_instruction_breakpoint": null}]}, "function": [], "exception": {"filters": ["uncaught"]}}, "session": {"user_choices": {}}, "variables": {"watches": []}} -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | yarnPath: .yarn/releases/yarn-3.5.1.cjs 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Pierre Dahmani 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | ts2typebox 3 |

4 | 5 |

6 | Creating TypeBox code from Typescript types. 7 |

8 | 9 |

10 | 11 | ts2typebox is released under the MIT license. 12 | 13 | 14 | Current npm package version. 15 | 16 | 17 | State of Github Action 18 | 19 |

20 | 21 | Cli tool which leverages the awesome 22 | [typebox-codegen](https://github.com/sinclairzx81/typebox-codegen) package by 23 | [sinclairzx81](https://github.com/sinclairzx81). 24 | 25 | ## Installation 26 | 27 | - `npm i -g ts2typebox` 28 | 29 | ## Use Case 30 | 31 | - You got a typescript project with types already lying around and are looking 32 | for a quick and easy way to get validations and JSON schemas based on them. 33 | - You prefer leveraging typescript to define your data types and to generate 34 | your validators and/or JSON schemas. 35 | 36 | ## Usage 37 | 38 | - The cli can be used with `ts2typebox --input --output `, 39 | or by simply running `ts2typebox`. The input defaults to "types.ts" and the 40 | output to "generated-types.ts" relative to the current working directory. For 41 | more see [cli usage](#cli-usage). 42 | 43 | ## Examples 44 | 45 | ```typescript 46 | // 47 | // Let's start with a simple type 48 | // 49 | 50 | export type Person = { 51 | age: number; 52 | name: string; 53 | }; 54 | 55 | // 56 | // Which becomes 57 | // 58 | 59 | import { Type, Static } from "@sinclair/typebox"; 60 | 61 | export type Person = Static; 62 | export const Person = Type.Object({ 63 | age: Type.Number(), 64 | name: Type.String(), 65 | }); 66 | 67 | // 68 | // Similarly, with an interface 69 | // 70 | 71 | export interface IPerson { 72 | age: number; 73 | name: string; 74 | } 75 | 76 | // 77 | // Which becomes 78 | // 79 | 80 | import { Type, Static } from "@sinclair/typebox"; 81 | 82 | export type IPerson = Static; 83 | export const IPerson = Type.Object({ 84 | age: Type.Number(), 85 | name: Type.String(), 86 | }); 87 | 88 | // 89 | // Let's add some more complicated types. What about unions and intersections? 90 | // 91 | 92 | export type T = { x: number } & { y: number }; 93 | export type U = { x: number } | { y: number }; 94 | 95 | // 96 | // Which becomes 97 | // 98 | 99 | import { Type, Static } from "@sinclair/typebox"; 100 | 101 | export type T = Static; 102 | export const T = Type.Intersect([ 103 | Type.Object({ 104 | x: Type.Number(), 105 | }), 106 | Type.Object({ 107 | y: Type.Number(), 108 | }), 109 | ]); 110 | 111 | export type U = Static; 112 | export const U = Type.Union([ 113 | Type.Object({ 114 | x: Type.Number(), 115 | }), 116 | Type.Object({ 117 | y: Type.Number(), 118 | }), 119 | ]); 120 | 121 | // 122 | // Nice! But I will need some JSON schema options here and there, which can't be 123 | // expressed in typescript at all... 124 | // No worries, simply use jsdoc in your types! 125 | // 126 | /** 127 | * @minimum 100 128 | * @maximum 200 129 | * @multipleOf 2 130 | * @default 150 131 | * @description "it's a number" - strings must be quoted 132 | * @foobar "should support unknown props" 133 | */ 134 | export type T = number; 135 | 136 | // 137 | // Which becomes 138 | // 139 | 140 | import { Type, Static } from "@sinclair/typebox"; 141 | 142 | export type T = Static; 143 | export const T = Type.Number({ 144 | minimum: 100, 145 | maximum: 200, 146 | multipleOf: 2, 147 | default: 150, 148 | description: "it's a number", 149 | foobar: "should support unknown props", 150 | }); 151 | 152 | // 153 | // Well, what if I don't like that the generated type and value has the same 154 | // name?! No worries, you can define your own transformation functions! 155 | // So that this.. 156 | // 157 | 158 | export type Person = { 159 | age: number; 160 | name: string; 161 | }; 162 | 163 | // 164 | // Can easily become 165 | // 166 | 167 | import { Type, Static } from "@sinclair/typebox"; 168 | 169 | export type PersonType = Static; 170 | export const PersonSchema = Type.Object({ 171 | age: Type.Number(), 172 | name: Type.String(), 173 | }); 174 | 175 | // 176 | // Sounds great! But I have many comments in my Typescript types and I want to 177 | // use them as source of truth for my code. Can this be done..? 178 | // Yup! We can start with this... 179 | // 180 | 181 | export type Person = { 182 | /** 183 | * @minimum 18 184 | */ 185 | age: number; 186 | /** 187 | * @description full name of the person 188 | */ 189 | name: string; 190 | }; 191 | 192 | // 193 | // And end up only generating the JSON schema/TypeBox values. 194 | // 195 | 196 | export const PersonSchema = Type.Object({ 197 | age: Type.Number({ minimum: 18 }), 198 | name: Type.String({ description: "full name of the person" }), 199 | }); 200 | 201 | // 202 | // For an example of programmatic usage check out the examples folder. 203 | // 204 | ``` 205 | 206 | For hands on examples, you can follow the simple snippets stored inside the 207 | [examples](https://github.com/xddq/ts2typebox/tree/main/examples) folder. For a 208 | more complete set of examples (every feature is tested) you can take a look at 209 | the tests inside this repo for the programmatic usage and inside the tests in 210 | [@sinclair/typebox-codegen](https://github.com/sinclairzx81/typebox-codegen) 211 | repo for the typegen. 212 | 213 | ## cli usage 214 | 215 | The following text is the output that will be displayed when you issue `ts2typebox -h` or 216 | `ts2typebox --help`. 217 | 218 | ``` 219 | 220 | ts2typebox generates TypeBox code from Typescript code. 221 | Version: ${packageJson.version} 222 | 223 | Usage: 224 | 225 | ts2typebox [ARGUMENTS] 226 | 227 | Arguments: 228 | 229 | -h, --help 230 | Displays this menu. 231 | 232 | -i, --input 233 | Specifies the relative path to the file containing the typescript types 234 | that will be used to generated typebox types. Defaults to "types.ts". 235 | 236 | -o, --output 237 | Specifies the relative path to generated file that will contain the 238 | typebox types. Defaults to "generated-types.ts". 239 | 240 | --output-stdout 241 | Does not generate an output file and prints the generated code to stdout 242 | instead. Has precedence over -o/--output. 243 | 244 | --disable-autogen-comment 245 | When used, it does not add the comment at the beginning of the generated 246 | file which is stating that the code was automatically generated. 247 | 248 | --skip-type-creation 249 | When used, strips all types from the generated code. This can be helpful 250 | if you want to use your Typescript types inside your input file (which 251 | probably contains comments) as source of truth and still use the generated 252 | TypeBox code (schema validators) to validate data based on these types. 253 | When using this option you probably want to also provide a custom 254 | transformValue function since two same symbols can't be imported from two 255 | different files. For an example take a look inside the repo under 256 | ./examples/skip-type-creation. 257 | 258 | Additional: 259 | 260 | Transformations 261 | 262 | You can adapt the names of the generated types (as well as the names of the 263 | generated values) using custom transformation functions which take a string 264 | as an input and return a string as their output. These will run on each of 265 | the generated types and values, respectively. Please take a look inside the 266 | repo under ./examples/transform-value-transform-type for an example of this. 267 | 268 | Formatting 269 | 270 | The generated output is formatted based on the prettier config inside your 271 | 272 | ``` 273 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # 1.6.2 2 | 3 | - Updated code generation to use `CloneType` instead of deprecated `TypeClone`. New minimum versions: @sinclair/typebox ^0.34.35 and @typebox/codegen ^0.10.5 4 | 5 | # 1.6.1 6 | 7 | - stop using fixed dependency versions so users of this package can e.g. use the latest typescript version. See https://github.com/xddq/ts2typebox/pull/27 8 | 9 | # 1.6.0 10 | 11 | - use typebox as peer dependency, update to current typebox major 0.32.X -------------------------------------------------------------------------------- /examples/basic/README.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | When ts2typebox is installed (simply issue npm i -g ts2typebox to do so), clone 4 | the repo, cd into this directory and: 5 | 6 | - Remove the old generated-types.ts file `rm generated-types.ts` 7 | - Use ts2typebox to generate the typebox types based on the types.ts file 8 | `ts2typebox` 9 | - done :] 10 | -------------------------------------------------------------------------------- /examples/basic/generated-types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ATTENTION. This code was AUTO GENERATED by ts2typebox. While I don't know 3 | * your use case, there is a high chance that direct changes to this file get 4 | * lost. Consider making changes to the underlying Typescript code you use to 5 | * generate this file instead. The default file is called "types.ts", perhaps 6 | * have a look there! :] 7 | */ 8 | 9 | import { Type, Static } from "@sinclair/typebox"; 10 | 11 | type Age = Static; 12 | const Age = Type.Number(); 13 | 14 | export type Address = Static; 15 | export const Address = Type.Object({ 16 | street: Type.String(), 17 | city: Type.String(), 18 | state: Type.String(), 19 | postalCode: Type.String(), 20 | }); 21 | 22 | export type Contact = Static; 23 | export const Contact = Type.Object({ 24 | phone: Type.String(), 25 | email: Type.String(), 26 | }); 27 | 28 | export type Person = Static; 29 | export const Person = Type.Object({ 30 | name: Type.String(), 31 | age: Age, 32 | address: Address, 33 | contact: Contact, 34 | }); 35 | -------------------------------------------------------------------------------- /examples/basic/types.ts: -------------------------------------------------------------------------------- 1 | // Arbitrary example types 2 | 3 | type Age = number; 4 | 5 | export type Address = { 6 | street: string; 7 | city: string; 8 | state: string; 9 | postalCode: string; 10 | }; 11 | 12 | export type Contact = { 13 | phone: string; 14 | email: string; 15 | }; 16 | 17 | export type Person = { 18 | name: string; 19 | age: Age; 20 | address: Address; 21 | contact: Contact; 22 | }; 23 | -------------------------------------------------------------------------------- /examples/disable-autogen-comment/README.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | When ts2typebox is installed (simply issue npm i -g ts2typebox to do so), clone 4 | the repo, cd into this directory and: 5 | 6 | - Remove the old generated-types.ts file `rm generated-types.ts` 7 | - Use ts2typebox to generate the typebox types based on the types.ts file 8 | `ts2typebox --disable-autogen-comment` 9 | - done :] 10 | -------------------------------------------------------------------------------- /examples/disable-autogen-comment/generated-types.ts: -------------------------------------------------------------------------------- 1 | import { Type, Static } from "@sinclair/typebox"; 2 | 3 | type Age = Static; 4 | const Age = Type.Number(); 5 | 6 | export type Address = Static; 7 | export const Address = Type.Object({ 8 | street: Type.String(), 9 | city: Type.String(), 10 | state: Type.String(), 11 | postalCode: Type.String(), 12 | }); 13 | 14 | export type Contact = Static; 15 | export const Contact = Type.Object({ 16 | phone: Type.String(), 17 | email: Type.String(), 18 | }); 19 | 20 | export type Person = Static; 21 | export const Person = Type.Object({ 22 | name: Type.String(), 23 | age: Type.Number(), 24 | address: Address, 25 | contact: Contact, 26 | }); 27 | -------------------------------------------------------------------------------- /examples/disable-autogen-comment/types.ts: -------------------------------------------------------------------------------- 1 | // Arbitrary example types 2 | 3 | type Age = number; 4 | 5 | export type Address = { 6 | street: string; 7 | city: string; 8 | state: string; 9 | postalCode: string; 10 | }; 11 | 12 | export type Contact = { 13 | phone: string; 14 | email: string; 15 | }; 16 | 17 | export type Person = { 18 | name: string; 19 | age: number; 20 | address: Address; 21 | contact: Contact; 22 | }; 23 | -------------------------------------------------------------------------------- /examples/json-schema-options/README.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | When ts2typebox is installed (simply issue npm i -g ts2typebox to do so), clone 4 | the repo, cd into this directory and: 5 | 6 | - Remove the old generated-types.ts file `rm generated-types.ts` 7 | - Use ts2typebox to generate the typebox types based on the types.ts file 8 | `ts2typebox` 9 | - done :] 10 | -------------------------------------------------------------------------------- /examples/json-schema-options/generated-types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ATTENTION. This code was AUTO GENERATED by ts2typebox. While I don't know 3 | * your use case, there is a high chance that direct changes to this file get 4 | * lost. Consider making changes to the underlying Typescript code you use to 5 | * generate this file instead. The default file is called "types.ts", perhaps 6 | * have a look there! :] 7 | */ 8 | 9 | import { Type, Static } from "@sinclair/typebox"; 10 | 11 | export type T = Static; 12 | export const T = Type.Object({ 13 | a: Type.Number({ 14 | minimum: 100, 15 | maximum: 200, 16 | multipleOf: 2, 17 | default: 150, 18 | description: "it's a number", 19 | anotherDescription: "can also use as quotes", 20 | foobar: "should support unknown props", 21 | }), 22 | }); 23 | -------------------------------------------------------------------------------- /examples/json-schema-options/types.ts: -------------------------------------------------------------------------------- 1 | // Arbitrary example types 2 | 3 | export type T = { 4 | /** 5 | * @minimum 100 6 | * @maximum 200 7 | * @multipleOf 2 8 | * @default 150 9 | * @description "it's a number" - strings must be quoted 10 | * @anotherDescription 'can also use as quotes' 11 | * @foobar "should support unknown props" 12 | */ 13 | a: number; 14 | }; 15 | -------------------------------------------------------------------------------- /examples/programmatic-usage/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .yarn 3 | -------------------------------------------------------------------------------- /examples/programmatic-usage/README.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | - Install dependencies `yarn` 4 | - Remove the old generated-typebox.ts file `rm generated-typebox.ts` 5 | - Start the code `yarn start` (generated-typebox.ts) 6 | - generated-typebox.ts should now again exist in the folder 7 | - done 🎉 8 | -------------------------------------------------------------------------------- /examples/programmatic-usage/generated-typebox.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ATTENTION. This code was AUTO GENERATED by ts2typebox. While I don't know 3 | * your use case, there is a high chance that direct changes to this file get 4 | * lost. Consider making changes to the underlying Typescript code you use to 5 | * generate this file instead. The default file is called "types.ts", perhaps 6 | * have a look there! :] 7 | */ 8 | 9 | import { Type, Static } from "@sinclair/typebox"; 10 | 11 | type Age = Static; 12 | const Age = Type.Number(); 13 | 14 | export type Address = Static; 15 | export const Address = Type.Object({ 16 | street: Type.String(), 17 | city: Type.String(), 18 | state: Type.String(), 19 | postalCode: Type.String(), 20 | }); 21 | 22 | export type Contact = Static; 23 | export const Contact = Type.Object({ 24 | phone: Type.String(), 25 | email: Type.String(), 26 | }); 27 | 28 | export type Person = Static; 29 | export const Person = Type.Object({ 30 | name: Type.String(), 31 | age: Age, 32 | address: Address, 33 | contact: Contact, 34 | }); 35 | -------------------------------------------------------------------------------- /examples/programmatic-usage/index.ts: -------------------------------------------------------------------------------- 1 | // Replace this with the 'import { ts2typebox} from "ts2typebox"' when you 2 | // install the package. 3 | import { readFileSync, writeFileSync } from "node:fs"; 4 | import { ts2typebox } from "../../src/index"; 5 | 6 | (async () => { 7 | const file = readFileSync(__dirname + "/types.ts", "utf-8"); 8 | const result = await ts2typebox({ input: file }); 9 | writeFileSync(__dirname + "/generated-typebox.ts", result); 10 | })(); 11 | -------------------------------------------------------------------------------- /examples/programmatic-usage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "programmatic-usage", 3 | "packageManager": "yarn@3.5.1", 4 | "scripts": { 5 | "start": "ts-node ./index.ts" 6 | }, 7 | "dependencies": { 8 | "@sinclair/typebox-codegen": "0.8.6" 9 | }, 10 | "devDependencies": { 11 | "ts-node": "10.9.1" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/programmatic-usage/types.ts: -------------------------------------------------------------------------------- 1 | // Arbitrary example types 2 | 3 | type Age = number; 4 | 5 | export type Address = { 6 | street: string; 7 | city: string; 8 | state: string; 9 | postalCode: string; 10 | }; 11 | 12 | export type Contact = { 13 | phone: string; 14 | email: string; 15 | }; 16 | 17 | export type Person = { 18 | name: string; 19 | age: Age; 20 | address: Address; 21 | contact: Contact; 22 | }; 23 | -------------------------------------------------------------------------------- /examples/programmatic-usage/yarn.lock: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 6 6 | cacheKey: 8 7 | 8 | "@cspotcode/source-map-support@npm:^0.8.0": 9 | version: 0.8.1 10 | resolution: "@cspotcode/source-map-support@npm:0.8.1" 11 | dependencies: 12 | "@jridgewell/trace-mapping": 0.3.9 13 | checksum: 5718f267085ed8edb3e7ef210137241775e607ee18b77d95aa5bd7514f47f5019aa2d82d96b3bf342ef7aa890a346fa1044532ff7cc3009e7d24fce3ce6200fa 14 | languageName: node 15 | linkType: hard 16 | 17 | "@jridgewell/resolve-uri@npm:^3.0.3": 18 | version: 3.1.1 19 | resolution: "@jridgewell/resolve-uri@npm:3.1.1" 20 | checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 21 | languageName: node 22 | linkType: hard 23 | 24 | "@jridgewell/sourcemap-codec@npm:^1.4.10": 25 | version: 1.4.15 26 | resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" 27 | checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 28 | languageName: node 29 | linkType: hard 30 | 31 | "@jridgewell/trace-mapping@npm:0.3.9": 32 | version: 0.3.9 33 | resolution: "@jridgewell/trace-mapping@npm:0.3.9" 34 | dependencies: 35 | "@jridgewell/resolve-uri": ^3.0.3 36 | "@jridgewell/sourcemap-codec": ^1.4.10 37 | checksum: d89597752fd88d3f3480845691a05a44bd21faac18e2185b6f436c3b0fd0c5a859fbbd9aaa92050c4052caf325ad3e10e2e1d1b64327517471b7d51babc0ddef 38 | languageName: node 39 | linkType: hard 40 | 41 | "@sinclair/typebox-codegen@npm:0.8.6": 42 | version: 0.8.6 43 | resolution: "@sinclair/typebox-codegen@npm:0.8.6" 44 | dependencies: 45 | "@sinclair/typebox": ^0.31.0 46 | prettier: ^2.8.7 47 | typescript: ^5.1.6 48 | checksum: e380d191b2165e81d60eab30479a1fd4ff7ba779d3fc2375db6682a70e286eaf56778abcf5fe2e07496d337cf4ad84c9c2783079c5aabeb0d0bf6144b3ef061a 49 | languageName: node 50 | linkType: hard 51 | 52 | "@sinclair/typebox@npm:^0.31.0": 53 | version: 0.31.3 54 | resolution: "@sinclair/typebox@npm:0.31.3" 55 | checksum: 8cd8187f6e1568255616d6a721022d6dfefa92fd7d8ff3a2f0b22adfe63ded8458f4c504e8e98c25f63cd148a62b248589eef02a63e360687d3b69bca222fc3d 56 | languageName: node 57 | linkType: hard 58 | 59 | "@tsconfig/node10@npm:^1.0.7": 60 | version: 1.0.9 61 | resolution: "@tsconfig/node10@npm:1.0.9" 62 | checksum: a33ae4dc2a621c0678ac8ac4bceb8e512ae75dac65417a2ad9b022d9b5411e863c4c198b6ba9ef659e14b9fb609bbec680841a2e84c1172df7a5ffcf076539df 63 | languageName: node 64 | linkType: hard 65 | 66 | "@tsconfig/node12@npm:^1.0.7": 67 | version: 1.0.11 68 | resolution: "@tsconfig/node12@npm:1.0.11" 69 | checksum: 5ce29a41b13e7897a58b8e2df11269c5395999e588b9a467386f99d1d26f6c77d1af2719e407621412520ea30517d718d5192a32403b8dfcc163bf33e40a338a 70 | languageName: node 71 | linkType: hard 72 | 73 | "@tsconfig/node14@npm:^1.0.0": 74 | version: 1.0.3 75 | resolution: "@tsconfig/node14@npm:1.0.3" 76 | checksum: 19275fe80c4c8d0ad0abed6a96dbf00642e88b220b090418609c4376e1cef81bf16237bf170ad1b341452feddb8115d8dd2e5acdfdea1b27422071163dc9ba9d 77 | languageName: node 78 | linkType: hard 79 | 80 | "@tsconfig/node16@npm:^1.0.2": 81 | version: 1.0.4 82 | resolution: "@tsconfig/node16@npm:1.0.4" 83 | checksum: 202319785901f942a6e1e476b872d421baec20cf09f4b266a1854060efbf78cde16a4d256e8bc949d31e6cd9a90f1e8ef8fb06af96a65e98338a2b6b0de0a0ff 84 | languageName: node 85 | linkType: hard 86 | 87 | "acorn-walk@npm:^8.1.1": 88 | version: 8.2.0 89 | resolution: "acorn-walk@npm:8.2.0" 90 | checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 91 | languageName: node 92 | linkType: hard 93 | 94 | "acorn@npm:^8.4.1": 95 | version: 8.8.2 96 | resolution: "acorn@npm:8.8.2" 97 | bin: 98 | acorn: bin/acorn 99 | checksum: f790b99a1bf63ef160c967e23c46feea7787e531292bb827126334612c234ed489a0dc2c7ba33156416f0ffa8d25bf2b0fdb7f35c2ba60eb3e960572bece4001 100 | languageName: node 101 | linkType: hard 102 | 103 | "arg@npm:^4.1.0": 104 | version: 4.1.3 105 | resolution: "arg@npm:4.1.3" 106 | checksum: 544af8dd3f60546d3e4aff084d451b96961d2267d668670199692f8d054f0415d86fc5497d0e641e91546f0aa920e7c29e5250e99fc89f5552a34b5d93b77f43 107 | languageName: node 108 | linkType: hard 109 | 110 | "create-require@npm:^1.1.0": 111 | version: 1.1.1 112 | resolution: "create-require@npm:1.1.1" 113 | checksum: a9a1503d4390d8b59ad86f4607de7870b39cad43d929813599a23714831e81c520bddf61bcdd1f8e30f05fd3a2b71ae8538e946eb2786dc65c2bbc520f692eff 114 | languageName: node 115 | linkType: hard 116 | 117 | "diff@npm:^4.0.1": 118 | version: 4.0.2 119 | resolution: "diff@npm:4.0.2" 120 | checksum: f2c09b0ce4e6b301c221addd83bf3f454c0bc00caa3dd837cf6c127d6edf7223aa2bbe3b688feea110b7f262adbfc845b757c44c8a9f8c0c5b15d8fa9ce9d20d 121 | languageName: node 122 | linkType: hard 123 | 124 | "make-error@npm:^1.1.1": 125 | version: 1.3.6 126 | resolution: "make-error@npm:1.3.6" 127 | checksum: b86e5e0e25f7f777b77fabd8e2cbf15737972869d852a22b7e73c17623928fccb826d8e46b9951501d3f20e51ad74ba8c59ed584f610526a48f8ccf88aaec402 128 | languageName: node 129 | linkType: hard 130 | 131 | "prettier@npm:^2.8.7": 132 | version: 2.8.8 133 | resolution: "prettier@npm:2.8.8" 134 | bin: 135 | prettier: bin-prettier.js 136 | checksum: b49e409431bf129dd89238d64299ba80717b57ff5a6d1c1a8b1a28b590d998a34e083fa13573bc732bb8d2305becb4c9a4407f8486c81fa7d55100eb08263cf8 137 | languageName: node 138 | linkType: hard 139 | 140 | "programmatic-usage@workspace:.": 141 | version: 0.0.0-use.local 142 | resolution: "programmatic-usage@workspace:." 143 | dependencies: 144 | "@sinclair/typebox-codegen": 0.8.6 145 | ts-node: 10.9.1 146 | languageName: unknown 147 | linkType: soft 148 | 149 | "ts-node@npm:10.9.1": 150 | version: 10.9.1 151 | resolution: "ts-node@npm:10.9.1" 152 | dependencies: 153 | "@cspotcode/source-map-support": ^0.8.0 154 | "@tsconfig/node10": ^1.0.7 155 | "@tsconfig/node12": ^1.0.7 156 | "@tsconfig/node14": ^1.0.0 157 | "@tsconfig/node16": ^1.0.2 158 | acorn: ^8.4.1 159 | acorn-walk: ^8.1.1 160 | arg: ^4.1.0 161 | create-require: ^1.1.0 162 | diff: ^4.0.1 163 | make-error: ^1.1.1 164 | v8-compile-cache-lib: ^3.0.1 165 | yn: 3.1.1 166 | peerDependencies: 167 | "@swc/core": ">=1.2.50" 168 | "@swc/wasm": ">=1.2.50" 169 | "@types/node": "*" 170 | typescript: ">=2.7" 171 | peerDependenciesMeta: 172 | "@swc/core": 173 | optional: true 174 | "@swc/wasm": 175 | optional: true 176 | bin: 177 | ts-node: dist/bin.js 178 | ts-node-cwd: dist/bin-cwd.js 179 | ts-node-esm: dist/bin-esm.js 180 | ts-node-script: dist/bin-script.js 181 | ts-node-transpile-only: dist/bin-transpile.js 182 | ts-script: dist/bin-script-deprecated.js 183 | checksum: 090adff1302ab20bd3486e6b4799e90f97726ed39e02b39e566f8ab674fd5bd5f727f43615debbfc580d33c6d9d1c6b1b3ce7d8e3cca3e20530a145ffa232c35 184 | languageName: node 185 | linkType: hard 186 | 187 | "typescript@npm:^5.1.6": 188 | version: 5.2.2 189 | resolution: "typescript@npm:5.2.2" 190 | bin: 191 | tsc: bin/tsc 192 | tsserver: bin/tsserver 193 | checksum: 7912821dac4d962d315c36800fe387cdc0a6298dba7ec171b350b4a6e988b51d7b8f051317786db1094bd7431d526b648aba7da8236607febb26cf5b871d2d3c 194 | languageName: node 195 | linkType: hard 196 | 197 | "typescript@patch:typescript@^5.1.6#~builtin": 198 | version: 5.2.2 199 | resolution: "typescript@patch:typescript@npm%3A5.2.2#~builtin::version=5.2.2&hash=77c9e2" 200 | bin: 201 | tsc: bin/tsc 202 | tsserver: bin/tsserver 203 | checksum: 07106822b4305de3f22835cbba949a2b35451cad50888759b6818421290ff95d522b38ef7919e70fb381c5fe9c1c643d7dea22c8b31652a717ddbd57b7f4d554 204 | languageName: node 205 | linkType: hard 206 | 207 | "v8-compile-cache-lib@npm:^3.0.1": 208 | version: 3.0.1 209 | resolution: "v8-compile-cache-lib@npm:3.0.1" 210 | checksum: 78089ad549e21bcdbfca10c08850022b22024cdcc2da9b168bcf5a73a6ed7bf01a9cebb9eac28e03cd23a684d81e0502797e88f3ccd27a32aeab1cfc44c39da0 211 | languageName: node 212 | linkType: hard 213 | 214 | "yn@npm:3.1.1": 215 | version: 3.1.1 216 | resolution: "yn@npm:3.1.1" 217 | checksum: 2c487b0e149e746ef48cda9f8bad10fc83693cd69d7f9dcd8be4214e985de33a29c9e24f3c0d6bcf2288427040a8947406ab27f7af67ee9456e6b84854f02dd6 218 | languageName: node 219 | linkType: hard 220 | -------------------------------------------------------------------------------- /examples/skip-type-generation/.ts2typeboxrc.cjs: -------------------------------------------------------------------------------- 1 | /** 2 | * For providing your own transform functions, you can basically copy paste this 3 | * file into your root directory, name it ".ts2typeboxrc.cjs" and adapt the 4 | * functions to your needs! 5 | * 6 | * Only options which have to be passed via code (options that are functions) may 7 | * be specified here. For now, these are transformTypeName and 8 | * transformValueName. 9 | */ 10 | 11 | /** 12 | * This function will be run on every type name. For a given code 13 | * 14 | * ``` 15 | * type T = number 16 | * ``` 17 | * 18 | * the default output would be: 19 | * 20 | * ``` 21 | * type T = Static 22 | * const T = Type.Number() 23 | * ``` 24 | * This function will run on the first "T". The generated code will contain the 25 | * transformed values. 26 | * 27 | * @param input {string} 28 | */ 29 | const transformTypeName = (input) => { 30 | return input; 31 | }; 32 | 33 | /** 34 | * This function will be run on every value name. For a given code 35 | * 36 | * ``` 37 | * type T = number 38 | * ``` 39 | * 40 | * the default output would be: 41 | * ``` 42 | * type T = Static 43 | * const T = Type.Number() 44 | * ``` 45 | * 46 | * This function will run on the second and third "T". The generated code will 47 | * contain the transformed values. 48 | * 49 | * @param input {string} 50 | */ 51 | const transformValueName = (input) => { 52 | return input + "Schema"; 53 | }; 54 | 55 | /** 56 | * Options that can only be passed via code (will probably only contain 57 | * functions since they are not serializeable in JS). 58 | */ 59 | module.exports = { 60 | transformTypeName, 61 | transformValueName, 62 | }; 63 | -------------------------------------------------------------------------------- /examples/skip-type-generation/README.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | When ts2typebox is installed (simply issue npm i -g ts2typebox to do so), clone 4 | the repo, cd into this directory and: 5 | 6 | - Remove the old generated-schemas.ts file `rm generated-schemas.ts` 7 | - Take a look at the '.ts2typeboxrc.cjs' file. Here you can define 8 | transformation functions which will get applied to all values and types in the 9 | generated output. This file has to exist inside the directory from which you 10 | run ts2typebox. 11 | - Here we use the transformValue function to simply append "Schema" to each 12 | generated value. 13 | - Use ts2typebox to generate the typebox code based on the types.ts file 14 | `ts2typebox --skip-type-creation --output generated-schemas.ts` 15 | - To understand how to possibly use this, take a quick look into ./index.ts 16 | - done :] 17 | -------------------------------------------------------------------------------- /examples/skip-type-generation/generated-schemas.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ATTENTION. This code was AUTO GENERATED by ts2typebox. While I don't know 3 | * your use case, there is a high chance that direct changes to this file get 4 | * lost. Consider making changes to the underlying Typescript code you use to 5 | * generate this file instead. The default file is called "types.ts", perhaps 6 | * have a look there! :] 7 | */ 8 | 9 | import { Type } from "@sinclair/typebox"; 10 | 11 | export const PersonSchema = Type.Object({ 12 | age: Type.Number({ minimum: 18 }), 13 | name: Type.String({ description: "full name of the person" }), 14 | }); 15 | -------------------------------------------------------------------------------- /examples/skip-type-generation/index.ts: -------------------------------------------------------------------------------- 1 | // Here you can now import your types (with comments) from your types.ts file 2 | // and the JSON schemas/typebox code from ./generated-schemas 3 | 4 | // import { PersonSchema } from "./generated-schemas"; 5 | // import { Person } from "./types"; 6 | 7 | export default {}; 8 | -------------------------------------------------------------------------------- /examples/skip-type-generation/types.ts: -------------------------------------------------------------------------------- 1 | export type Person = { 2 | /** 3 | * @minimum 18 4 | */ 5 | age: number; 6 | /** 7 | * @description full name of the person 8 | */ 9 | name: string; 10 | }; 11 | -------------------------------------------------------------------------------- /examples/transform-value-transform-type/.ts2typeboxrc.cjs: -------------------------------------------------------------------------------- 1 | /** 2 | * For providing your own transform functions, you can basically copy paste this 3 | * file into your root directory, name it ".ts2typeboxrc.cjs" and adapt the 4 | * functions to your needs! 5 | * 6 | * Only options which have to be passed via code (options that are functions) may 7 | * be specified here. For now, these are transformTypeName and 8 | * transformValueName. 9 | */ 10 | 11 | /** 12 | * This function will be run on every type name. For a given code 13 | * 14 | * ``` 15 | * type T = number 16 | * ``` 17 | * 18 | * the default output would be: 19 | * 20 | * ``` 21 | * type T = Static 22 | * const T = Type.Number() 23 | * ``` 24 | * This function will run on the first "T". The generated code will contain the 25 | * transformed values. 26 | * 27 | * @param input {string} 28 | */ 29 | const transformTypeName = (input) => { 30 | return input + "Type"; 31 | }; 32 | 33 | /** 34 | * This function will be run on every value name. For a given code 35 | * 36 | * ``` 37 | * type T = number 38 | * ``` 39 | * 40 | * the default output would be: 41 | * ``` 42 | * type T = Static 43 | * const T = Type.Number() 44 | * ``` 45 | * 46 | * This function will run on the second and third "T". The generated code will 47 | * contain the transformed values. 48 | * 49 | * @param input {string} 50 | */ 51 | const transformValueName = (input) => { 52 | // arbitrary example 53 | return input + "Schema"; 54 | }; 55 | 56 | /** 57 | * Options that can only be passed via code (will probably only contain 58 | * functions since they are not serializeable in JS). 59 | */ 60 | module.exports = { 61 | transformTypeName, 62 | transformValueName, 63 | }; 64 | -------------------------------------------------------------------------------- /examples/transform-value-transform-type/README.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | When ts2typebox is installed (simply issue npm i -g ts2typebox to do so), clone 4 | the repo, cd into this directory and: 5 | 6 | - Remove the old generated-types.ts file `rm generated-types.ts` 7 | - Take a look at the '.ts2typeboxrc.cjs' file. Here you can define 8 | transformation functions which will get applied to all values and types in the 9 | generated output. This file has to exist inside the directory from which you 10 | run ts2typebox. 11 | - Use ts2typebox to generate the typebox types based on the types.ts file 12 | `ts2typebox` 13 | - done :] 14 | -------------------------------------------------------------------------------- /examples/transform-value-transform-type/generated-types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ATTENTION. This code was AUTO GENERATED by ts2typebox. While I don't know 3 | * your use case, there is a high chance that direct changes to this file get 4 | * lost. Consider making changes to the underlying Typescript code you use to 5 | * generate this file instead. The default file is called "types.ts", perhaps 6 | * have a look there! :] 7 | */ 8 | 9 | import { Type, Static } from "@sinclair/typebox"; 10 | 11 | export type PersonType = Static; 12 | export const PersonSchema = Type.Object({ 13 | age: Type.Number(), 14 | name: Type.String(), 15 | }); 16 | -------------------------------------------------------------------------------- /examples/transform-value-transform-type/types.ts: -------------------------------------------------------------------------------- 1 | export type Person = { 2 | age: number; 3 | name: string; 4 | }; 5 | -------------------------------------------------------------------------------- /git-hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Runs prettier on all files before comitting them. 4 | # src: https://prettier.io/docs/en/precommit.html 5 | 6 | FILES=$(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g') 7 | [ -z "$FILES" ] && exit 0 8 | 9 | echo "Running prettier to format files before commiting..." 10 | 11 | # Prettify all selected files 12 | echo "$FILES" | xargs ./node_modules/.bin/prettier --ignore-unknown --write 13 | 14 | echo "Done!" 15 | 16 | # Add back the modified/prettified files to staging 17 | echo "$FILES" | xargs git add 18 | 19 | exit 0 20 | 21 | 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts2typebox", 3 | "version": "1.6.2", 4 | "description": "Creates TypeBox code from Typescript code", 5 | "main": "dist/src/index.js", 6 | "source": "dist/src/index.js", 7 | "typings": "dist/src/index.d.ts", 8 | "bin": { 9 | "ts-to-typebox": "dist/src/cli/index.js", 10 | "ts2typebox": "dist/src/cli/index.js" 11 | }, 12 | "scripts": { 13 | "build": "tsc", 14 | "watch-ts": "tsc -w", 15 | "test": "tsc && node --test --test-reporter spec", 16 | "start": "node dist/src/index.js" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/xddq/ts2typebox.git" 21 | }, 22 | "keywords": [ 23 | "JSON schema", 24 | "ts2typebox", 25 | "ts-to-typebox", 26 | "typescript", 27 | "typebox", 28 | "ts", 29 | "validation", 30 | "parsing", 31 | "IO", 32 | "cli" 33 | ], 34 | "author": "Pierre Dahmani", 35 | "license": "MIT", 36 | "bugs": { 37 | "url": "https://github.com/xddq/ts2typebox/issues" 38 | }, 39 | "homepage": "https://github.com/xddq/ts2typebox#readme", 40 | "dependencies": { 41 | "@sinclair/typebox-codegen": "^0.10.5", 42 | "cosmiconfig": "^8.1.3", 43 | "minimist": "^1.2.8", 44 | "prettier": "^2.8.7", 45 | "typescript": "^5.7.3" 46 | }, 47 | "devDependencies": { 48 | "@sinclair/typebox": "0.34.25", 49 | "@types/minimist": "1.2.5", 50 | "@types/node": "18.16.0", 51 | "@types/prettier": "2.7.2", 52 | "@types/shelljs": "0.8.15", 53 | "shelljs": "0.8.5", 54 | "tsconfig-paths": "4.2.0" 55 | }, 56 | "peerDependencies": { 57 | "@sinclair/typebox": "^0.34.25" 58 | }, 59 | "packageManager": "yarn@3.5.1" 60 | } 61 | -------------------------------------------------------------------------------- /src/cli/cli.ts: -------------------------------------------------------------------------------- 1 | import { readFileSync, createWriteStream } from "node:fs"; 2 | import { Readable } from "node:stream"; 3 | import minimist from "minimist"; 4 | 5 | import packageJson from "../../package.json"; 6 | import { ts2typebox } from "../programmatic-usage"; 7 | 8 | const readCliOptions = (): minimist.ParsedArgs => { 9 | return minimist(process.argv.slice(2), { 10 | alias: { 11 | input: "i", 12 | output: "o", 13 | help: "h", 14 | }, 15 | default: { 16 | input: "types.ts", 17 | output: "generated-types.ts", 18 | }, 19 | }); 20 | }; 21 | 22 | /** 23 | * This functions is executed when running schema2typebox via the cli. 24 | * 25 | * @param getCliOptionsFn This function was added to be able to overwrite the 26 | * default behaviour of reading in the cli options in order to make them easily 27 | * testable by bassing a custom readCliOptions function. 28 | */ 29 | export const runCli = async ( 30 | getCliOptionsFn: typeof readCliOptions = readCliOptions 31 | ) => { 32 | const args = getCliOptionsFn(); 33 | 34 | // TODO: narrow condition. 35 | if (args.help) { 36 | return process.stdout.write(getHelpText.run()); 37 | } 38 | 39 | const inputPath = process.cwd() + `/${args.input ?? "schema.json"}`; 40 | const inputFileAsString = readFileSync(inputPath, "utf-8"); 41 | 42 | const typeboxCode = await ts2typebox({ 43 | input: inputFileAsString, 44 | disableAutogenComment: args["disable-autogen-comment"], 45 | skipTypeCreation: args["skip-type-creation"], 46 | }); 47 | 48 | const generatedCodeStream = Readable.from(typeboxCode.split(/(\r\n|\r|\n)/)); 49 | if (args["output-stdout"]) { 50 | return generatedCodeStream.pipe(process.stdout); 51 | } 52 | 53 | const outputPath = 54 | process.cwd() + `/${args.output ?? "generated-typebox.ts"}`; 55 | return generatedCodeStream.pipe(createWriteStream(outputPath)); 56 | }; 57 | 58 | /** 59 | * Declaring this as function in order to make it better testable. 60 | * Using an object to be able to mock it and track its usage. 61 | */ 62 | export const getHelpText = { 63 | run: () => { 64 | return ` 65 | ts2typebox generates TypeBox code from Typescript code. 66 | Version: ${packageJson.version} 67 | 68 | Usage: 69 | 70 | ts2typebox [ARGUMENTS] 71 | 72 | Arguments: 73 | 74 | -h, --help 75 | Displays this menu. 76 | 77 | -i, --input 78 | Specifies the relative path to the file containing the typescript types 79 | that will be used to generated typebox types. Defaults to "types.ts". 80 | 81 | -o, --output 82 | Specifies the relative path to generated file that will contain the 83 | typebox types. Defaults to "generated-types.ts". 84 | 85 | --output-stdout 86 | Does not generate an output file and prints the generated code to stdout 87 | instead. Has precedence over -o/--output. 88 | 89 | --disable-autogen-comment 90 | When used, it does not add the comment at the beginning of the generated 91 | file which is stating that the code was automatically generated. 92 | 93 | --skip-type-creation 94 | When used, strips all types from the generated code. This can be helpful 95 | if you want to use your Typescript types inside your input file (which 96 | probably contains comments) as source of truth and still use the generated 97 | TypeBox code (schema validators) to validate data based on these types. 98 | When using this option you probably want to also provide a custom 99 | transformValue function since two same symbols can't be imported from two 100 | different files. For an example take a look inside the repo under 101 | ./examples/skip-type-creation. 102 | 103 | Additional: 104 | 105 | Transformations 106 | 107 | You can adapt the names of the generated types (as well as the names of the 108 | generated values) using custom transformation functions which take a string 109 | as an input and return a string as their output. These will run on each of 110 | the generated types and values, respectively. Please take a look inside the 111 | repo under ./examples/transform-value-transform-type for an example of this. 112 | 113 | Formatting 114 | 115 | The generated output is formatted based on the prettier config inside your 116 | repo (or the default one, if you don't have one). 117 | `; 118 | }, 119 | }; 120 | -------------------------------------------------------------------------------- /src/cli/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { runCli } from "./cli"; 4 | 5 | (async () => { 6 | await runCli(); 7 | })(); 8 | -------------------------------------------------------------------------------- /src/codeOptions.cjs: -------------------------------------------------------------------------------- 1 | /** 2 | * For providing your own transform functions, you can basically copy paste this 3 | * file into your root directory, name it ".ts2typeboxrc.cjs" and adapt the 4 | * functions to your needs! 5 | * 6 | * Only options which have to be passed via code (options that are functions) may 7 | * be specified here. For now, these are transformTypeName and 8 | * transformValueName. 9 | */ 10 | 11 | /** 12 | * This function will be run on every type name. For a given code 13 | * 14 | * ``` 15 | * type T = number 16 | * ``` 17 | * 18 | * the default output would be: 19 | * 20 | * ``` 21 | * type T = Static 22 | * const T = Type.Number() 23 | * ``` 24 | * This function will run on the first "T". The generated code will contain the 25 | * transformed values. 26 | * 27 | * @param input {string} 28 | */ 29 | const transformTypeName = (input) => { 30 | return input; 31 | }; 32 | 33 | /** 34 | * This function will be run on every value name. For a given code 35 | * 36 | * ``` 37 | * type T = number 38 | * ``` 39 | * 40 | * the default output would be: 41 | * ``` 42 | * type T = Static 43 | * const T = Type.Number() 44 | * ``` 45 | * 46 | * This function will run on the second and third "T". The generated code will 47 | * contain the transformed values. 48 | * 49 | * @param input {string} 50 | */ 51 | const transformValueName = (input) => { 52 | return input; 53 | }; 54 | 55 | /** 56 | * Options that can only be passed via code (will probably only contain 57 | * functions since they are not serializeable in JS). 58 | */ 59 | module.exports = { 60 | transformTypeName, 61 | transformValueName, 62 | }; 63 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { ts2typebox, Ts2TypeboxOptions } from "./programmatic-usage"; 2 | -------------------------------------------------------------------------------- /src/jsdoc.ts: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | 3 | @typebox/codegen 4 | 5 | The MIT License (MIT) 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | 25 | ---------------------------------------------------------------------------*/ 26 | 27 | /** JSDoc Property Parser */ 28 | export namespace JsDoc { 29 | function DecodeWithNonQuotedProperties(content: string): any { 30 | const parseFunction = new Function(`return (${content});`); 31 | return parseFunction(); 32 | } 33 | function Decode(content: string) { 34 | try { 35 | return DecodeWithNonQuotedProperties(content); 36 | } catch { 37 | return content; 38 | } 39 | } 40 | function* ParseValue( 41 | key: string, 42 | content: string 43 | ): IterableIterator<[string, any]> { 44 | for (let i = 0; i < content.length; i++) { 45 | if (content[i] === "\n" || content[i] === "-") { 46 | const value = content.slice(0, i).trim(); 47 | const rest = content.slice(i); 48 | yield [key, Decode(value)]; 49 | return yield* ParseContent(rest); 50 | } 51 | } 52 | } 53 | function* ParseKey(content: string): IterableIterator<[string, any]> { 54 | for (let i = 1; i < content.length; i++) { 55 | if (content[i] === " ") { 56 | const key = content.slice(1, i); 57 | const rest = content.slice(i).trimStart(); 58 | return yield* ParseValue(key, rest); 59 | } 60 | } 61 | } 62 | function* ParseContent(content: string): IterableIterator<[string, any]> { 63 | for (let i = 0; i < content.length; i++) { 64 | if (content[i] === "@") { 65 | return yield* ParseKey(content.slice(i)); 66 | } 67 | } 68 | } 69 | export function Parse(content: string): Record { 70 | const properties = [...ParseContent(content)]; 71 | return properties.reduce( 72 | (acc, [key, value]) => ({ ...acc, [key]: value }), 73 | {} 74 | ); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/programmatic-usage.ts: -------------------------------------------------------------------------------- 1 | import * as prettier from "prettier"; 2 | import { cosmiconfig } from "cosmiconfig"; 3 | import packageJson from "../package.json"; 4 | import { default as defaultCodeOptions } from "./codeOptions.cjs"; 5 | import * as codegen from "@sinclair/typebox-codegen"; 6 | 7 | export type Ts2TypeboxOptions = { 8 | /** 9 | * The given Typescript code as utf-8 encoded string. 10 | */ 11 | input: string; 12 | /** 13 | * Removes the comment at the beginning of the generated typebox code which 14 | * mentions that the code was auto generated and should not be changed since 15 | * there is a high risk that changes might get lost. 16 | */ 17 | disableAutogenComment?: true; 18 | /** 19 | * Skips the creation of types in the generated file. Only creates the typebox 20 | * validators containing the JSON schemas based on your typescript types. See 21 | * the output of ts2typebox -h for more info. 22 | */ 23 | skipTypeCreation?: boolean; 24 | }; 25 | 26 | /** 27 | * Just an alias for string. This gets returned by the ts2typebox function and 28 | * contains the generated types as string. 29 | */ 30 | type GeneratedTypes = string; 31 | 32 | /** 33 | * Use this function for programmatic usage of ts2typebox. The options are typed 34 | * and commented. 35 | * 36 | * @returns The generated types as string if (outputStdout was set) or undefined 37 | * otherwise. 38 | * 39 | * @throws Error 40 | **/ 41 | export const ts2typebox = async ({ 42 | input, 43 | disableAutogenComment, 44 | skipTypeCreation, 45 | }: Ts2TypeboxOptions): Promise => { 46 | const generatedTs = codegen.TypeScriptToTypeBox.Generate(input); 47 | 48 | // post-processing 49 | // 1. transformations 50 | const ts2typeboxCodeOptions = await cosmiconfig("ts2typebox").search(); 51 | // TODO: perhaps validate with typebox that these are indeed valid codeOption 52 | // configs (ts2typebox options) 53 | const usedCodeOptions = 54 | ts2typeboxCodeOptions === null 55 | ? defaultCodeOptions 56 | : (ts2typeboxCodeOptions.config as typeof defaultCodeOptions); 57 | const transformedTs = transformValuesAndTypes(generatedTs, usedCodeOptions); 58 | 59 | // 2. formatting 60 | const explorer = cosmiconfig("prettier"); 61 | const searchResult = await explorer.search(); 62 | // TODO: perhaps validate with typebox that these are indeed valid prettier configs 63 | const prettierConfig = 64 | searchResult === null ? {} : (searchResult.config as prettier.Options); 65 | const resultFormatted = prettier.format(transformedTs, { 66 | parser: "typescript", 67 | ...prettierConfig, 68 | }); 69 | 70 | const resultFiltered = 71 | skipTypeCreation === undefined 72 | ? resultFormatted 73 | : filterTypes(resultFormatted); 74 | const result = 75 | disableAutogenComment === undefined 76 | ? addCommentThatCodeIsGenerated.run(resultFiltered) 77 | : resultFiltered; 78 | 79 | return result; 80 | }; 81 | 82 | /** 83 | * Post-processing after successful code generation. 84 | * Transforms all values and types based on given functions. 85 | */ 86 | const transformValuesAndTypes = ( 87 | generatedTypes: string, 88 | transformFns: typeof defaultCodeOptions 89 | ) => { 90 | const tsWithTransformedTypes = generatedTypes.replace( 91 | /(type)\s(\w+)/gm, 92 | (_match, group1, group2) => { 93 | return group1 + " " + transformFns.transformTypeName(group2); 94 | } 95 | ); 96 | const result = tsWithTransformedTypes.replace( 97 | /(typeof|const)\s(\w+)/gm, 98 | (_match, group1, group2) => { 99 | return group1 + " " + transformFns.transformValueName(group2); 100 | } 101 | ); 102 | return result; 103 | }; 104 | 105 | /** 106 | * Post-processing after successful code generation. 107 | * Removes each line starting with "export type" or "type". 108 | */ 109 | const filterTypes = (input: GeneratedTypes) => { 110 | const result = input.replace(/^(export\s+)?type.*(\r?\n|$)/gm, ""); 111 | // Now we still have to adapt the import line since we would otherwise get 112 | // "unused imports". For now, we simply remove the first line and append the 113 | // correct one. 114 | return ( 115 | 'import { Type } from "@sinclair/typebox";\n' + 116 | result.split("\n").slice(1).join("\n") 117 | ); 118 | }; 119 | 120 | /** 121 | * Declaring this as function in order to make it better testable. 122 | * Using an object to be able to mock it and track its usage. 123 | */ 124 | export const getHelpText = { 125 | run: () => { 126 | return ` 127 | ts2typebox is a cli tool to generate typebox JSON schemas based on given 128 | typescript types. The generated output is formatted based on the prettier 129 | config inside your repo (or the default one, if you don't have one). 130 | Version: ${packageJson.version} 131 | 132 | Usage: 133 | 134 | ts2typebox [ARGUMENTS] 135 | 136 | Arguments: 137 | 138 | -h, --help 139 | Displays this menu. 140 | 141 | -i, --input 142 | Specifies the relative path to the file containing the typescript types 143 | that will be used to generated typebox types. Defaults to "types.ts". 144 | 145 | -o, --output 146 | Specifies the relative path to generated file that will contain the 147 | typebox types. Defaults to "generated-types.ts". 148 | 149 | --output-stdout 150 | Does not generate an output file and prints the generated code to stdout 151 | instead. Has precedence over -o/--output. 152 | 153 | --disable-autogen-comment 154 | When used, it does not add the comment at the beginning of the generated 155 | file which is stating that the code was automatically generated. 156 | 157 | --skip-type-creation 158 | When used, strips all types from the generated code. This can be helpful 159 | if you want to use your Typescript types inside your input file (which 160 | probably contains comments) as source of truth and still use the generated 161 | JSON schema validators (typebox values) to validate data based on these 162 | types. When using this option you probably want to also provide a custom 163 | transformValue function since two same symbols can't be imported from two 164 | different files. For an example take a look inside the repo under 165 | ./examples/skip-type-creation. 166 | 167 | Additional: 168 | 169 | You can adapt the names of the generated types (as well as the names of the 170 | generated values) using custom transformation functions which take a string 171 | as an input and return a string as their output. These will run on each of 172 | the generated types and values, respectively. Please take a look inside the 173 | repo under ./examples/transform-value-transform-type for an example of this. 174 | `; 175 | }, 176 | }; 177 | 178 | /** 179 | * Declaring this as an object with a function in order to make it better 180 | * testable with mocks. Allows for tracking the call count. 181 | */ 182 | export const addCommentThatCodeIsGenerated = { 183 | run: (code: string) => { 184 | return `/** 185 | * ATTENTION. This code was AUTO GENERATED by ts2typebox. While I don't know 186 | * your use case, there is a high chance that direct changes to this file get 187 | * lost. Consider making changes to the underlying Typescript code you use to 188 | * generate this file instead. The default file is called "types.ts", perhaps 189 | * have a look there! :] 190 | */ 191 | 192 | ${code}`; 193 | }, 194 | }; 195 | -------------------------------------------------------------------------------- /test/index.ts: -------------------------------------------------------------------------------- 1 | import { describe, test, mock, beforeEach } from "node:test"; 2 | import assert from "node:assert/strict"; 3 | import * as prettier from "prettier"; 4 | import fs from "node:fs"; 5 | import path from "node:path"; 6 | import shell from "shelljs"; 7 | import { ts2typebox } from "../src/programmatic-usage"; 8 | 9 | const SHELLJS_RETURN_CODE_OK = 0; 10 | const buildOsIndependentPath = (foldersOrFiles: string[]) => { 11 | return foldersOrFiles.join(path.sep); 12 | }; 13 | 14 | const formatWithPrettier = (input: string): string => { 15 | return prettier.format(input, { parser: "typescript" }); 16 | }; 17 | 18 | /** 19 | * Formats given input with prettier and returns the result. This is used for 20 | * testing to be able to compare generated types with expected types without 21 | * having to take care of formatting. 22 | * @throws Error 23 | **/ 24 | export const expectEqualIgnoreFormatting = ( 25 | input1: string, 26 | input2: string 27 | ): void => { 28 | assert.equal(formatWithPrettier(input1), formatWithPrettier(input2)); 29 | }; 30 | 31 | describe("programmatic usage API", () => { 32 | beforeEach(() => { 33 | // Reset the globally tracked mocks. 34 | mock.reset(); 35 | }); 36 | test("generates TypeBox code", async () => { 37 | // prepares and writes a test types.ts file. 38 | const dummyTypes = ` 39 | type T = { 40 | a: number; 41 | b: string; 42 | }; 43 | `; 44 | const expectedOutput = ` 45 | /** 46 | * ATTENTION. This code was AUTO GENERATED by ts2typebox. While I don't know 47 | * your use case, there is a high chance that direct changes to this file get 48 | * lost. Consider making changes to the underlying Typescript code you use to 49 | * generate this file instead. The default file is called "types.ts", perhaps 50 | * have a look there! :] 51 | */ 52 | 53 | import { Type, Static } from '@sinclair/typebox'; 54 | 55 | type T = Static; 56 | const T = Type.Object({ 57 | a: Type.Number(), 58 | b: Type.String(), 59 | }); 60 | `; 61 | const generatedTypeBox = await ts2typebox({ 62 | input: dummyTypes, 63 | }); 64 | expectEqualIgnoreFormatting(generatedTypeBox, expectedOutput); 65 | }); 66 | test("disableAutogenComment option", async () => { 67 | // prepares and writes a test types.ts file. 68 | const dummyTypes = ` 69 | type T = { 70 | a: number; 71 | b: string; 72 | }; 73 | `; 74 | const expectedOutput = ` 75 | import { Type, Static } from '@sinclair/typebox'; 76 | 77 | type T = Static; 78 | const T = Type.Object({ 79 | a: Type.Number(), 80 | b: Type.String(), 81 | }); 82 | `; 83 | const generatedTypeBox = await ts2typebox({ 84 | input: dummyTypes, 85 | disableAutogenComment: true, 86 | }); 87 | expectEqualIgnoreFormatting(generatedTypeBox, expectedOutput); 88 | }); 89 | test("skipTypeCreation option", async () => { 90 | const dummyTypes = ` 91 | type T = { 92 | a: number; 93 | b: string; 94 | }; 95 | `; 96 | const expectedOutput = ` 97 | /** 98 | * ATTENTION. This code was AUTO GENERATED by ts2typebox. While I don't know 99 | * your use case, there is a high chance that direct changes to this file get 100 | * lost. Consider making changes to the underlying Typescript code you use to 101 | * generate this file instead. The default file is called "types.ts", perhaps 102 | * have a look there! :] 103 | */ 104 | 105 | import { Type } from '@sinclair/typebox'; 106 | 107 | const T = Type.Object({ 108 | a: Type.Number(), 109 | b: Type.String(), 110 | }); 111 | `; 112 | const generatedTypeBox = await ts2typebox({ 113 | input: dummyTypes, 114 | skipTypeCreation: true, 115 | }); 116 | expectEqualIgnoreFormatting(generatedTypeBox, expectedOutput); 117 | }); 118 | test("with prettier config", async () => { 119 | // TODO: .prettierrc.yml should not exist before 120 | 121 | // prepares and writes a test prettierrc.yml file. 122 | const dummyPretterConfig = "singleQuote: true"; 123 | const configFileAbsolute = buildOsIndependentPath([ 124 | __dirname, 125 | "..", 126 | "..", 127 | ".prettierrc.yml", 128 | ]); 129 | // check that file does not exist yet 130 | await assert.rejects(async () => { 131 | return await fs.promises.access(configFileAbsolute); 132 | }); 133 | 134 | fs.writeFileSync(configFileAbsolute, dummyPretterConfig); 135 | 136 | const dummyTypes = ` 137 | type T = { 138 | a: number; 139 | b: string; 140 | }; 141 | `; 142 | const generatedTypeBox = await ts2typebox({ 143 | input: dummyTypes, 144 | }); 145 | // We expect that all " will be converted to ' 146 | // Therefore something like (default) 147 | // import { Type, Static } from "@sinclair/typebox"; 148 | // will become (with our custom config) 149 | // import { Type, Static } from '@sinclair/typebox'; 150 | assert.equal(generatedTypeBox.includes("'@sinclair/typebox'"), true); 151 | 152 | // cleanup generated files 153 | const { code: returnCode } = shell.rm("-f", [configFileAbsolute]); 154 | assert.equal(returnCode, SHELLJS_RETURN_CODE_OK); 155 | }); 156 | 157 | test("with .ts2typeboxrc.cjs config", async () => { 158 | const dummyTs2TypeboxRc = ` 159 | const transformTypeName = (input) => { 160 | return "TestType" + input; 161 | }; 162 | const transformValueName = (input) => { 163 | return "testValue" + input; 164 | }; 165 | 166 | module.exports = { 167 | transformTypeName, 168 | transformValueName, 169 | }; 170 | `; 171 | const configFileAbsolute = buildOsIndependentPath([ 172 | __dirname, 173 | "..", 174 | "..", 175 | ".ts2typeboxrc.cjs", 176 | ]); 177 | // check that file does not exist yet 178 | await assert.rejects(async () => { 179 | return await fs.promises.access(configFileAbsolute); 180 | }); 181 | fs.writeFileSync(configFileAbsolute, dummyTs2TypeboxRc); 182 | 183 | // prepares and writes a test types.ts file. 184 | const dummyTypes = ` 185 | type T = number; 186 | export type U = number; 187 | `; 188 | 189 | const expectedOutput = ` 190 | /** 191 | * ATTENTION. This code was AUTO GENERATED by ts2typebox. While I don't know 192 | * your use case, there is a high chance that direct changes to this file get 193 | * lost. Consider making changes to the underlying Typescript code you use to 194 | * generate this file instead. The default file is called "types.ts", perhaps 195 | * have a look there! :] 196 | */ 197 | 198 | import { Type, Static } from "@sinclair/typebox"; 199 | 200 | type TestTypeT = Static; 201 | const testValueT = Type.Number(); 202 | 203 | export type TestTypeU = Static; 204 | export const testValueU = Type.Number(); 205 | `; 206 | const generatedTypeBox = await ts2typebox({ 207 | input: dummyTypes, 208 | }); 209 | expectEqualIgnoreFormatting(generatedTypeBox, expectedOutput); 210 | 211 | // cleanup generated files 212 | const { code: returnCode } = shell.rm("-f", [configFileAbsolute]); 213 | assert.equal(returnCode, SHELLJS_RETURN_CODE_OK); 214 | }); 215 | }); 216 | // TODO: create cli usage tests with the refactored/fixed new cli file 217 | // describe("cli usage", () => {}); 218 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "CommonJS", 4 | "moduleResolution": "node", 5 | "target": "ES2021", 6 | "outDir": "./dist" /* Specify an output folder for all emitted files. */, 7 | "noEmit": false, 8 | "baseUrl": ".", 9 | "esModuleInterop": true, 10 | "allowSyntheticDefaultImports": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "strict": true, 13 | "sourceMap": true, 14 | "skipLibCheck": true, 15 | "resolveJsonModule": true, 16 | "allowJs": true, 17 | "checkJs": true, 18 | "paths": { 19 | "@/*": ["./src/*"] 20 | }, 21 | "declaration": true 22 | }, 23 | "include": ["src", "test"], 24 | "exclude": ["examples", "dist", "coverage"] 25 | } 26 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 6 6 | cacheKey: 8 7 | 8 | "@babel/code-frame@npm:^7.0.0": 9 | version: 7.21.4 10 | resolution: "@babel/code-frame@npm:7.21.4" 11 | dependencies: 12 | "@babel/highlight": ^7.18.6 13 | checksum: e5390e6ec1ac58dcef01d4f18eaf1fd2f1325528661ff6d4a5de8979588b9f5a8e852a54a91b923846f7a5c681b217f0a45c2524eb9560553160cd963b7d592c 14 | languageName: node 15 | linkType: hard 16 | 17 | "@babel/helper-validator-identifier@npm:^7.18.6": 18 | version: 7.19.1 19 | resolution: "@babel/helper-validator-identifier@npm:7.19.1" 20 | checksum: 0eca5e86a729162af569b46c6c41a63e18b43dbe09fda1d2a3c8924f7d617116af39cac5e4cd5d431bb760b4dca3c0970e0c444789b1db42bcf1fa41fbad0a3a 21 | languageName: node 22 | linkType: hard 23 | 24 | "@babel/highlight@npm:^7.18.6": 25 | version: 7.18.6 26 | resolution: "@babel/highlight@npm:7.18.6" 27 | dependencies: 28 | "@babel/helper-validator-identifier": ^7.18.6 29 | chalk: ^2.0.0 30 | js-tokens: ^4.0.0 31 | checksum: 92d8ee61549de5ff5120e945e774728e5ccd57fd3b2ed6eace020ec744823d4a98e242be1453d21764a30a14769ecd62170fba28539b211799bbaf232bbb2789 32 | languageName: node 33 | linkType: hard 34 | 35 | "@sinclair/typebox-codegen@npm:^0.10.5": 36 | version: 0.10.5 37 | resolution: "@sinclair/typebox-codegen@npm:0.10.5" 38 | dependencies: 39 | "@sinclair/typebox": ^0.33.1 40 | prettier: ^2.8.7 41 | typescript: ^5.4.5 42 | checksum: e5917e1ac80b5761b848cb8d6f890bffcdf3eb5f9af92d36e3d37ce9ce0e1f051f1f34214b117111180d247ffb8cb2e5fa53b947a9ae0a8ea6fac965efc6a5db 43 | languageName: node 44 | linkType: hard 45 | 46 | "@sinclair/typebox@npm:0.34.25": 47 | version: 0.34.25 48 | resolution: "@sinclair/typebox@npm:0.34.25" 49 | checksum: 72a1d04a70e28fffc54d4241baee4cd0ba3338de0ed3c40a1eca5b3be29be4be8ea8119cef4e64acacf1a679f6504ea747616eec042514455fadc709762b85c7 50 | languageName: node 51 | linkType: hard 52 | 53 | "@sinclair/typebox@npm:^0.33.1": 54 | version: 0.33.22 55 | resolution: "@sinclair/typebox@npm:0.33.22" 56 | checksum: d87c623b2b853a2684edda8d8a9f842867a9e22d0120142b8c82d0c7fc97ac0e5d95027c2f14497ccce0bd101b706645d04acd602b04c0c706002f57f51302e3 57 | languageName: node 58 | linkType: hard 59 | 60 | "@types/glob@npm:~7.2.0": 61 | version: 7.2.0 62 | resolution: "@types/glob@npm:7.2.0" 63 | dependencies: 64 | "@types/minimatch": "*" 65 | "@types/node": "*" 66 | checksum: 6ae717fedfdfdad25f3d5a568323926c64f52ef35897bcac8aca8e19bc50c0bd84630bbd063e5d52078b2137d8e7d3c26eabebd1a2f03ff350fff8a91e79fc19 67 | languageName: node 68 | linkType: hard 69 | 70 | "@types/minimatch@npm:*": 71 | version: 5.1.2 72 | resolution: "@types/minimatch@npm:5.1.2" 73 | checksum: 0391a282860c7cb6fe262c12b99564732401bdaa5e395bee9ca323c312c1a0f45efbf34dce974682036e857db59a5c9b1da522f3d6055aeead7097264c8705a8 74 | languageName: node 75 | linkType: hard 76 | 77 | "@types/minimist@npm:1.2.5": 78 | version: 1.2.5 79 | resolution: "@types/minimist@npm:1.2.5" 80 | checksum: 477047b606005058ab0263c4f58097136268007f320003c348794f74adedc3166ffc47c80ec3e94687787f2ab7f4e72c468223946e79892cf0fd9e25e9970a90 81 | languageName: node 82 | linkType: hard 83 | 84 | "@types/node@npm:*": 85 | version: 20.1.4 86 | resolution: "@types/node@npm:20.1.4" 87 | checksum: bffa6a6e92831cc805b13658c55be8e04abe3202d5e57ddd7fee4cfbe269656a1f475909a9f9514e1aff50310d0d90c516ac2c649cb6f1c77d4b1079c2fd1e88 88 | languageName: node 89 | linkType: hard 90 | 91 | "@types/node@npm:18.16.0": 92 | version: 18.16.0 93 | resolution: "@types/node@npm:18.16.0" 94 | checksum: 63e0042136663b9e85ce503a4c65406cc6621fdba63ea66c74b4b1364a9aa9bdb57cadcb76696abab177f38a819b0fa6ace9e7f1647dcb990aedb1b4bd01012f 95 | languageName: node 96 | linkType: hard 97 | 98 | "@types/prettier@npm:2.7.2": 99 | version: 2.7.2 100 | resolution: "@types/prettier@npm:2.7.2" 101 | checksum: b47d76a5252265f8d25dd2fe2a5a61dc43ba0e6a96ffdd00c594cb4fd74c1982c2e346497e3472805d97915407a09423804cc2110a0b8e1b22cffcab246479b7 102 | languageName: node 103 | linkType: hard 104 | 105 | "@types/shelljs@npm:0.8.15": 106 | version: 0.8.15 107 | resolution: "@types/shelljs@npm:0.8.15" 108 | dependencies: 109 | "@types/glob": ~7.2.0 110 | "@types/node": "*" 111 | checksum: 94939421c6c83d3075e1c56bf940eb3c34567c6b2ac0b553ec81de7f4c7e7cdfc729117d821c22418d64c45fcd4f96a6ec7ae21ed0d7a80e3e9a008672dde35f 112 | languageName: node 113 | linkType: hard 114 | 115 | "ansi-styles@npm:^3.2.1": 116 | version: 3.2.1 117 | resolution: "ansi-styles@npm:3.2.1" 118 | dependencies: 119 | color-convert: ^1.9.0 120 | checksum: d85ade01c10e5dd77b6c89f34ed7531da5830d2cb5882c645f330079975b716438cd7ebb81d0d6e6b4f9c577f19ae41ab55f07f19786b02f9dfd9e0377395665 121 | languageName: node 122 | linkType: hard 123 | 124 | "argparse@npm:^2.0.1": 125 | version: 2.0.1 126 | resolution: "argparse@npm:2.0.1" 127 | checksum: 83644b56493e89a254bae05702abf3a1101b4fa4d0ca31df1c9985275a5a5bd47b3c27b7fa0b71098d41114d8ca000e6ed90cad764b306f8a503665e4d517ced 128 | languageName: node 129 | linkType: hard 130 | 131 | "balanced-match@npm:^1.0.0": 132 | version: 1.0.2 133 | resolution: "balanced-match@npm:1.0.2" 134 | checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 135 | languageName: node 136 | linkType: hard 137 | 138 | "brace-expansion@npm:^1.1.7": 139 | version: 1.1.11 140 | resolution: "brace-expansion@npm:1.1.11" 141 | dependencies: 142 | balanced-match: ^1.0.0 143 | concat-map: 0.0.1 144 | checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 145 | languageName: node 146 | linkType: hard 147 | 148 | "callsites@npm:^3.0.0": 149 | version: 3.1.0 150 | resolution: "callsites@npm:3.1.0" 151 | checksum: 072d17b6abb459c2ba96598918b55868af677154bec7e73d222ef95a8fdb9bbf7dae96a8421085cdad8cd190d86653b5b6dc55a4484f2e5b2e27d5e0c3fc15b3 152 | languageName: node 153 | linkType: hard 154 | 155 | "chalk@npm:^2.0.0": 156 | version: 2.4.2 157 | resolution: "chalk@npm:2.4.2" 158 | dependencies: 159 | ansi-styles: ^3.2.1 160 | escape-string-regexp: ^1.0.5 161 | supports-color: ^5.3.0 162 | checksum: ec3661d38fe77f681200f878edbd9448821924e0f93a9cefc0e26a33b145f1027a2084bf19967160d11e1f03bfe4eaffcabf5493b89098b2782c3fe0b03d80c2 163 | languageName: node 164 | linkType: hard 165 | 166 | "color-convert@npm:^1.9.0": 167 | version: 1.9.3 168 | resolution: "color-convert@npm:1.9.3" 169 | dependencies: 170 | color-name: 1.1.3 171 | checksum: fd7a64a17cde98fb923b1dd05c5f2e6f7aefda1b60d67e8d449f9328b4e53b228a428fd38bfeaeb2db2ff6b6503a776a996150b80cdf224062af08a5c8a3a203 172 | languageName: node 173 | linkType: hard 174 | 175 | "color-name@npm:1.1.3": 176 | version: 1.1.3 177 | resolution: "color-name@npm:1.1.3" 178 | checksum: 09c5d3e33d2105850153b14466501f2bfb30324a2f76568a408763a3b7433b0e50e5b4ab1947868e65cb101bb7cb75029553f2c333b6d4b8138a73fcc133d69d 179 | languageName: node 180 | linkType: hard 181 | 182 | "concat-map@npm:0.0.1": 183 | version: 0.0.1 184 | resolution: "concat-map@npm:0.0.1" 185 | checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af 186 | languageName: node 187 | linkType: hard 188 | 189 | "cosmiconfig@npm:^8.1.3": 190 | version: 8.3.6 191 | resolution: "cosmiconfig@npm:8.3.6" 192 | dependencies: 193 | import-fresh: ^3.3.0 194 | js-yaml: ^4.1.0 195 | parse-json: ^5.2.0 196 | path-type: ^4.0.0 197 | peerDependencies: 198 | typescript: ">=4.9.5" 199 | peerDependenciesMeta: 200 | typescript: 201 | optional: true 202 | checksum: dc339ebea427898c9e03bf01b56ba7afbac07fc7d2a2d5a15d6e9c14de98275a9565da949375aee1809591c152c0a3877bb86dbeaf74d5bd5aaa79955ad9e7a0 203 | languageName: node 204 | linkType: hard 205 | 206 | "error-ex@npm:^1.3.1": 207 | version: 1.3.2 208 | resolution: "error-ex@npm:1.3.2" 209 | dependencies: 210 | is-arrayish: ^0.2.1 211 | checksum: c1c2b8b65f9c91b0f9d75f0debaa7ec5b35c266c2cac5de412c1a6de86d4cbae04ae44e510378cb14d032d0645a36925d0186f8bb7367bcc629db256b743a001 212 | languageName: node 213 | linkType: hard 214 | 215 | "escape-string-regexp@npm:^1.0.5": 216 | version: 1.0.5 217 | resolution: "escape-string-regexp@npm:1.0.5" 218 | checksum: 6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 219 | languageName: node 220 | linkType: hard 221 | 222 | "fs.realpath@npm:^1.0.0": 223 | version: 1.0.0 224 | resolution: "fs.realpath@npm:1.0.0" 225 | checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 226 | languageName: node 227 | linkType: hard 228 | 229 | "function-bind@npm:^1.1.1": 230 | version: 1.1.1 231 | resolution: "function-bind@npm:1.1.1" 232 | checksum: b32fbaebb3f8ec4969f033073b43f5c8befbb58f1a79e12f1d7490358150359ebd92f49e72ff0144f65f2c48ea2a605bff2d07965f548f6474fd8efd95bf361a 233 | languageName: node 234 | linkType: hard 235 | 236 | "glob@npm:^7.0.0": 237 | version: 7.2.3 238 | resolution: "glob@npm:7.2.3" 239 | dependencies: 240 | fs.realpath: ^1.0.0 241 | inflight: ^1.0.4 242 | inherits: 2 243 | minimatch: ^3.1.1 244 | once: ^1.3.0 245 | path-is-absolute: ^1.0.0 246 | checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 247 | languageName: node 248 | linkType: hard 249 | 250 | "has-flag@npm:^3.0.0": 251 | version: 3.0.0 252 | resolution: "has-flag@npm:3.0.0" 253 | checksum: 4a15638b454bf086c8148979aae044dd6e39d63904cd452d970374fa6a87623423da485dfb814e7be882e05c096a7ccf1ebd48e7e7501d0208d8384ff4dea73b 254 | languageName: node 255 | linkType: hard 256 | 257 | "has@npm:^1.0.3": 258 | version: 1.0.3 259 | resolution: "has@npm:1.0.3" 260 | dependencies: 261 | function-bind: ^1.1.1 262 | checksum: b9ad53d53be4af90ce5d1c38331e712522417d017d5ef1ebd0507e07c2fbad8686fffb8e12ddecd4c39ca9b9b47431afbb975b8abf7f3c3b82c98e9aad052792 263 | languageName: node 264 | linkType: hard 265 | 266 | "import-fresh@npm:^3.3.0": 267 | version: 3.3.0 268 | resolution: "import-fresh@npm:3.3.0" 269 | dependencies: 270 | parent-module: ^1.0.0 271 | resolve-from: ^4.0.0 272 | checksum: 2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa 273 | languageName: node 274 | linkType: hard 275 | 276 | "inflight@npm:^1.0.4": 277 | version: 1.0.6 278 | resolution: "inflight@npm:1.0.6" 279 | dependencies: 280 | once: ^1.3.0 281 | wrappy: 1 282 | checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd 283 | languageName: node 284 | linkType: hard 285 | 286 | "inherits@npm:2": 287 | version: 2.0.4 288 | resolution: "inherits@npm:2.0.4" 289 | checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 290 | languageName: node 291 | linkType: hard 292 | 293 | "interpret@npm:^1.0.0": 294 | version: 1.4.0 295 | resolution: "interpret@npm:1.4.0" 296 | checksum: 2e5f51268b5941e4a17e4ef0575bc91ed0ab5f8515e3cf77486f7c14d13f3010df9c0959f37063dcc96e78d12dc6b0bb1b9e111cdfe69771f4656d2993d36155 297 | languageName: node 298 | linkType: hard 299 | 300 | "is-arrayish@npm:^0.2.1": 301 | version: 0.2.1 302 | resolution: "is-arrayish@npm:0.2.1" 303 | checksum: eef4417e3c10e60e2c810b6084942b3ead455af16c4509959a27e490e7aee87cfb3f38e01bbde92220b528a0ee1a18d52b787e1458ee86174d8c7f0e58cd488f 304 | languageName: node 305 | linkType: hard 306 | 307 | "is-core-module@npm:^2.11.0": 308 | version: 2.12.0 309 | resolution: "is-core-module@npm:2.12.0" 310 | dependencies: 311 | has: ^1.0.3 312 | checksum: f7f7eb2ab71fd769ee9fb2385c095d503aa4b5ce0028c04557de03f1e67a87c85e5bac1f215945fc3c955867a139a415a3ec4c4234a0bffdf715232660f440a6 313 | languageName: node 314 | linkType: hard 315 | 316 | "js-tokens@npm:^4.0.0": 317 | version: 4.0.0 318 | resolution: "js-tokens@npm:4.0.0" 319 | checksum: 8a95213a5a77deb6cbe94d86340e8d9ace2b93bc367790b260101d2f36a2eaf4e4e22d9fa9cf459b38af3a32fb4190e638024cf82ec95ef708680e405ea7cc78 320 | languageName: node 321 | linkType: hard 322 | 323 | "js-yaml@npm:^4.1.0": 324 | version: 4.1.0 325 | resolution: "js-yaml@npm:4.1.0" 326 | dependencies: 327 | argparse: ^2.0.1 328 | bin: 329 | js-yaml: bin/js-yaml.js 330 | checksum: c7830dfd456c3ef2c6e355cc5a92e6700ceafa1d14bba54497b34a99f0376cecbb3e9ac14d3e5849b426d5a5140709a66237a8c991c675431271c4ce5504151a 331 | languageName: node 332 | linkType: hard 333 | 334 | "json-parse-even-better-errors@npm:^2.3.0": 335 | version: 2.3.1 336 | resolution: "json-parse-even-better-errors@npm:2.3.1" 337 | checksum: 798ed4cf3354a2d9ccd78e86d2169515a0097a5c133337807cdf7f1fc32e1391d207ccfc276518cc1d7d8d4db93288b8a50ba4293d212ad1336e52a8ec0a941f 338 | languageName: node 339 | linkType: hard 340 | 341 | "json5@npm:^2.2.2": 342 | version: 2.2.3 343 | resolution: "json5@npm:2.2.3" 344 | bin: 345 | json5: lib/cli.js 346 | checksum: 2a7436a93393830bce797d4626275152e37e877b265e94ca69c99e3d20c2b9dab021279146a39cdb700e71b2dd32a4cebd1514cd57cee102b1af906ce5040349 347 | languageName: node 348 | linkType: hard 349 | 350 | "lines-and-columns@npm:^1.1.6": 351 | version: 1.2.4 352 | resolution: "lines-and-columns@npm:1.2.4" 353 | checksum: 0c37f9f7fa212b38912b7145e1cd16a5f3cd34d782441c3e6ca653485d326f58b3caccda66efce1c5812bde4961bbde3374fae4b0d11bf1226152337f3894aa5 354 | languageName: node 355 | linkType: hard 356 | 357 | "minimatch@npm:^3.1.1": 358 | version: 3.1.2 359 | resolution: "minimatch@npm:3.1.2" 360 | dependencies: 361 | brace-expansion: ^1.1.7 362 | checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a 363 | languageName: node 364 | linkType: hard 365 | 366 | "minimist@npm:^1.2.6, minimist@npm:^1.2.8": 367 | version: 1.2.8 368 | resolution: "minimist@npm:1.2.8" 369 | checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 370 | languageName: node 371 | linkType: hard 372 | 373 | "once@npm:^1.3.0": 374 | version: 1.4.0 375 | resolution: "once@npm:1.4.0" 376 | dependencies: 377 | wrappy: 1 378 | checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 379 | languageName: node 380 | linkType: hard 381 | 382 | "parent-module@npm:^1.0.0": 383 | version: 1.0.1 384 | resolution: "parent-module@npm:1.0.1" 385 | dependencies: 386 | callsites: ^3.0.0 387 | checksum: 6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff 388 | languageName: node 389 | linkType: hard 390 | 391 | "parse-json@npm:^5.2.0": 392 | version: 5.2.0 393 | resolution: "parse-json@npm:5.2.0" 394 | dependencies: 395 | "@babel/code-frame": ^7.0.0 396 | error-ex: ^1.3.1 397 | json-parse-even-better-errors: ^2.3.0 398 | lines-and-columns: ^1.1.6 399 | checksum: 62085b17d64da57f40f6afc2ac1f4d95def18c4323577e1eced571db75d9ab59b297d1d10582920f84b15985cbfc6b6d450ccbf317644cfa176f3ed982ad87e2 400 | languageName: node 401 | linkType: hard 402 | 403 | "path-is-absolute@npm:^1.0.0": 404 | version: 1.0.1 405 | resolution: "path-is-absolute@npm:1.0.1" 406 | checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 407 | languageName: node 408 | linkType: hard 409 | 410 | "path-parse@npm:^1.0.7": 411 | version: 1.0.7 412 | resolution: "path-parse@npm:1.0.7" 413 | checksum: 49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a 414 | languageName: node 415 | linkType: hard 416 | 417 | "path-type@npm:^4.0.0": 418 | version: 4.0.0 419 | resolution: "path-type@npm:4.0.0" 420 | checksum: 5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 421 | languageName: node 422 | linkType: hard 423 | 424 | "prettier@npm:^2.8.7": 425 | version: 2.8.8 426 | resolution: "prettier@npm:2.8.8" 427 | bin: 428 | prettier: bin-prettier.js 429 | checksum: b49e409431bf129dd89238d64299ba80717b57ff5a6d1c1a8b1a28b590d998a34e083fa13573bc732bb8d2305becb4c9a4407f8486c81fa7d55100eb08263cf8 430 | languageName: node 431 | linkType: hard 432 | 433 | "rechoir@npm:^0.6.2": 434 | version: 0.6.2 435 | resolution: "rechoir@npm:0.6.2" 436 | dependencies: 437 | resolve: ^1.1.6 438 | checksum: fe76bf9c21875ac16e235defedd7cbd34f333c02a92546142b7911a0f7c7059d2e16f441fe6fb9ae203f459c05a31b2bcf26202896d89e390eda7514d5d2702b 439 | languageName: node 440 | linkType: hard 441 | 442 | "resolve-from@npm:^4.0.0": 443 | version: 4.0.0 444 | resolution: "resolve-from@npm:4.0.0" 445 | checksum: f4ba0b8494846a5066328ad33ef8ac173801a51739eb4d63408c847da9a2e1c1de1e6cbbf72699211f3d13f8fc1325648b169bd15eb7da35688e30a5fb0e4a7f 446 | languageName: node 447 | linkType: hard 448 | 449 | "resolve@npm:^1.1.6": 450 | version: 1.22.2 451 | resolution: "resolve@npm:1.22.2" 452 | dependencies: 453 | is-core-module: ^2.11.0 454 | path-parse: ^1.0.7 455 | supports-preserve-symlinks-flag: ^1.0.0 456 | bin: 457 | resolve: bin/resolve 458 | checksum: 7e5df75796ebd429445d102d5824482ee7e567f0070b2b45897b29bb4f613dcbc262e0257b8aeedb3089330ccaea0d6a0464df1a77b2992cf331dcda0f4cb549 459 | languageName: node 460 | linkType: hard 461 | 462 | "resolve@patch:resolve@^1.1.6#~builtin": 463 | version: 1.22.2 464 | resolution: "resolve@patch:resolve@npm%3A1.22.2#~builtin::version=1.22.2&hash=c3c19d" 465 | dependencies: 466 | is-core-module: ^2.11.0 467 | path-parse: ^1.0.7 468 | supports-preserve-symlinks-flag: ^1.0.0 469 | bin: 470 | resolve: bin/resolve 471 | checksum: 66cc788f13b8398de18eb4abb3aed90435c84bb8935953feafcf7231ba4cd191b2c10b4a87b1e9681afc34fb138c705f91f7330ff90bfa36f457e5584076a2b8 472 | languageName: node 473 | linkType: hard 474 | 475 | "shelljs@npm:0.8.5": 476 | version: 0.8.5 477 | resolution: "shelljs@npm:0.8.5" 478 | dependencies: 479 | glob: ^7.0.0 480 | interpret: ^1.0.0 481 | rechoir: ^0.6.2 482 | bin: 483 | shjs: bin/shjs 484 | checksum: 7babc46f732a98f4c054ec1f048b55b9149b98aa2da32f6cf9844c434b43c6251efebd6eec120937bd0999e13811ebd45efe17410edb3ca938f82f9381302748 485 | languageName: node 486 | linkType: hard 487 | 488 | "strip-bom@npm:^3.0.0": 489 | version: 3.0.0 490 | resolution: "strip-bom@npm:3.0.0" 491 | checksum: 8d50ff27b7ebe5ecc78f1fe1e00fcdff7af014e73cf724b46fb81ef889eeb1015fc5184b64e81a2efe002180f3ba431bdd77e300da5c6685d702780fbf0c8d5b 492 | languageName: node 493 | linkType: hard 494 | 495 | "supports-color@npm:^5.3.0": 496 | version: 5.5.0 497 | resolution: "supports-color@npm:5.5.0" 498 | dependencies: 499 | has-flag: ^3.0.0 500 | checksum: 95f6f4ba5afdf92f495b5a912d4abee8dcba766ae719b975c56c084f5004845f6f5a5f7769f52d53f40e21952a6d87411bafe34af4a01e65f9926002e38e1dac 501 | languageName: node 502 | linkType: hard 503 | 504 | "supports-preserve-symlinks-flag@npm:^1.0.0": 505 | version: 1.0.0 506 | resolution: "supports-preserve-symlinks-flag@npm:1.0.0" 507 | checksum: 53b1e247e68e05db7b3808b99b892bd36fb096e6fba213a06da7fab22045e97597db425c724f2bbd6c99a3c295e1e73f3e4de78592289f38431049e1277ca0ae 508 | languageName: node 509 | linkType: hard 510 | 511 | "ts2typebox@workspace:.": 512 | version: 0.0.0-use.local 513 | resolution: "ts2typebox@workspace:." 514 | dependencies: 515 | "@sinclair/typebox": 0.34.25 516 | "@sinclair/typebox-codegen": ^0.10.5 517 | "@types/minimist": 1.2.5 518 | "@types/node": 18.16.0 519 | "@types/prettier": 2.7.2 520 | "@types/shelljs": 0.8.15 521 | cosmiconfig: ^8.1.3 522 | minimist: ^1.2.8 523 | prettier: ^2.8.7 524 | shelljs: 0.8.5 525 | tsconfig-paths: 4.2.0 526 | typescript: ^5.7.3 527 | peerDependencies: 528 | "@sinclair/typebox": ^0.34.25 529 | bin: 530 | ts-to-typebox: dist/src/cli/index.js 531 | ts2typebox: dist/src/cli/index.js 532 | languageName: unknown 533 | linkType: soft 534 | 535 | "tsconfig-paths@npm:4.2.0": 536 | version: 4.2.0 537 | resolution: "tsconfig-paths@npm:4.2.0" 538 | dependencies: 539 | json5: ^2.2.2 540 | minimist: ^1.2.6 541 | strip-bom: ^3.0.0 542 | checksum: 28c5f7bbbcabc9dabd4117e8fdc61483f6872a1c6b02a4b1c4d68c5b79d06896c3cc9547610c4c3ba64658531caa2de13ead1ea1bf321c7b53e969c4752b98c7 543 | languageName: node 544 | linkType: hard 545 | 546 | "typescript@npm:^5.4.5, typescript@npm:^5.7.3": 547 | version: 5.7.3 548 | resolution: "typescript@npm:5.7.3" 549 | bin: 550 | tsc: bin/tsc 551 | tsserver: bin/tsserver 552 | checksum: 6c38b1e989918e576f0307e6ee013522ea480dfce5f3ca85c9b2d8adb1edeffd37f4f30cd68de0c38a44563d12ba922bdb7e36aa2dac9c51de5d561e6e9a2e9c 553 | languageName: node 554 | linkType: hard 555 | 556 | "typescript@patch:typescript@^5.4.5#~builtin, typescript@patch:typescript@^5.7.3#~builtin": 557 | version: 5.7.3 558 | resolution: "typescript@patch:typescript@npm%3A5.7.3#~builtin::version=5.7.3&hash=77c9e2" 559 | bin: 560 | tsc: bin/tsc 561 | tsserver: bin/tsserver 562 | checksum: 633cd749d6cd7bc842c6b6245847173bba99742a60776fae3c0fbcc0d1733cd51a733995e5f4dadd8afb0e64e57d3c7dbbeae953a072ee303940eca69e22f311 563 | languageName: node 564 | linkType: hard 565 | 566 | "wrappy@npm:1": 567 | version: 1.0.2 568 | resolution: "wrappy@npm:1.0.2" 569 | checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 570 | languageName: node 571 | linkType: hard 572 | --------------------------------------------------------------------------------