@bazo/openapi-client-generator 3.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -0
- package/bin.js +21603 -0
- package/package.json +22 -0
- package/skills/generate-client/SKILL.md +180 -0
- package/skills/integrate-full-client/SKILL.md +178 -0
- package/skills/integrate-kotlin-client/SKILL.md +186 -0
- package/skills/integrate-playwright-client/SKILL.md +165 -0
- package/skills/integrate-swift-client/SKILL.md +151 -0
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bazo/openapi-client-generator",
|
|
3
|
+
"version": "3.0.13",
|
|
4
|
+
"bin": {
|
|
5
|
+
"openapi-client-generator": "bin.js"
|
|
6
|
+
},
|
|
7
|
+
"files": [
|
|
8
|
+
"bin.js",
|
|
9
|
+
"skills"
|
|
10
|
+
],
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@apidevtools/swagger-parser": "^12.1.0"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/bazo/openapi-client-generator.git"
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public",
|
|
20
|
+
"registry": "https://registry.npmjs.org"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: generate-client
|
|
3
|
+
description: >
|
|
4
|
+
Run the @bazo/openapi-client-generator CLI to produce a typed API client
|
|
5
|
+
from an OpenAPI JSON spec. Covers CLI flags (-n/--name, -m/--mode),
|
|
6
|
+
positional arguments (spec path, output directory), generation modes
|
|
7
|
+
(full, playwright, swift, kotlin), output file naming, and npm script
|
|
8
|
+
integration. Load when generating, regenerating, or configuring the
|
|
9
|
+
openapi-client-generator CLI.
|
|
10
|
+
type: core
|
|
11
|
+
library: openapi-client-generator
|
|
12
|
+
library_version: "3.0.0"
|
|
13
|
+
sources:
|
|
14
|
+
- "bazo/openapi-client-generator:src/bin.ts"
|
|
15
|
+
- "bazo/openapi-client-generator:src/pipeline.ts"
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Generate Client
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -D @bazo/openapi-client-generator
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Run the generator:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npx openapi-client api.json out/ -n MyClient -m full
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Arguments and flags:
|
|
33
|
+
|
|
34
|
+
| Position/Flag | Required | Description |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| `<spec.json>` | yes | Path to a local OpenAPI JSON file |
|
|
37
|
+
| `<output-dir>` | yes | Directory for the generated file |
|
|
38
|
+
| `-n, --name` | yes | Client class name (must be a valid TypeScript identifier) |
|
|
39
|
+
| `-m, --mode` | no | `full` (default), `playwright`, `swift`, or `kotlin` |
|
|
40
|
+
|
|
41
|
+
Save as an npm script:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"scripts": {
|
|
46
|
+
"generate-api": "openapi-client api.json src/generated/ -n ApiClient -m full"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Core Patterns
|
|
52
|
+
|
|
53
|
+
### Generate a full-mode TypeScript client (React Query + Wretch + Zod)
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx openapi-client openapi.json src/api/ -n ApiClient -m full
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Produces `src/api/ApiClient.ts` with Zod schemas, React Query hooks, and a client class.
|
|
60
|
+
|
|
61
|
+
### Generate a Playwright test client
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx openapi-client openapi.json tests/api/ -n TestApi -m playwright
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Produces `tests/api/TestApi.ts` with async methods wrapping Playwright's `APIRequestContext`.
|
|
68
|
+
|
|
69
|
+
### Generate a Swift client
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx openapi-client openapi.json Sources/API/ -n ApiClient -m swift
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Produces `Sources/API/ApiClient.swift` with Codable structs and URLSession-based async methods.
|
|
76
|
+
|
|
77
|
+
### Generate a Kotlin client
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npx openapi-client openapi.json src/main/kotlin/api/ -n ApiClient -m kotlin
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Produces `src/main/kotlin/api/ApiClient.kt` with `@Serializable` data classes and Ktor suspend functions.
|
|
84
|
+
|
|
85
|
+
## Common Mistakes
|
|
86
|
+
|
|
87
|
+
### CRITICAL Hallucinating non-existent CLI flags
|
|
88
|
+
|
|
89
|
+
Wrong:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npx openapi-client api.json out/ -n MyClient --format json --validate --strict
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Correct:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npx openapi-client api.json out/ -n MyClient -m full
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The CLI uses `parseArgs` with `strict: true`. Only `-n/--name`, `-m/--mode`, `-v/--version`, and `-h/--help` exist. Any other flag causes a hard error.
|
|
102
|
+
|
|
103
|
+
Source: src/bin.ts
|
|
104
|
+
|
|
105
|
+
### HIGH Wrong positional argument order
|
|
106
|
+
|
|
107
|
+
Wrong:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
npx openapi-client out/ api.json -n MyClient
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Correct:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npx openapi-client api.json out/ -n MyClient
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The first positional must be the spec file path, the second must be the output directory. Swapping them causes the tool to try reading a directory as a JSON file.
|
|
120
|
+
|
|
121
|
+
Source: src/bin.ts
|
|
122
|
+
|
|
123
|
+
### HIGH Omitting the required --name flag
|
|
124
|
+
|
|
125
|
+
Wrong:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npx openapi-client api.json out/ -m full
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Correct:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
npx openapi-client api.json out/ -n MyClient -m full
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The `-n/--name` flag is required. It sets the exported class name and output filename. The CLI exits with an error if missing.
|
|
138
|
+
|
|
139
|
+
Source: src/bin.ts
|
|
140
|
+
|
|
141
|
+
### HIGH Passing a YAML spec or URL instead of a JSON file
|
|
142
|
+
|
|
143
|
+
Wrong:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npx openapi-client https://api.example.com/openapi.yaml out/ -n MyClient
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Correct:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
npx openapi-client ./openapi.json out/ -n MyClient
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The parser expects a local JSON file path. YAML specs and remote URLs are not supported.
|
|
156
|
+
|
|
157
|
+
Source: src/parser/openapi-parser.ts
|
|
158
|
+
|
|
159
|
+
### HIGH Using an invalid mode name
|
|
160
|
+
|
|
161
|
+
Wrong:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
npx openapi-client api.json out/ -n MyClient -m react-query
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Correct:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
npx openapi-client api.json out/ -n MyClient -m full
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Mode must be exactly `full`, `playwright`, `swift`, or `kotlin`. Aliases like `react-query`, `ts`, `ios`, or `android` are not recognized.
|
|
174
|
+
|
|
175
|
+
Source: src/bin.ts
|
|
176
|
+
|
|
177
|
+
See also: integrate-full-client/SKILL.md — peer deps and client instantiation for full mode
|
|
178
|
+
See also: integrate-playwright-client/SKILL.md — Playwright fixture setup for playwright mode
|
|
179
|
+
See also: integrate-swift-client/SKILL.md — Xcode integration for swift mode
|
|
180
|
+
See also: integrate-kotlin-client/SKILL.md — Ktor setup for kotlin mode
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: integrate-full-client
|
|
3
|
+
description: >
|
|
4
|
+
Use the generated full-mode TypeScript client in a web application.
|
|
5
|
+
Covers peer dependencies (zod, wretch, @tanstack/react-query), client
|
|
6
|
+
class instantiation with baseUrl and QueryClient, React Query useQuery
|
|
7
|
+
and useMutation hooks, Wretch HTTP configuration via onHttpConfigure,
|
|
8
|
+
ApiResponse<T> type, query invalidation, and GenericWretchError. Load
|
|
9
|
+
when importing or using a generated full-mode client file.
|
|
10
|
+
type: framework
|
|
11
|
+
library: openapi-client-generator
|
|
12
|
+
library_version: "3.0.0"
|
|
13
|
+
requires:
|
|
14
|
+
- generate-client
|
|
15
|
+
sources:
|
|
16
|
+
- "bazo/openapi-client-generator:src/modes/full/index.ts"
|
|
17
|
+
- "bazo/openapi-client-generator:src/modes/full/query.ts"
|
|
18
|
+
- "bazo/openapi-client-generator:src/modes/full/mutation.ts"
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
This skill builds on generate-client. Read it first for CLI usage.
|
|
22
|
+
|
|
23
|
+
# Integrate Full Client
|
|
24
|
+
|
|
25
|
+
## Setup
|
|
26
|
+
|
|
27
|
+
Install peer dependencies required by the generated file:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install zod wretch @tanstack/react-query
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Instantiate the client:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
37
|
+
import { MyClient } from "./generated/MyClient";
|
|
38
|
+
|
|
39
|
+
const queryClient = new QueryClient();
|
|
40
|
+
const api = new MyClient("https://api.example.com", queryClient);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The constructor signature is:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
constructor(
|
|
47
|
+
baseUrl: string,
|
|
48
|
+
queryClient: QueryClient,
|
|
49
|
+
options?: RequestInit,
|
|
50
|
+
onHttpConfigure?: (w: Http) => Http
|
|
51
|
+
)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Core Patterns
|
|
55
|
+
|
|
56
|
+
### Use a generated query hook in a React component
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
function TaskList() {
|
|
60
|
+
const { data, isLoading } = api.listTasks.useQuery({ page: 1, limit: 10 });
|
|
61
|
+
|
|
62
|
+
if (isLoading) return <div>Loading...</div>;
|
|
63
|
+
return <div>{data?.data.items.map(t => <div key={t.id}>{t.title}</div>)}</div>;
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Each query operation exposes `.useQuery(params, options?)` which returns a standard React Query result extended with `.key` (the query key) and `.invalidate()` (shortcut for `queryClient.invalidateQueries`).
|
|
68
|
+
|
|
69
|
+
### Use a generated mutation hook
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
function CreateTask() {
|
|
73
|
+
const { mutate, isPending } = api.createTask.useMutation({
|
|
74
|
+
onSuccess: () => api.listTasks.useQuery.invalidate?.(),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<button onClick={() => mutate({ body: { title: "New task", status: "todo" } })} disabled={isPending}>
|
|
79
|
+
Create
|
|
80
|
+
</button>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Each mutation operation exposes `.useMutation(options?)`.
|
|
86
|
+
|
|
87
|
+
### Use the query function directly (outside React)
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
const result = await api.listTasks.query({ page: 1, limit: 10 });
|
|
91
|
+
console.log(result.data); // typed response body
|
|
92
|
+
console.log(result.status); // HTTP status code
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Every operation also exposes a `.query()` or `.mutation()` function for non-React usage.
|
|
96
|
+
|
|
97
|
+
### Configure HTTP with auth headers
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
const api = new MyClient(
|
|
101
|
+
"https://api.example.com",
|
|
102
|
+
queryClient,
|
|
103
|
+
undefined,
|
|
104
|
+
(http) => http.auth(`Bearer ${token}`)
|
|
105
|
+
);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The `onHttpConfigure` callback receives a Wretch instance and must return one. Use it to add auth, interceptors, or middleware.
|
|
109
|
+
|
|
110
|
+
## Common Mistakes
|
|
111
|
+
|
|
112
|
+
### CRITICAL Missing peer dependencies
|
|
113
|
+
|
|
114
|
+
Wrong:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npm install zod
|
|
118
|
+
# Generated file fails: Cannot find module 'wretch'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Correct:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npm install zod wretch @tanstack/react-query
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The generated full-mode file imports from `zod`, `wretch`, `wretch/addons/queryString`, and `@tanstack/react-query`. All four must be installed in the consuming project.
|
|
128
|
+
|
|
129
|
+
Source: src/modes/full/index.ts generateImports
|
|
130
|
+
|
|
131
|
+
### CRITICAL Instantiating client without QueryClient
|
|
132
|
+
|
|
133
|
+
Wrong:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
const api = new MyClient("https://api.example.com");
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Correct:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
143
|
+
const queryClient = new QueryClient();
|
|
144
|
+
const api = new MyClient("https://api.example.com", queryClient);
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The constructor requires both `baseUrl` and a `QueryClient` instance. The client uses a Proxy to lazily bind operations to the HTTP instance and QueryClient — without the QueryClient, hooks will fail at runtime.
|
|
148
|
+
|
|
149
|
+
Source: src/modes/full/index.ts generateClient
|
|
150
|
+
|
|
151
|
+
### HIGH Editing the generated file directly
|
|
152
|
+
|
|
153
|
+
Wrong:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
// Manually adding a custom method to MyClient.ts
|
|
157
|
+
export class MyClient {
|
|
158
|
+
// ...generated code...
|
|
159
|
+
async customMethod() { /* hand-written */ }
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Correct:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
// Extend or wrap the generated client in a separate file
|
|
167
|
+
import { MyClient } from "./generated/MyClient";
|
|
168
|
+
|
|
169
|
+
class ExtendedClient extends MyClient {
|
|
170
|
+
async customMethod() { /* hand-written */ }
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The generated output is meant to be regenerated from the spec. Manual edits are overwritten on the next generation run.
|
|
175
|
+
|
|
176
|
+
Source: maintainer interview
|
|
177
|
+
|
|
178
|
+
See also: generate-client/SKILL.md — CLI usage for regenerating the client
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: integrate-kotlin-client
|
|
3
|
+
description: >
|
|
4
|
+
Use the generated Kotlin client in an Android or JVM application. Covers
|
|
5
|
+
Ktor HttpClient and kotlinx.serialization dependencies, instantiation
|
|
6
|
+
with HttpClient and baseUrl string, suspend operation functions in
|
|
7
|
+
coroutine scope, @Serializable data classes, ApiResponse<T>, ApiException
|
|
8
|
+
handling, and content negotiation setup. Load when importing or using a
|
|
9
|
+
generated kotlin-mode client file.
|
|
10
|
+
type: framework
|
|
11
|
+
library: openapi-client-generator
|
|
12
|
+
library_version: "3.0.0"
|
|
13
|
+
requires:
|
|
14
|
+
- generate-client
|
|
15
|
+
sources:
|
|
16
|
+
- "bazo/openapi-client-generator:src/modes/kotlin/index.ts"
|
|
17
|
+
- "bazo/openapi-client-generator:src/modes/kotlin/query.ts"
|
|
18
|
+
- "bazo/openapi-client-generator:src/modes/kotlin/mutation.ts"
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
This skill builds on generate-client. Read it first for CLI usage.
|
|
22
|
+
|
|
23
|
+
# Integrate Kotlin Client
|
|
24
|
+
|
|
25
|
+
## Setup
|
|
26
|
+
|
|
27
|
+
Add dependencies to `build.gradle.kts`:
|
|
28
|
+
|
|
29
|
+
```kotlin
|
|
30
|
+
plugins {
|
|
31
|
+
kotlin("plugin.serialization") version "2.1.0"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
dependencies {
|
|
35
|
+
implementation("io.ktor:ktor-client-core:3.1.0")
|
|
36
|
+
implementation("io.ktor:ktor-client-cio:3.1.0")
|
|
37
|
+
implementation("io.ktor:ktor-client-content-negotiation:3.1.0")
|
|
38
|
+
implementation("io.ktor:ktor-serialization-kotlinx-json:3.1.0")
|
|
39
|
+
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0")
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Instantiate the client:
|
|
44
|
+
|
|
45
|
+
```kotlin
|
|
46
|
+
import io.ktor.client.*
|
|
47
|
+
import io.ktor.client.plugins.contentnegotiation.*
|
|
48
|
+
import io.ktor.serialization.kotlinx.json.*
|
|
49
|
+
|
|
50
|
+
val httpClient = HttpClient(CIO) {
|
|
51
|
+
install(ContentNegotiation) {
|
|
52
|
+
json()
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
val api = ApiClient(client = httpClient, baseUrl = "https://api.example.com")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The constructor signature is:
|
|
60
|
+
|
|
61
|
+
```kotlin
|
|
62
|
+
class ApiClient(
|
|
63
|
+
private val client: HttpClient,
|
|
64
|
+
private val baseUrl: String
|
|
65
|
+
)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Core Patterns
|
|
69
|
+
|
|
70
|
+
### Call a query operation
|
|
71
|
+
|
|
72
|
+
```kotlin
|
|
73
|
+
runBlocking {
|
|
74
|
+
val result = api.listTasks(page = 1, limit = 10)
|
|
75
|
+
println(result.data.items) // List<Task>
|
|
76
|
+
println(result.status) // 200
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
All operations are `suspend` functions. Query parameters map to function parameters with defaults for optional ones.
|
|
81
|
+
|
|
82
|
+
### Call a mutation operation
|
|
83
|
+
|
|
84
|
+
```kotlin
|
|
85
|
+
runBlocking {
|
|
86
|
+
val result = api.createTask(
|
|
87
|
+
body = CreateTaskRequest(title = "Build feature", status = "todo")
|
|
88
|
+
)
|
|
89
|
+
println(result.data.id) // created task ID
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Mutations take a `body` parameter typed as the corresponding `@Serializable` data class.
|
|
94
|
+
|
|
95
|
+
### Handle API errors
|
|
96
|
+
|
|
97
|
+
```kotlin
|
|
98
|
+
runBlocking {
|
|
99
|
+
try {
|
|
100
|
+
val result = api.getTask(taskId = "nonexistent")
|
|
101
|
+
} catch (e: ApiException) {
|
|
102
|
+
println("HTTP ${e.statusCode}: ${e.body}")
|
|
103
|
+
println("URL: ${e.responseUrl}")
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Non-success responses throw `ApiException` with `statusCode`, `body`, `responseHeaders`, and `responseUrl`.
|
|
109
|
+
|
|
110
|
+
## Common Mistakes
|
|
111
|
+
|
|
112
|
+
### CRITICAL Missing Ktor or kotlinx.serialization dependencies
|
|
113
|
+
|
|
114
|
+
Wrong:
|
|
115
|
+
|
|
116
|
+
```kotlin
|
|
117
|
+
// build.gradle.kts — missing ktor and serialization deps
|
|
118
|
+
dependencies {
|
|
119
|
+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Correct:
|
|
124
|
+
|
|
125
|
+
```kotlin
|
|
126
|
+
dependencies {
|
|
127
|
+
implementation("io.ktor:ktor-client-core:3.1.0")
|
|
128
|
+
implementation("io.ktor:ktor-client-cio:3.1.0")
|
|
129
|
+
implementation("io.ktor:ktor-client-content-negotiation:3.1.0")
|
|
130
|
+
implementation("io.ktor:ktor-serialization-kotlinx-json:3.1.0")
|
|
131
|
+
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0")
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The generated file imports `io.ktor.client.*` and `kotlinx.serialization.*`. Both Ktor client (with a chosen engine like CIO) and kotlinx-serialization-json must be in the project dependencies.
|
|
136
|
+
|
|
137
|
+
Source: src/modes/kotlin/index.ts generateImports
|
|
138
|
+
|
|
139
|
+
### HIGH Calling suspend functions outside coroutine scope
|
|
140
|
+
|
|
141
|
+
Wrong:
|
|
142
|
+
|
|
143
|
+
```kotlin
|
|
144
|
+
fun main() {
|
|
145
|
+
val result = api.getTask(taskId = "123") // Compilation error
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Correct:
|
|
150
|
+
|
|
151
|
+
```kotlin
|
|
152
|
+
suspend fun main() {
|
|
153
|
+
val result = api.getTask(taskId = "123")
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
All generated operations are `suspend` functions. They must be called from a coroutine scope, a `suspend` function, or a builder like `runBlocking`.
|
|
158
|
+
|
|
159
|
+
Source: src/modes/kotlin/query.ts
|
|
160
|
+
|
|
161
|
+
### HIGH Editing the generated file directly
|
|
162
|
+
|
|
163
|
+
Wrong:
|
|
164
|
+
|
|
165
|
+
```kotlin
|
|
166
|
+
// Adding a custom method directly in ApiClient.kt
|
|
167
|
+
class ApiClient(private val client: HttpClient, private val baseUrl: String) {
|
|
168
|
+
// ...generated code...
|
|
169
|
+
suspend fun customMethod() { /* hand-written */ }
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Correct:
|
|
174
|
+
|
|
175
|
+
```kotlin
|
|
176
|
+
// Extend via extension functions in a separate file
|
|
177
|
+
suspend fun ApiClient.customMethod() {
|
|
178
|
+
/* hand-written */
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The generated output is meant to be regenerated from the spec. Manual edits are overwritten on the next generation run. Use Kotlin extension functions in a separate file for custom methods.
|
|
183
|
+
|
|
184
|
+
Source: maintainer interview
|
|
185
|
+
|
|
186
|
+
See also: generate-client/SKILL.md — CLI usage for regenerating the client
|