Skip to content

Commit

Permalink
remove comments from generated; readme update
Browse files Browse the repository at this point in the history
  • Loading branch information
vladkens committed Jan 9, 2024
1 parent 54b14fb commit 35d2c7e
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 26 deletions.
4 changes: 1 addition & 3 deletions examples/petstore-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@ export class ApiClient {

async ParseError(rep: Response) {
try {
// try to parse domain error from response body
return await rep.json()
} catch (e) {
// otherwise return response as is
throw rep
}
}
Expand All @@ -58,7 +56,7 @@ export class ApiClient {
let body: FormData | URLSearchParams | string | undefined = undefined

if (ct === "multipart/form-data" || ct === "application/x-www-form-urlencoded") {
headers.delete("content-type") // https://stackoverflow.com/a/61053359/3664464
headers.delete("content-type")
body = ct === "multipart/form-data" ? new FormData() : new URLSearchParams()
for (const [k, v] of Object.entries(opts.body as Record<string, string>)) {
body.append(k, v)
Expand Down
4 changes: 1 addition & 3 deletions examples/petstore-v3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@ export class ApiClient {

async ParseError(rep: Response) {
try {
// try to parse domain error from response body
return await rep.json()
} catch (e) {
// otherwise return response as is
throw rep
}
}
Expand All @@ -58,7 +56,7 @@ export class ApiClient {
let body: FormData | URLSearchParams | string | undefined = undefined

if (ct === "multipart/form-data" || ct === "application/x-www-form-urlencoded") {
headers.delete("content-type") // https://stackoverflow.com/a/61053359/3664464
headers.delete("content-type")
body = ct === "multipart/form-data" ? new FormData() : new URLSearchParams()
for (const [k, v] of Object.entries(opts.body as Record<string, string>)) {
body.append(k, v)
Expand Down
29 changes: 20 additions & 9 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
<div align="center">

[<img src="https://badgen.net/npm/v/apigen-ts" alt="version" />](https://npmjs.org/package/apigen-ts)
[<img src="https://github.com/vladkens/apigen-ts/workflows/test/badge.svg" alt="test status" />](https://github.com/vladkens/apigen-ts/actions)
[<img src="https://badgen.net/packagephobia/publish/apigen-ts" alt="size" />](https://packagephobia.now.sh/result?p=apigen-ts)
[<img src="https://badgen.net/npm/dm/apigen-ts" alt="downloads" />](https://npmjs.org/package/apigen-ts)
[<img src="https://badgen.net/github/license/vladkens/apigen-ts" alt="license" />](https://github.com/vladkens/apigen-ts/blob/main/LICENSE)
[<img src="https://badgen.net/static/-/buy%20me%20a%20coffee/ff813f?icon=buymeacoffee&label" alt="donate" />](https://buymeacoffee.com/vladkens)

</div>

Expand All @@ -15,7 +15,7 @@
</div>

<div align="center">
TypeScript api client generator from OpenAPI specification
TypeScript HTTP Client Generator from OpenAPI Specification
</div>

## Features
Expand All @@ -37,7 +37,7 @@ yarn install -D apigen-ts

## Usage

### Generate
### 1. Generate

```sh
# From url
Expand All @@ -49,9 +49,9 @@ yarn apigen-ts ./openapi.json ./api-client.ts

Run `yarn apigen-ts --help` for more options. See examples of generated clients [here](./examples/).

### Import
### 2. Import

```typescript
```ts
import { ApiClient } from "./api-client"

const api = new ApiClient({
Expand All @@ -60,9 +60,9 @@ const api = new ApiClient({
})
```

### Use
### 3. Use

```typescript
```ts
// GET /pet/{petId}
await api.pet.getPetById(1) // -> Pet

Expand All @@ -77,18 +77,29 @@ await api.user.updateUser("username", { firstName: "John" })

### Login flow

```typescript
```ts
const { token } = await api.auth.login({ usename, password })
api.Config.headers = { Authorization: token }

await api.protectedRoute.get() // here authenticated
```

### Automatic date parsing

```sh
yarn apigen-ts ./openapi.json ./api-client.ts --parse-dates
```

```ts
const pet = await api.pet.getPetById(1)
const createdAt: Date = pet.createdAt // date parsed from string with format=date-time
```

### NodeJS API

Create file like `apigen.mjs` with content:

```javascript
```js
import { apigen } from "apigen-ts"

await apigen({
Expand Down
15 changes: 8 additions & 7 deletions scripts/guru-check.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { enumerate, filterNullable } from "array-utils-ts"
import { exec } from "child_process"
import fs from "fs/promises"
import util from "node:util"
import { loadSchema } from "../src/generator"
import { apigen } from "../src/main"

Expand Down Expand Up @@ -53,7 +51,7 @@ const generateClients = async () => {
for (const [i, file] of enumerate(files, 1)) {
if (debugId && i !== debugId) continue

const src = `${BaseDir}/specs/${file}`
const src = await fs.realpath(`${BaseDir}/specs/${file}`)
const out = `${BaseDir}/clients/${file.replace(".json", ".ts")}`

const doc = JSON.parse(await fs.readFile(src, "utf-8"))
Expand All @@ -64,7 +62,7 @@ const generateClients = async () => {
const tag = `[${i.toString().padStart(len, " ")}/${files.length}] (${ver}) ${src}`

try {
await apigen({ source: src, output: out, parseDates: true })
await apigen({ source: `file://${src}`, output: out, parseDates: true })
console.log(`${tag} generated`)
} catch (err) {
console.log(tag, "failed", err)
Expand All @@ -82,9 +80,12 @@ const generateClients = async () => {
console.log(`versions: ${Object.entries(versions).map((x) => x.join(" - ")).join(", ")}`)
if (failed.length) console.log(`failed ids: ${failed.join(", ")}`)

const cmd = `yarn tsc --noEmit ${BaseDir}/clients/*.ts`
const { stdout, stderr } = await util.promisify(exec)(cmd)
console.log(stdout, stderr)
// NODE_OPTIONS="--max-old-space-size=8192" yarn tsc --noEmit ${BaseDir}/clients/*.ts
// const cmd = `yarn tsc --noEmit ${BaseDir}/clients/*.ts`
// const { stdout, stderr } = await util.promisify(exec)(cmd, {
// env: { ...process.env, NODE_OPTIONS: "--max-old-space-size=8192" },
// })
// console.log(stdout, stderr)
}

const main = async () => {
Expand Down
3 changes: 2 additions & 1 deletion src/_template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ export class ApiClient {
let body: FormData | URLSearchParams | string | undefined = undefined

if (ct === "multipart/form-data" || ct === "application/x-www-form-urlencoded") {
headers.delete("content-type") // https://stackoverflow.com/a/61053359/3664464
// https://stackoverflow.com/a/61053359/3664464
headers.delete("content-type")
body = ct === "multipart/form-data" ? new FormData() : new URLSearchParams()
for (const [k, v] of Object.entries(opts.body as Record<string, string>)) {
body.append(k, v)
Expand Down
2 changes: 2 additions & 0 deletions src/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ export const generateAst = async (ctx: Context) => {
}

export const loadSchema = async (url: string, upgrade = true): Promise<Oas3Definition> => {
if (url.startsWith("file://")) url = url.substring(7)

const { bundle } = await redocly.bundle({
ref: url,
config: await redocly.createConfig({}),
Expand Down
7 changes: 4 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ export const apigen = async (config: Partial<Config> & Pick<Config, "source" | "
let code = [
`// Auto-generated by https://github.com/vladkens/apigen-ts`,
`// Source: ${config.source}\n`,
...file.split("\n").filter((x) => !x.startsWith("// Note: ")),
// remove all comments expect which starts with "// apigen:"
...file.split("\n").filter((x) => !/\s*\/\/\s(?!apigen:)/.test(x)),
].join("\n")

if (!ctx.parseDates) {
code = code.replace(/\s*ISO_FORMAT\s=.+$/gm, "")
code = code.replace(/PopulateDates.+?\n\s{2}\}/s, "")
code = code.replace(/this.PopulateDates\((.+)\)/, "$1")
}

// broken types by design, but typescript still can print it
// need to keep original formatting & comments of the template
// broken type by design, need to keep original formatting (ts still can print it)
code = code.replace("// apigen:modules", printCode(modules as unknown as ts.Statement[]))
code = code.replace("// apigen:types", printCode(types))
code = code.replace("class ApiClient", `class ${ctx.name}`)
Expand Down

0 comments on commit 35d2c7e

Please sign in to comment.