blob: b77302fbcd10f3b1625e0b190ce172a6f11749ef [file] [view]
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# OpenAPI Client Generation
This project uses [OpenAPI Generator](https://openapi-generator.tech/) to automatically generate the API client services and models based on the Apache Fineract Swagger specification.
## Configuration
The generator is configured in `package.json` and uses custom templates located in `templates/openapi-generator/`.
- **Output Directory**: `src/app/api/`
- **Spec Source**: `public/api/fineract.json` (preprocessed into `api-spec/fineract.json` during generation)
- **Custom Templates**: `templates/openapi-generator/licenseInfo.mustache` (adds Apache License header to all files)
- **Spec Preprocessor**: `scripts/preprocess-spec.mjs` (rewrites operationIds for stable method names — see below)
## Stable method names (important)
Generated method names are **stable across spec versions** by design. Without intervention, the
`typescript-angular` generator names methods from the spec's `operationId`s, which the Fineract spec
reuses across hundreds of endpoints; the generator then disambiguates them with a global,
document-order counter (`retrieveAll21`, `create6`, ...). Any spec change reshuffles every number and
breaks call sites throughout the app.
To prevent this, `npm run copy-swagger` runs `scripts/preprocess-spec.mjs`, which rewrites every
`operationId` to a deterministic value derived from the HTTP method + request path:
| Endpoint | Generated method |
| ------------------------------ | ----------------------------- |
| `GET /v1/clients` | `getClients` |
| `GET /v1/clients/{clientId}` | `getClientsClientId` |
| `PUT /v1/savingsaccounts/{id}` | `putSavingsaccountsAccountId` |
Because `(method, path)` is unique per OpenAPI, these names are collision-free and independent of
document order, so regenerating against a newer Fineract spec does **not** churn names. The
preprocessor also fills in any missing `responses.*.description`, so generation passes validation
without `--skip-validate-spec`. The committed spec (`public/api/fineract.json`) is never modified —
only the throwaway `api-spec/fineract.json` copy the generator consumes.
The rationale and alternatives considered are recorded in
[`DOCS/adr/0001-stable-openapi-operation-ids.md`](./adr/0001-stable-openapi-operation-ids.md).
## Commands
### Generate the API Client
To (re)generate the API client, run:
```bash
npm run generate-api
```
This command will:
1. **Preprocess** the spec (`copy-swagger`): run `scripts/preprocess-spec.mjs` to rewrite operationIds and patch missing response descriptions, writing `api-spec/fineract.json`.
2. **Clean** the previous output (`clean-api`): remove `src/app/api/api` and `src/app/api/model` so endpoints removed upstream do not leave orphan files behind (the generator never prunes).
3. Run the OpenAPI generator (`typescript-angular`, `ngVersion=22.0.7`) with the custom license header template.
### Update the Swagger Spec
**This is automated.** `.github/workflows/api-spec-sync.yml` runs weekly, and opens a pull
request whenever Apache Fineract's spec changes — with the removed operations and their call
sites listed in the body. See
[ADR 0002](adr/0002-automated-fineract-spec-sync.md). To run it on demand, use the workflow's
`workflow_dispatch` trigger; `dry_run: true` does everything except open the PR.
To do it by hand, replace `public/api/fineract.json` and run `npm run generate-api`. You can
also point at a spec elsewhere via the `FINERACT_SWAGGER_PATH` environment variable. Because
method names are stable (see above), most call sites continue to compile; only genuinely
added/removed/renamed endpoints need attention.
> **Upstream serves the spec minified; the committed copy is Prettier-formatted**, and
> `public/` is not in `.prettierignore`. Run `npm run format` after replacing the file or CI's
> `format` job fails on a single 1.4 MB line.
The spec can be read straight out of the published image without booting anything:
```bash
CID=$(docker create apache/fineract:latest)
docker cp "$CID:/app/resources/static/fineract.json" ./fineract.json
docker rm -f "$CID"
```
### Provenance
`public/api/fineract.provenance.json` records where the committed spec came from: the image
reference and digest, the upstream commit, `info.version`, path/operation/schema counts, and
hashes of both the raw upstream bytes and the committed file. It is written by the sync
workflow — do not edit it by hand.
## Maintenance
### Custom Templates
If you need to customize the generated code further (e.g., adding common interceptors or changing the way models are generated), you can add more `.mustache` files to the `templates/openapi-generator/` directory.
### Ignoring Files
To prevent the generator from overwriting or creating certain files, add them to the `.openapi-generator-ignore` file in the root of the project. Currently ignored:
- `git_push.sh`
- `README.md` (inside `src/app/api/`)
- `.gitignore` (inside `src/app/api/`)