From 68344548bbd6f4c68b3d2d60c7abd277697dffc0 Mon Sep 17 00:00:00 2001 From: Drew Powers Date: Sun, 30 Oct 2022 11:40:29 -0600 Subject: [PATCH] Update docs --- .github/pull_request_template.md | 13 ++++ CONTRIBUTING.md | 130 +++++++++++++++++-------------- README.md | 60 +++++--------- package.json | 1 + 4 files changed, 104 insertions(+), 100 deletions(-) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..7c6437360 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,13 @@ +## Changes + +_What does this PR change? Link to any related issue(s)._ + +## How to Review + +_How can a reviewer review your changes? What should be kept in mind for this review?_ + +## Checklist + +- [ ] Unit tests updated +- [ ] README updated +- [ ] `examples/` directory updated (if applicable) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dd665c073..484eaaf1a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,98 +1,108 @@ # Contributing -Thanks for being willing to contribute! +Thanks for being willing to contribute! 🙏 -**Working on your first Pull Request?** You can learn how from this _free_ series [How to Contribute to an Open Source -Project on GitHub][egghead] +**Working on your first Pull Request (PR)?** You can learn how from this _free_ series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github) -## Project setup +## Open issues + +Please check out the [the open issues](https://github.com/drwpow/openapi-typescript/issues). Issues labelled [**Help Wanted**](https://github.com/drwpow/openapi-typescript/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) and [**Good First Issue**](https://github.com/drwpow/openapi-typescript/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) are especially good to help with. + +Contributing doesn’t have to be in code! Simply answering questions in open issues, or providing workarounds, is just as important a contribution as making pull requests. + +## Setup + +### Dependencies 1. Install [pnpm](https://pnpm.io/) 2. Fork and clone the repo 3. Run `pnpm i` to install dependencies 4. Create a branch for your PR with `git checkout -b pr/your-branch-name` -It’s also recommended you have [ESLint][eslint] installed and set up correctly. You may also run the command -`npm run lint` to see lint errors. +### VS Code setup -> Tip: Keep your `main` branch pointing at the original repository and make pull requests from branches on your fork. To -> do this, run: -> -> ``` -> git remote add upstream https://github.com/drwpow/openapi-typescript.git -> git fetch upstream -> git branch --set-upstream-to=upstream/main main -> ``` -> -> This will add the original repository as a "remote" called "upstream," Then fetch the git information from that -> remote, then set your local `main` branch to use the upstream main branch whenever you run `git pull`. Then you can -> make all of your pull request branches based on this `main` branch. Whenever you want to update your version of -> `main`, do a regular `git pull`. +If using VS Code, the following extensions are recommended (or their equivalent extensions if using another editor) -## Committing and pushing changes +- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) -Please make sure to run the tests (`npm test`) before you commit your changes. +## Workflow -### Local schemas +When working locally, run: -This repo supports OpenAPI 2.0 and 3.0. There are some real-world examples located in `tests/v2/specs/*.yaml` and -`tests/v3/specs/*.yaml`, respectively. Testing large, real schemas was a major goal of this project. Many libraries only -test the “Petstore” example from Swagger, which is contrived and is missing much complexity from companies’ production -schemas. +```bash +npm run dev +``` -_Note: don’t update the `yaml` schemas with your own custom additions (but if the official versions have updated, then -it’s fine to update them here). If you’d like to add your schema for testing, then please add them as a new schema, and -add them to `./expected/*.ts`._ +This will compile the code as you change automatically. -#### Regenerating schemas +### TDD -If you’ve added a feature or fixed a bug and need to update the generated schemas, run the following: +This library is a great usecase for [test-driven development (TDD)](https://en.wikipedia.org/wiki/Test-driven_development). If you’re new to this, the basic workflow is: -``` -# 1. re-build the package -npm run build -# 2. run the local CLI (not the npm one!) -./bin/cli.js tests/v3/specs/github.yaml -o tests/v3/expected/github.ts -# NOTE: on Windows, try running the script on WSL if getting errors -``` +1. First, write a [test](#testing) that fully outlines what you’d _like_ the output to be. +2. Make sure this test **fails** when you run `npm test` (yes, _fails!_) +3. Then, make changes to `src/` until the tests pass. + +_Code generation is hard!_ And for that reason, starting with a very clear expectation of your end-goal can make working easier. + +### Unit tests or snapshot tests? + +This library has both unit tests (tests that test a tiny part of a schema) and snapshot tests (tests that run over an entire, complete schema). When opening a PR, the former are more valuable than the latter, and are always required. However, updating snapshot tests can help with the following: + +- Fixing bugs that deal with multiple schemas with remote `$ref`s +- Fixing Node.js or OS-related bugs +- Adding a CLI option that changes the entire output + +For most PRs, **snapshot tests can be avoided.** But for scenarios similar to the ones mentioned, they can ensure everything is working as expected. + +### Generating types + +It may be surprising to hear, but _generating TypeScript types from OpenAPI is opinionated!_ Even though TypeScript and OpenAPI are very close relatives, both being JavaScript/JSON-based, they are nonetheless 2 different languages and thus there is always some room for interpretation. Likewise, some parts of the OpenAPI specification can be ambiguous on how they’re used, and what the expected type outcomes may be (though this is generally for more advanced usecasees, such as specific implementations of `anyOf` as well as [discriminator](https://spec.openapis.org/oas/latest.html#discriminatorObject) and complex polymorphism). -This should update the expected TypeScript definiton. +All that said, this library should strive to generate _the most predictable_ TypeScript output for a given schema. And to achieve that, it always helps to open an [issue](https://github.com/drwpow/openapi-typescript/issues) or [discussion](https://github.com/drwpow/openapi-typescript/discussions) to gather feedback. -_Also if this appears in `examples/` feel free to update that, too!_ +### Opening a PR + +When opening a pull request, make sure all of the following is done: + +- [x] Tests are added +- [x] Build passes (`npm run build`) +- [x] Tests pass (`npm test`) +- [x] Linting passes (`npm run lint`) + +Lastly, be sure to fill out the complete PR template! ## Testing -Tests use [Vitest](https://vitest.dev), a modern test-runner based on Jest. To run the tests locally, run: +This library uses [Vitest](https://vitest.dev/) for testing. There’s a great [VS Code extension](https://marketplace.visualstudio.com/items?itemName=ZixuanChen.vitest-explorer) you can optionally use if you’d like in-editor debugging tools. -``` +### Running tests + +💡 The tests test **the production build** in `dist/`. Be sure to run `npm run build` before running tests (or keep `npm run dev` running in the background, which compiles as-you-work)! + +To run the entire test suite once, run: + + +```bash npm test ``` To run an individual test: -``` -npx vitest [part of filename] +```bash +npx vitest [partial filename] ``` -Or to start all tests in watch mode: +To start the entire test suite in watch mode: -``` +```bash npx vitest ``` -[See docs](https://vitest.dev) +### Running linting -## Help needed +To run ESLint on the project: -Please check out the [the open issues][issues]. Issues labelled [**Help Wanted**][help-wanted] and [**Good First -Issue**][good-first-issue] are especially good to help with. - -Also, please watch the repo and respond to questions/bug reports/feature requests! Thanks! - -[all-contributors]: https://github.com/all-contributors/all-contributors -[egghead]: https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github -[eslint]: https://eslint.org/ -[good-first-issue]: - https://github.com/drwpow/openapi-typescript/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22 -[help-wanted]: https://github.com/drwpow/openapi-typescript/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22 -[issues]: https://github.com/drwpow/openapi-typescript/issues +```bash +npm run lint +``` diff --git a/README.md b/README.md index 6533f1f0e..ff8c748a8 100644 --- a/README.md +++ b/README.md @@ -8,22 +8,18 @@ # 📘️ openapi-typescript -🚀 Convert [OpenAPI 3.0][openapi3] and [2.0 (Swagger)][openapi2] schemas to TypeScript interfaces using Node.js. +🚀 Convert [OpenAPI](https://spec.openapis.org/oas/latest.html) schemas to TypeScript interfaces painlessly using pure Node.js. No Java, node-gyp, or running OpenAPI servers necessary. Uses [Prettier](https://npmjs.com/prettier) to format the output. **Features** -- ✅ [OpenAPI 3.0][openapi3] -- ✅ [Swagger 2.0][openapi2] -- ✅ Supports YAML and JSON schema formats +- ✅ Supports YAML and JSON - ✅ Supports loading via remote URL (simple authentication supported with the `--auth` flag) - ✅ Supports remote references: `$ref: "external.yaml#components/schemas/User"` -- ✅ Formats using [Prettier][prettier] -- ✅ TypeScript 4.0 features +- ✅ Prettier formatting is fully customizable to match your existing code style. **Examples** -- [Stripe, OpenAPI 2.0](./examples/stripe-openapi2.ts) -- [Stripe, OpenAPI 3.0](./examples/stripe-openapi3.ts) +[See examples](./examples/) ## Usage @@ -54,14 +50,12 @@ _Thanks to [@sharmarajdaksh](https://github.com/sharmarajdaksh) for the glob fea #### ☁️ Reading specs from remote resource ```bash -npx openapi-typescript https://petstore.swagger.io/v2/swagger.json --output petstore.ts +npx openapi-typescript https://petstore3.swagger.io/api/v3/openapi.yaml --output petstore.d.ts -# 🔭 Loading spec from https://petstore.swagger.io/v2/swagger.json… -# 🚀 https://petstore.swagger.io/v2/swagger.json -> petstore.ts [650ms] +# 🔭 Loading spec from https://petstore3.swagger.io/api/v3/openapi.yaml… +# 🚀 https://petstore3.swagger.io/api/v3/openapi.yaml -> petstore.d.ts [650ms] ``` -_Note: globbing doesn’t work for remote schemas because there is no reliable way to determine a list of files to select from a remote file system._ - _Thanks to [@psmyrdek](https://github.com/psmyrdek) for the remote spec feature!_ #### Using in TypeScript @@ -76,7 +70,9 @@ type APIResponse = components["schemas"]["APIResponse"]; Because OpenAPI schemas may have invalid TypeScript characters as names, the square brackets are a safe way to access every property. -Also note that there’s a special `operations` interface that you can import `OperationObjects` by their [operationId][openapi-operationid]: +##### Operations + +Operations can be imported directly by their [operationId](https://spec.openapis.org/oas/latest.html#operation-object): ```ts import { operations } from "./generated-schema.ts"; @@ -84,8 +80,6 @@ import { operations } from "./generated-schema.ts"; type getUsersById = operations["getUsersById"]; ``` -Even though `operations` isn’t present in your original schema, it’s a simple convenience and won’t disrupt any of your other types. - _Thanks to [@gr2m](https://github.com/gr2m) for the operations feature!_ #### openapi-typescript-fetch @@ -94,7 +88,6 @@ The generated spec can also be used with [openapi-typescript-fetch](https://www. ```ts import { paths } from "./petstore"; - import { Fetcher } from "openapi-typescript-fetch"; // declare fetcher for paths @@ -163,7 +156,6 @@ npx openapi-typescript schema.yaml | `--make-paths-enum` | `-pe` | `false` | (optional) Generate an enum of endpoint paths | | `--path-params-as-types` | | `false` | (optional) Substitute path parameter names with their respective types | | `--raw-schema` | | `false` | Generate TS types from partial schema (e.g. having `components.schema` at the top level) | -| `--version` | | | Force OpenAPI version with `--version 3` or `--version 2` (required for `--raw-schema` when version is unknown) | ### 🐢 Node @@ -172,7 +164,7 @@ npm i --save-dev openapi-typescript ``` ```js -import fs from "fs"; +import fs from "node:fs"; import openapiTS from "openapi-typescript"; // example 1: load [object] as schema (JSON only) @@ -187,9 +179,7 @@ const output = await openapiTS(localPath); const output = await openapiTS("https://myurl.com/v1/openapi.yaml"); ``` -The Node API may be useful if dealing with dynamically-created schemas, or you’re using within context of a larger application. Pass in either a JSON-friendly object to load a schema from memory, or a string to load a schema from a local file or remote URL (it will load the file quickly using built-in Node methods). Note that a YAML string isn’t supported in the Node.js API; either use the CLI or convert to JSON using [js-yaml][js-yaml] first. - -⚠️ As of `v4.0`, `openapiTS()` is an async function. +The Node API may be useful if dealing with dynamically-created schemas, or you’re using within context of a larger application. Pass in either a JSON-friendly object to load a schema from memory, or a string to load a schema from a local file or remote URL (it will load the file quickly using built-in Node methods). Note that a YAML string isn’t supported in the Node.js API; either use the CLI or convert to JSON using [js-yaml](https://www.npmjs.com/package/js-yaml) first. #### Custom Formatter @@ -222,26 +212,16 @@ _Note: you don’t have to use `.format`—this is just an example! You can use ## 🏅 Project Goals -1. Support converting any OpenAPI 3.0 or 2.0 (Swagger) schema to TypeScript types, no matter how complicated -1. The generated TypeScript types **must** match your schema as closely as possible (i.e. don’t convert names to - `PascalCase` or follow any TypeScript-isms; faithfully reproduce your schema as closely as possible, capitalization - and all) -1. This library is a TypeScript generator, not a schema validator. +1. Support converting any valid OpenAPI schema to TypeScript types, no matter how complicated. +1. This library does **NOT** validate your schema, there are other libraries for that. +1. The generated TypeScript types **must** match your schema as closely as possible (e.g. no renaming to + `PascalCase`) +1. This library should never require Java, node-gyp, or some other complex environment to work. This should require Node.js and nothing else. +1. This library will never require a running OpenAPI server to work. ## 🤝 Contributing -PRs are welcome! Please see our [CONTRIBUTING.md](./CONTRIBUTING.md) guide. Opening an issue beforehand to discuss is -encouraged but not required. - -[glob]: https://www.npmjs.com/package/glob -[js-yaml]: https://www.npmjs.com/package/js-yaml -[namespace]: https://www.typescriptlang.org/docs/handbook/namespaces.html -[npm-run-all]: https://www.npmjs.com/package/npm-run-all -[openapi-format]: https://swagger.io/specification/#data-types -[openapi-operationid]: https://swagger.io/specification/#operation-object -[openapi2]: https://swagger.io/specification/v2/ -[openapi3]: https://swagger.io/specification -[prettier]: https://npmjs.com/prettier +PRs are welcome! Please see our [CONTRIBUTING.md](./CONTRIBUTING.md) guide. ### Contributors ✨ @@ -323,7 +303,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d - + diff --git a/package.json b/package.json index 8a7fee529..8a9c571c5 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "homepage": "https://github.com/drwpow/openapi-typescript#readme", "scripts": { "build": "del dist && tsc", + "dev": "tsc --watch", "format": "npm run prettier -w .", "lint": "eslint .", "prepare": "npm run build",