Skip to content

Commit 91e8a30

Browse files
committed
docs(openapi-generator): add improvement plan
1 parent cae7a32 commit 91e8a30

File tree

1 file changed

+163
-0
lines changed

1 file changed

+163
-0
lines changed

plans.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# Plan for Improving OpenAPI Generator
2+
3+
## Goal:
4+
5+
To evolve the `@metal-box/openapi-generator` into a robust, production-grade tool capable of generating `metal-box/fetch` clients that fully support the OpenAPI 3.x specification, as exemplified by `e-commerse.json` and `e-commerse2.json`.
6+
7+
## Core Principles:
8+
9+
- **Robustness:** Handle malformed input gracefully, provide clear error messages.
10+
- **Type Safety:** Maximize TypeScript type inference and correctness in generated code.
11+
- **Extensibility:** Design components to be easily extendable for future OpenAPI features or custom requirements.
12+
- **Maintainability:** Write clean, modular, and well-tested code.
13+
- **Completeness:** Aim to support all relevant OpenAPI features for client generation.
14+
15+
## Phases of Improvement:
16+
17+
### Phase 1: Foundational Improvements & Robustness
18+
19+
1. **Enhanced Error Handling in `parser.ts`:**
20+
- Wrap `readFileSync` and `JSON.parse` in `try-catch` blocks.
21+
- Provide specific, actionable error messages for file not found, permission issues, and invalid JSON.
22+
- **Example from `e-commerse.json`:** If the JSON is malformed, the current tool crashes.
23+
24+
2. **OpenAPI Spec Validation:**
25+
- Integrate an external OpenAPI validator library (e.g., `swagger-parser` for validation and dereferencing).
26+
- Validate the input OpenAPI document against the official OpenAPI schema before processing.
27+
- **Benefit:** Prevents downstream errors from invalid or incomplete specs.
28+
29+
3. **Centralized OpenAPI Dereferencing:**
30+
- Use a library (e.g., `swagger-parser`'s `dereference` method) to resolve all `$ref` pointers in the OpenAPI document upfront.
31+
- **Benefit:** Simplifies subsequent processing by working with a fully resolved document, avoiding repeated `$ref` resolution logic.
32+
- **Example from `e-commerse.json`:** `#/components/schemas/Product` is referenced multiple times. Dereferencing would provide the full schema directly.
33+
34+
4. **Improved Type Safety for `parsePaths` Output:**
35+
- Replace `Record<string, any>` with a more precise recursive type definition for the `parsedPaths` object.
36+
- **Benefit:** Enhances maintainability and enables better type checking for the router structure.
37+
38+
### Phase 2: Comprehensive Schema Generation (`mapOpenApiTypeToZod`)
39+
40+
This phase focuses on making `mapOpenApiTypeToZod` capable of generating accurate Zod schemas for all OpenAPI schema features.
41+
42+
1. **Polymorphism (`allOf`, `anyOf`, `oneOf`, `discriminator`):**
43+
- **`allOf`:** Map to `z.intersection()` or merge properties.
44+
- **`anyOf`:** Map to `z.union()` (or `z.discriminatedUnion()` if `discriminator` is present).
45+
- **`oneOf`:** Map to `z.union()` with additional checks for exclusivity, or `z.discriminatedUnion()`.
46+
- **`discriminator`:** Implement logic to generate `z.discriminatedUnion()` for polymorphic schemas.
47+
- **Example from `e-commerse.json`:** `Product` schema uses `discriminator` with `ElectronicsProduct` and `ClothingProduct` via `allOf`.
48+
- **Example from `e-commerse2.json`:** `PaymentMethod` uses `oneOf` with `discriminator`.
49+
50+
2. **Enums:**
51+
- Detect `enum` keyword in schema properties.
52+
- Generate `z.enum(['value1', 'value2'])`.
53+
- **Example from `e-commerse.json`:** `category` parameter, `Product.productType`, `Order.status`.
54+
55+
3. **Nullability:**
56+
- Check for `nullable: true` (OpenAPI 3.0) or `type: ['string', 'null']` (OpenAPI 3.1).
57+
- Generate `.nullable()` for the corresponding Zod schema.
58+
- **Example from `e-commerse2.json`:** `User.profile` is optional, but properties within it might be nullable.
59+
60+
4. **Constraints and Validation:**
61+
- **Numeric:** Map `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, `multipleOf` to `z.number().min()`, `.max()`, `.multipleOf()`.
62+
- **String:** Map `minLength`, `maxLength`, `pattern` to `z.string().min()`, `.max()`, `.regex()`.
63+
- **Array:** Map `minItems`, `maxItems`, `uniqueItems` to `z.array().min()`, `.max()`, `.unique()`.
64+
- **Example from `e-commerse.json`:** `price` has `minimum: 0`. `page` and `limit` parameters have `minimum`/`maximum`. `priceRange` array has `minItems`/`maxItems`.
65+
- **Example from `e-commerse2.json`:** `User.username` has `pattern`.
66+
67+
5. **Default Values:**
68+
- Detect `default` keyword.
69+
- Generate `.default()` for the Zod schema.
70+
- **Example from `e-commerse.json`:** `page` and `limit` parameters have `default` values.
71+
72+
6. **`readOnly` / `writeOnly`:**
73+
- Consider how to reflect these in generated types (e.g., separate input/output types, or Zod refinements).
74+
- **Example from `e-commerse2.json`:** `User.id` is `readOnly`, `User.profile.joinDate` is `readOnly`, `Product.stock` is `writeOnly`.
75+
76+
7. **`additionalProperties`:**
77+
- Handle `additionalProperties` (boolean or schema) for object types.
78+
- **Example from `e-commerse.json`:** `sort` parameter has `additionalProperties`. `ElectronicsProduct.specs` has `additionalProperties`.
79+
80+
8. **Recursive Schemas:**
81+
- Implement a strategy to handle schemas that reference themselves (e.g., a tree structure). This often involves `z.lazy()` or a two-pass approach.
82+
83+
9. **Improved `$ref` Resolution for Schemas:**
84+
- Ensure robust handling of `$ref`s within schemas, including local and external references (if supported by the dereferencing step).
85+
86+
### Phase 3: Advanced Operation & Parameter Handling (`generateBuilder`)
87+
88+
This phase focuses on making `generateBuilder` capable of generating `metal-box/fetch` configurations for all operation-level features.
89+
90+
1. **Full Content Type Support for Request Bodies:**
91+
- Iterate through `operation.requestBody.content` to find the most appropriate media type.
92+
- Map `multipart/form-data` to `FormData` and `def_body()` that accepts `FormData`.
93+
- Map `application/xml` or `text/plain` to appropriate `def_body()` that accepts `string` or `Blob`.
94+
- **Example from `e-commerse.json`:** `products` POST supports `application/json`, `application/xml`, `multipart/form-data`.
95+
- **Example from `e-commerse2.json`:** `products` POST uses `multipart/form-data`.
96+
97+
2. **Comprehensive Parameter Handling:**
98+
- **Query Parameters (`in: 'query'`):**
99+
- Generate `def_searchparams()` with a Zod schema derived from the parameter schemas.
100+
- Handle `style` (e.g., `form`, `pipeDelimited`, `deepObject`) and `explode` for complex query parameters (arrays, objects).
101+
- **Example from `e-commerse.json`:** `category`, `priceRange`, `page`, `limit`, `sort` parameters.
102+
- **Example from `e-commerse2.json`:** `searchQuery`, `tags`, `page` parameters.
103+
- **Header Parameters (`in: 'header'`):**
104+
- Generate `headers` object in the `query` call or use `def_request_handler` to set headers.
105+
- **Example from `e-commerse.json`:** `userId` parameter.
106+
- **Cookie Parameters (`in: 'cookie'`):**
107+
- Similar to header parameters, but for cookies.
108+
- **Path Parameters (`in: 'path'`):**
109+
- Ensure `metal-box/fetch`'s dynamic path handling (`$id`) is correctly integrated with the generated `path` object in the `query` call.
110+
- **Example from `e-commerse.json`:** `orderId` path parameter.
111+
112+
3. **Multiple Responses (Success and Error):**
113+
- Iterate through `operation.responses` to generate `def_response` for all successful status codes (2xx).
114+
- Consider generating specific error response types for non-2xx responses (e.g., `400`, `404`, `default`). This might involve a union type for the response or separate error handling.
115+
- **Example from `e-commerse.json`:** `products` GET has `200`, `400`, `default` responses.
116+
117+
4. **Request Body `$ref` Resolution:**
118+
- Ensure `generateBuilder` can resolve `$ref`s pointing to `components/requestBodies` (e.g., `OrderProcessingRequest` in `e-commerse2.json`).
119+
120+
5. **Conditional `def_json()`:**
121+
- Only add `f.builder().def_json()` if `application/json` is the primary content type for either request or response.
122+
123+
### Phase 4: Router & API Enhancements (`generateRouter`)
124+
125+
1. **Server Variable Resolution:**
126+
- Implement logic to resolve server variables (e.g., `{environment}`, `{version}`).
127+
- Provide options for users to specify variable values (e.g., via CLI arguments or configuration).
128+
- Default to `default` values if available.
129+
- **Example from `e-commerse.json`:** `servers` array with `environment` and `version` variables.
130+
131+
2. **Security Scheme Integration:**
132+
- Parse `components/securitySchemes` and `security` objects at global and operation levels.
133+
- Generate `metal-box/fetch` middleware or `def_request_handler` logic to add authentication headers (e.g., `Authorization` for API Key, Basic, Bearer, OAuth2).
134+
- **Example from `e-commerse.json`:** `apiKeyAuth`, `basicAuth`, `bearerAuth`, `oauth2` schemes.
135+
136+
3. **Callbacks & Webhooks:**
137+
- **Callbacks:** Analyze `callbacks` objects within operations. Determine if client-side generation for these is feasible or necessary (often server-side). If so, generate corresponding client-side types/interfaces.
138+
- **Webhooks:** Analyze `webhooks` objects. Generate types for webhook payloads.
139+
- **Example from `e-commerse.json`:** `productCreatedNotification` callback, `orderStatusUpdate` webhook.
140+
- **Example from `e-commerse2.json`:** `onOrderProcessed` callback, `inventoryUpdate` webhook.
141+
142+
4. **Configurability:**
143+
- Allow users to configure `prettier` options (e.g., read from `.prettierrc`).
144+
- Add CLI options for various generation behaviors (e.g., include/exclude specific features, custom base URL overrides).
145+
146+
### Phase 5: Testing & Documentation
147+
148+
1. **Comprehensive Unit & Integration Tests:**
149+
- Write dedicated tests for each new feature implemented, using small, focused OpenAPI snippets.
150+
- Expand integration tests using `e-commerse.json` and `e-commerse2.json` to cover the newly supported features.
151+
- Ensure generated code passes linting and type-checking.
152+
153+
2. **Detailed Documentation:**
154+
- Update the `README.md` with instructions on how to use the generator, supported OpenAPI features, and configuration options.
155+
- Provide examples of generated code for various OpenAPI constructs.
156+
157+
## Tools/Libraries to Consider:
158+
159+
- **`swagger-parser`:** For robust OpenAPI parsing, validation, and dereferencing.
160+
- **`json-schema-to-typescript`:** As a reference or for inspiration on complex schema mapping, though direct Zod generation is preferred.
161+
- **`openapi-sampler`:** For generating example payloads from schemas (useful for testing).
162+
163+
This plan outlines a significant undertaking, but following these steps will transform the current generator into a high-quality, production-ready tool.

0 commit comments

Comments
 (0)