@tzurp/openapi-skills 1.2.5

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.
Files changed (83) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +230 -0
  3. package/bin/openapi-skills +4 -0
  4. package/dist/cli.d.ts +37 -0
  5. package/dist/cli.js +1646 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/client-schema-builder.d.ts +35 -0
  8. package/dist/client-schema-builder.js +268 -0
  9. package/dist/client-schema-builder.js.map +1 -0
  10. package/dist/helper/base64url-json.d.ts +3 -0
  11. package/dist/helper/base64url-json.js +28 -0
  12. package/dist/helper/base64url-json.js.map +1 -0
  13. package/dist/helper/dotNotation.d.ts +3 -0
  14. package/dist/helper/dotNotation.js +34 -0
  15. package/dist/helper/dotNotation.js.map +1 -0
  16. package/dist/helper/endpoint-filter.d.ts +16 -0
  17. package/dist/helper/endpoint-filter.js +165 -0
  18. package/dist/helper/endpoint-filter.js.map +1 -0
  19. package/dist/helper/endpoint-utils.d.ts +2 -0
  20. package/dist/helper/endpoint-utils.js +10 -0
  21. package/dist/helper/endpoint-utils.js.map +1 -0
  22. package/dist/helper/error-codes.d.ts +27 -0
  23. package/dist/helper/error-codes.js +116 -0
  24. package/dist/helper/error-codes.js.map +1 -0
  25. package/dist/helper/error-formatter.d.ts +46 -0
  26. package/dist/helper/error-formatter.js +72 -0
  27. package/dist/helper/error-formatter.js.map +1 -0
  28. package/dist/helper/get-operation-filter.d.ts +17 -0
  29. package/dist/helper/get-operation-filter.js +26 -0
  30. package/dist/helper/get-operation-filter.js.map +1 -0
  31. package/dist/helper/graphql.d.ts +40 -0
  32. package/dist/helper/graphql.js +967 -0
  33. package/dist/helper/graphql.js.map +1 -0
  34. package/dist/helper/http-client.d.ts +28 -0
  35. package/dist/helper/http-client.js +90 -0
  36. package/dist/helper/http-client.js.map +1 -0
  37. package/dist/helper/json-updater.d.ts +17 -0
  38. package/dist/helper/json-updater.js +195 -0
  39. package/dist/helper/json-updater.js.map +1 -0
  40. package/dist/helper/logger.d.ts +13 -0
  41. package/dist/helper/logger.js +56 -0
  42. package/dist/helper/logger.js.map +1 -0
  43. package/dist/helper/output-size.d.ts +5 -0
  44. package/dist/helper/output-size.js +7 -0
  45. package/dist/helper/output-size.js.map +1 -0
  46. package/dist/helper/parameter-schema.d.ts +14 -0
  47. package/dist/helper/parameter-schema.js +36 -0
  48. package/dist/helper/parameter-schema.js.map +1 -0
  49. package/dist/helper/paths.d.ts +11 -0
  50. package/dist/helper/paths.js +47 -0
  51. package/dist/helper/paths.js.map +1 -0
  52. package/dist/helper/prompt-delete.d.ts +1 -0
  53. package/dist/helper/prompt-delete.js +13 -0
  54. package/dist/helper/prompt-delete.js.map +1 -0
  55. package/dist/helper/request-artifacts.d.ts +14 -0
  56. package/dist/helper/request-artifacts.js +60 -0
  57. package/dist/helper/request-artifacts.js.map +1 -0
  58. package/dist/helper/request-preparation.d.ts +23 -0
  59. package/dist/helper/request-preparation.js +85 -0
  60. package/dist/helper/request-preparation.js.map +1 -0
  61. package/dist/helper/sanitizer.d.ts +1 -0
  62. package/dist/helper/sanitizer.js +17 -0
  63. package/dist/helper/sanitizer.js.map +1 -0
  64. package/dist/helper/update-check.d.ts +1 -0
  65. package/dist/helper/update-check.js +36 -0
  66. package/dist/helper/update-check.js.map +1 -0
  67. package/dist/index.d.ts +50 -0
  68. package/dist/index.js +163 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/install-skill.d.ts +5 -0
  71. package/dist/install-skill.js +139 -0
  72. package/dist/install-skill.js.map +1 -0
  73. package/dist/parser.d.ts +12 -0
  74. package/dist/parser.js +393 -0
  75. package/dist/parser.js.map +1 -0
  76. package/dist/validate-response.d.ts +47 -0
  77. package/dist/validate-response.js +1017 -0
  78. package/dist/validate-response.js.map +1 -0
  79. package/package.json +63 -0
  80. package/skill-templates/SKILL.md +204 -0
  81. package/skill-templates/create-endpoint-test.md +413 -0
  82. package/skill-templates/http-client.md +141 -0
  83. package/skill-templates/write-client-code.md +219 -0
@@ -0,0 +1,219 @@
1
+ # Scenario: Write Client Code for an Operation
2
+
3
+ **Goal:** Generate TypeScript client code for a specific operation using schema metadata.
4
+
5
+ ## Workflow
6
+
7
+ 1. **Ensure API is parsed:** Run `openapi-skills get-api-names` to verify API exists, or run `openapi-skills generate <spec-source> --base-url <url> --no-progress --rename<newApiName>` if needed.
8
+ 2. **Find the operation identifier:** Run `openapi-skills list --api <apiName>` with at least one schema-appropriate filter. Use `--method`/`--path`/`--tag` when the schema exposes OpenAPI operations, or `--root-type` when it exposes GraphQL root fields. Use `--filter`, `--tag`, and `--index` as needed.
9
+ 3. **Get schema:** Run `openapi-skills generate-client-schema <operationId> --api <apiName>` to retrieve structured metadata for code generation.
10
+ 4. **Generate client code:** Using the schema output, write the TypeScript client class following the rules in this document.
11
+
12
+ **Example:**
13
+ ```bash
14
+ openapi-skills generate-client-schema addPet --api petstore
15
+ ```
16
+
17
+ ---
18
+
19
+ ## Scope
20
+
21
+ **Generate:** TypeScript class with typed methods, interfaces for parameters and responses, JSDoc comments describing each method.
22
+
23
+ **Do NOT generate:** Usage examples showing how to instantiate or call the client. Users will write their own usage code.
24
+
25
+ ## Generated Code Structure
26
+
27
+ ### File Header
28
+
29
+ All generated client code must begin with:
30
+ ```typescript
31
+ /**
32
+ * <API Name> Client
33
+ * Generated from <apiName> API schema by openapi-skills.
34
+ */
35
+ ```
36
+
37
+ Substitute placeholders:
38
+ - `<API Name>`: Human-readable API name (e.g., "Petstore" or "GitHub")
39
+ - `<operationId>`: The operation identifier from the schema (for example, an OpenAPI `operationId` or a GraphQL `name`)
40
+ - `<apiName>`: The parsed API name from config (e.g., "petstore")
41
+
42
+ ### Class Structure Rules
43
+
44
+ **Constructor:**
45
+ - Must accept a single `httpClient` parameter implementing the `HttpClient` interface (see `http-client.md` for the HttpClient interface definition).
46
+ - Must NOT accept or define `baseUrl`, `authToken`, `apiKey`, or any authentication-related properties.
47
+ - Must include this comment above the constructor:
48
+ ```typescript
49
+ // Pass your own http client that implements the HttpClient interface.
50
+ ```
51
+ - All base URL and authentication handling is delegated to the `httpClient` implementation.
52
+
53
+ **Methods:**
54
+ - Each operation becomes an instance method named after the operation identifier from the schema.
55
+ - All methods must use `this.httpClient` to make requests.
56
+ - All methods are instance methods (not static).
57
+ - If the operation request body is multipart or contains binary fields, preserve that distinction in the request-body type metadata instead of collapsing everything into a plain string/object payload.
58
+
59
+ **Class Naming:**
60
+ - Format: `<ApiName><FirstPathSegment>Client`
61
+ - `<ApiName>`: Capitalized API name (e.g., `Petstore`)
62
+ - `<FirstPathSegment>`: Capitalized first path segment (e.g., `User` for `/user/login`, `Pet` for `/pet/{id}`)
63
+ - Example: `PetstorePetClient` for API `petstore` and path `/pet/{petId}`
64
+
65
+ **Required HttpClient Interface:**
66
+ ```typescript
67
+ interface HttpClient {
68
+ get(url: string, headers?: Record<string, string>): Promise<any>;
69
+ post(url: string, body?: any, headers?: Record<string, string>): Promise<any>;
70
+ put(url: string, body?: any, headers?: Record<string, string>): Promise<any>;
71
+ delete(url: string, headers?: Record<string, string>): Promise<any>;
72
+ }
73
+ ```
74
+
75
+ ## Method Generation Rules
76
+
77
+ ### Parameter Ordering in Method Signatures
78
+
79
+ Parameters must appear in this order:
80
+ 1. **Path parameters** (required, positional)
81
+ 2. **Query parameters** (optional, single object with all query params as optional properties)
82
+ 3. **Request body** (required if the operation has a requestBody, named `body`)
83
+ 4. **Headers** (optional, named `headers`)
84
+
85
+ Examples:
86
+ - GET with path + query: `async getPet(petId: number, query?: { details?: boolean }, headers?: Record<string, string>): Promise<GetPetResponse>`
87
+ - POST with body: `async createPet(body: CreatePetRequest, headers?: Record<string, string>): Promise<CreatePetResponse>`
88
+ - DELETE with path: `async deletePet(petId: number, headers?: Record<string, string>): Promise<void>`
89
+
90
+ ### Query Parameter Serialization
91
+
92
+ - **Flat objects only**: Query parameters are always a single flat object (no nested objects).
93
+ - **Arrays**: If a query param is an array (e.g., `tags: string[]`), serialize using `URLSearchParams`, which handles array values via comma separation or bracket notation per API convention.
94
+ - **Encoding**: Use `URLSearchParams` for automatic URL encoding of special characters.
95
+
96
+ Example implementation:
97
+ ```typescript
98
+ if (query) {
99
+ const params = new URLSearchParams();
100
+ Object.entries(query).forEach(([key, value]) => {
101
+ if (Array.isArray(value)) {
102
+ value.forEach(v => params.append(key, v));
103
+ } else if (value !== undefined) {
104
+ params.append(key, String(value));
105
+ }
106
+ });
107
+ const queryString = params.toString();
108
+ if (queryString) url += `?${queryString}`;
109
+ }
110
+ ```
111
+
112
+ ### Response Handling
113
+
114
+ - **Single success response**: Return type is `Promise<ResponseType>`. Use `<operationId>Response` naming for the interface.
115
+ - **Multiple success/error responses (different status codes)**: Include all in a union type. Example: `Promise<FindPetByIdResponse | FindPetByIdError>` for 200/404 responses. Each status code gets its own interface derived from the response schema.
116
+ - **Void/No response**: If `generate-client-schema` returns `response: null`, generate `Promise<void>` as return type.
117
+ - **Response type naming**: Use `<operationId>Response`, `<operationId>Error`, `<operationId>NotFound`, etc. to reflect the complete response schema for each status code, not just extracted data properties.
118
+
119
+ ### URL Construction
120
+
121
+ - Path parameters are substituted using template literals: `/pet/${petId}`
122
+ - Query string is appended only if query parameters exist and are not empty
123
+ - Do not include the base URL; the `httpClient` implementation handles it
124
+
125
+ ### Multipart and File Uploads
126
+
127
+ - When `generate-client-schema` indicates multipart content, represent file fields explicitly in the generated request-body shape.
128
+ - Prefer a file descriptor style for binary fields, for example `{ kind: "file", path: string, fileName?: string, mimeType?: string }`, and derive `fileName` and `mimeType` from the file context when the path is known.
129
+ - Keep ordinary text fields as strings or normal JSON values.
130
+ - Use any `encoding.<field>.contentType` hint from the schema when choosing the file MIME type.
131
+ - If the operation is a raw binary upload, the client should accept a file-like body instead of a JSON object.
132
+
133
+ ## Complete Example
134
+
135
+ ### Sample Input: generate-client-schema Output
136
+
137
+ ```json
138
+ {
139
+ "operationId": "findPetById",
140
+ "method": "GET",
141
+ "path": "/pet/{petId}",
142
+ "parameters": [
143
+ { "name": "petId", "in": "path", "required": true, "type": "integer" },
144
+ { "name": "details", "in": "query", "required": false, "type": "boolean" }
145
+ ],
146
+ "requestBody": null,
147
+ "responses": {
148
+ "200": { "type": "object", "properties": { "id": { "type": "number" }, "name": { "type": "string" } } },
149
+ "404": { "type": "object", "properties": { "error": { "type": "string" } } }
150
+ }
151
+ }
152
+ ```
153
+
154
+ ### Sample Output: Generated TypeScript Client
155
+
156
+ ```typescript
157
+ /**
158
+ * Petstore Client - findPetById
159
+ * Generated from petstore API schema by openapi-skills.
160
+ */
161
+
162
+ interface HttpClient {
163
+ get(url: string, headers?: Record<string, string>): Promise<any>;
164
+ post(url: string, body?: any, headers?: Record<string, string>): Promise<any>;
165
+ put(url: string, body?: any, headers?: Record<string, string>): Promise<any>;
166
+ delete(url: string, headers?: Record<string, string>): Promise<any>;
167
+ }
168
+
169
+ export interface FindPetByIdResponse {
170
+ id: number;
171
+ name: string;
172
+ }
173
+
174
+ export interface FindPetByIdError {
175
+ error: string;
176
+ }
177
+
178
+ export class PetstorePetClient {
179
+ // Pass your own http client that implements the HttpClient interface.
180
+ constructor(private httpClient: HttpClient) {}
181
+
182
+ /**
183
+ * Find pet by ID.
184
+ * @param petId - ID of pet to return
185
+ * @param query - Optional query parameters
186
+ * @param headers - Optional HTTP headers
187
+ * @returns Promise resolving to FindPetByIdResponse or FindPetByIdError
188
+ */
189
+ async findPetById(
190
+ petId: number,
191
+ query?: { details?: boolean },
192
+ headers?: Record<string, string>
193
+ ): Promise<FindPetByIdResponse | FindPetByIdError> {
194
+ let url = `/pet/${petId}`;
195
+
196
+ if (query) {
197
+ const params = new URLSearchParams();
198
+ if (query.details !== undefined) {
199
+ params.append('details', String(query.details));
200
+ }
201
+ const queryString = params.toString();
202
+ if (queryString) url += `?${queryString}`;
203
+ }
204
+
205
+ return this.httpClient.get(url, headers);
206
+ }
207
+ }
208
+ ```
209
+
210
+ ### Key Implementation Points
211
+
212
+ 1. **Type definitions** for request/response are placed above the class
213
+ 2. **Constructor** accepts only `httpClient`; no auth or baseUrl handling
214
+ 3. **Method signature** follows parameter order: path → query → headers
215
+ 4. **URL construction** is relative (no base URL; httpClient adds it)
216
+ 5. **Query serialization** uses URLSearchParams for proper encoding
217
+ 6. **Return type** is a union of all possible response types (`FindPetByIdResponse | FindPetByIdError`)
218
+ 7. **Response type naming** reflects the complete response schema (not extracted properties). Use `<operationId>Response` and `<operationId>Error` format
219
+ 8. **JSDoc** documents parameters and return type