apple / apple/swift-openapi-generator

Proposal: Export resolved context for extension tools (no internal API exposure)

Open
#863 3 comments 0 reactions 0 assignees View on GitHub
kind/feature status/triage
Dominant language
Swift
Stars
2k
Forks
182
Avg merge
13h 28m
Merged PRs (30d)
5

Description

## Motivation

We propose a **CLI-based contract** so that third-party tools (e.g. Build Tool Plugins) can generate **additional** Swift files alongside the built-in Types, Client, and Server, using the **same resolved** OpenAPI document and config—**without** the generator exposing or stabilizing any internal APIs (e.g. `_OpenAPIGeneratorCore`).

The real problem is **behavioral consistency**. The official generator applies Filter (e.g. only certain endpoints), visibility (public/internal), naming strategy, and other config. Manually re-implementing config resolution and re-parsing the spec in a third-party tool is error-prone and will drift when the generator's filter or naming rules change. Staying in sync with the generator's **resolved** output is what extension tools need—not access to internal data structures.

**Use case:** [Kawarimi](https://github.com/novr/Kawarimi) is a SwiftPM Build Tool Plugin that today: (1) Invokes the official generator (via `_OpenAPIGeneratorCore`) to produce Types, Client, and Server; (2) Loads the same OpenAPI spec and config again and re-resolves filter, visibility, etc.; (3) Generates extra files: a `ClientTransport` mock and an `APIProtocol` default implementation. Any mismatch in filter or visibility between (1) and (2) leads to inconsistent generated code. Current workaround: re-parsing and re-resolving in a separate process, which duplicates logic and can drift from the generator's behavior.

## Proposed solution

**Possible directions (overview):**

- **Option A – Callback / delegate:** The generator accepts an optional callback that receives the resolved document and config and can write extra files. Extension logic runs in the same process as the generator.
- **Option B – CLI-based contract:** The generator optionally exports its "Resolved Context" (post-filtered document + resolved config) to a file. A separate process (e.g. another build tool) reads that file and generates additional Swift. No internal API exposure; only a documented file format.
- **Option C – Pluggable generator list:** The generator supports a list of "modes" or pluggable implementations (including third-party) so one build command produces both built-in and custom outputs in the same process.

We recommend **Option B** for process isolation, no dependency clash risk, and no stability burden on internal types. Below is the concrete shape we have in mind.

**Option B refined ("Resolved Context" export):**

- **No internal API exposure.** The generator does not expose or stabilize `_OpenAPIGeneratorCore` or other internal types. Extension tools do not link against the generator's internals.
- **CLI-based contract.** The generator gains an optional way to **export** its "Resolved Context" (e.g. post-filtered OpenAPI document + resolved configuration) to a file (e.g. JSON or a documented format). A separate process (e.g. Kawarimi) reads that file and generates additional Swift. Example: a `--save-resolved-config ` (or similar) flag that writes the resolved context after the main generation run.
- **Process isolation and version safety.** Extension tools run in a separate process; no risk of dependency clashes (e.g. different SwiftSyntax or OpenAPIKit versions) inside the generator process.
- **Opt-in and non-blocking.** The export step runs only when explicitly requested. Default runs are unchanged. Extension tools are separate build commands and do not block the generator's step.

**Benefits:** Single source of truth; custom outputs stay in sync with filter, visibility, naming; zero maintenance burden for core (no linking against third-party code, no stability guarantee on internal types); enables mock transports, default handlers, and other extensions.

**Anticipated concerns:**

| Concern | Response |
|--------|----------|
| "Exposing core logic will freeze internal data structures." | We are **not** asking for internal API exposure. Only an **exported artifact** (resolved document + config) in a documented format. Internal types can evolve; only the export format needs a stability story. |
| "Hooks could slow down builds." | The mechanism is **opt-in**. Extension tools run as **separate** build commands. |
| "Third-party tools might pull in conflicting dependencies." | **Process separation** (Option B): extension tools use their own dependencies in their own process. No dependency hell inside the core. |

## Alternatives considered

- **Option A (callback in-process):** Would require the core to load or depend on third-party code, risking dependency hell and forcing stability guarantees on internal types. We do not recommend it.
- **Option C (pluggable generator list in one process):** Similar dependency and pipeline complexity; we prefer a clear separation: generator writes resolved context; extension reads it in another process.
- **No export:** Third-party tools keep re-parsing spec and config. Current approach; works but duplicates logic and can drift from generator behavior.

## Additional information

- Use case / reference: [Kawarimi](https://github.com/novr/Kawarimi) (ClientTransport mock, APIProtocol default implementation).
- We can propose a concrete schema for the exported file (which metadata to include) and contribute to a prototype if that would help.
- Open questions: (1) Is adding an optional "export resolved context" (e.g. `--save-resolved-config `) within the desired scope? (2) What format and schema would fit the project's goals? (3) Are there existing CLI flags or plugin outputs we could align with?

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the generator's existing CLI flags and plugin outputs, which the issue identifies as open questions. Define the scope and documented schema for an opt-in resolved-context artifact, with completion requiring agreement on the export format and behavior for extension tools such as Kawarimi.

Written by the indexing model from the issue text.

Assessment

Tech stack
openapi, swift
Domain
cli, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.