Skip to content

feat: add tsoa for API type control and documentation#1501

Open
Andreybest wants to merge 12 commits into
finos:mainfrom
Andreybest:1430-api-checking-docs
Open

feat: add tsoa for API type control and documentation#1501
Andreybest wants to merge 12 commits into
finos:mainfrom
Andreybest:1430-api-checking-docs

Conversation

@Andreybest
Copy link
Copy Markdown
Contributor

Resolves #1430.

Add tsoa for endpoint type checking and generation of OpenAPI documentation. Generates swagger.json to /dist folder.
All tests for endpoints that were present, passes (with minor changes), all logic is preserved.

Caveats:

  1. tsoa checks for field presence, but does not check if string in field is empty, thus should be checked manually (or I've missed something in configuration). For example: POST api/v1/push/{id}/reject (rejectPush), if empty or whitespaces provided, will not check for it, thus old logic for theck with .trim() is left.
  2. tsoa has a configuration field noImplicitAdditionalProperties, that allows to change behavior of endpoints for rejecting of excess fields. Currently set to ignore due to POST api/v1/repo (createRepo), this endpoint passes body to a db.createRepo(body), and inner type expects additionalProperties that are passed to a row in a DB. Question: is this expected or not? If not, maybe we should enable more strict mode on noImplicitAdditionalProperties? :)

@Andreybest Andreybest requested a review from a team as a code owner April 10, 2026 12:54
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 10, 2026

Deploy Preview for endearing-brigadeiros-63f9d0 canceled.

Name Link
🔨 Latest commit a1650eb
🔍 Latest deploy log https://app.netlify.com/projects/endearing-brigadeiros-63f9d0/deploys/6a0b32f7525b820008917418

@Andreybest Andreybest requested a review from jescalada April 10, 2026 12:54
Copy link
Copy Markdown
Contributor

@jescalada jescalada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution, @Andreybest! 🚀

Things are looking good so far, just a few things to mention other than the code comments:

  • It'd be great to have screenshots of the generated OpenAPI spec to see if things are working as we hoped
  • I noticed a duplicate interface (AttestationAnswer) and am wondering if there aren't other interfaces that can be reused or combined into one
  • Test coverage seems to go down somewhat (-1.5%), we should improve coverage on any code additions such as proxyStore.ts, etc.

We might need another review since the changes are quite large @finos/git-proxy-maintainers

Comment thread package.json
Comment thread src/app.ts
Comment thread src/service/authentication.ts
Comment thread src/service/controllers/AuthController.ts Outdated
Comment thread src/service/controllers/AuthController.ts Outdated

if (currentHosts.length < previousHosts.length) {
console.log('Restarting the proxy to remove a host');
const proxy = getProxy();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another bit to double-check for proper restart behaviour

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again probably missing a call to RegisterRoutes(app);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answered in comment above

Comment thread src/service/interfaces/common.interfaces.ts
Comment thread test/services/routes/auth.test.ts
Comment thread test/services/routes/users.test.ts Outdated
Comment thread tsoa.json
@kriswest
Copy link
Copy Markdown
Contributor

@jescalada and @Andreybest There is a docusaurus plugin for rendering OpenAPI docs at:

https://docusaurus-openapi.tryingpan.dev/
https://github.com/PaloAltoNetworks/docusaurus-openapi-docs

Whereas in the FDC3 website we use a very simple static page and the Redoc lib to render the same: https://github.com/finos/FDC3/blob/main/website/src/pages/schemas/next/app-directory.html

Note that you have to link to this as an external link or docusaurus will return a 404 when navigating within the site:

https://github.com/finos/FDC3/blob/ffea3be0735bdd7a72ffba5473addfe49535833e/website/docs/app-directory/spec.md?plain=1#L7-L13

@Andreybest
Copy link
Copy Markdown
Contributor Author

Thank you for the review @jescalada !
Can you please review it again? Applied changes to most of your comments :)

  1. Screenshot of swagger
image 2. Duplicate removed, quickly checked, should be no more repetiotions (but not sure) 3. Don't see a message from code cov bot on this matter, can you please show me where I can find a code coverage stats?

@Andreybest
Copy link
Copy Markdown
Contributor Author

Checked all commits on main branch for new changes to logic for endpoints. None was changed, checked up to commit 6981427c50a5e5ccd3e91a2d4229b27135f8dcc3

Comment thread package.json Outdated
Co-authored-by: Fabio Vincenzi <93596376+fabiovincenzi@users.noreply.github.com>
Signed-off-by: Andrew <andrey255@live.com>
@Andreybest
Copy link
Copy Markdown
Contributor Author

Thanks for change @fabiovincenzi ! Added your suggested change.

@Andreybest
Copy link
Copy Markdown
Contributor Author

Checked all commits on main branch for new changes to logic for endpoints. None was changed, checked up to commit: ad58c5a47f64b6380da1ce1d7f6556c17e7e9efc

@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

❌ Patch coverage is 86.59966% with 240 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.48%. Comparing base (4c6e8d4) to head (f206b81).

Files with missing lines Patch % Lines
src/service/generatedRoutes.ts 87.08% 139 Missing ⚠️
src/service/controllers/AuthController.ts 76.43% 42 Missing and 3 partials ⚠️
src/service/controllers/PushController.ts 90.85% 15 Missing and 1 partial ⚠️
src/service/authentication.ts 77.35% 10 Missing and 2 partials ⚠️
src/service/index.ts 60.86% 9 Missing ⚠️
src/service/controllers/RepoController.ts 95.78% 7 Missing and 1 partial ⚠️
src/service/controllers/HomeController.ts 53.84% 6 Missing ⚠️
src/service/proxyStore.ts 70.00% 3 Missing ⚠️
src/app.ts 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1501      +/-   ##
==========================================
- Coverage   90.25%   89.48%   -0.77%     
==========================================
  Files          69       71       +2     
  Lines        5561     6612    +1051     
  Branches      958      970      +12     
==========================================
+ Hits         5019     5917     +898     
- Misses        523      673     +150     
- Partials       19       22       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@re-vlad re-vlad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just small non critical change requested

Comment thread tsoa.json Outdated
@@ -0,0 +1,26 @@
{
"entryFile": "src/app.ts",
"noImplicitAdditionalProperties": "ignore",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows arbitrary additional properties in request bodies. The current implementation in createRepo() passes the entire body to db.createRepo(body), but this should be validated against a strict schema. The db schema should be the source of truth, not the API layer accepting arbitrary data. So, change "noImplicitAdditionalProperties": "ignore" to "noImplicitAdditionalProperties": "throw"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @re-vlad, thanks for the concern. That is actually what I pointed out in my PR description no. 2 point. And I agree with you.

@kriswest and @jescalada would appreciate your comment on this matter.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with setting noImplicitAdditionalProperties to throw 👍🏼

Can this be done by adding proper types to the request body? You can see what the body looks like in src/ui/services/repo.ts:

const addRepo = async (repo: RepoView): Promise<ServiceResult<RepoView>> => {
  const apiV1Base = await getApiV1BaseUrl();
  const url = new URL(`${apiV1Base}/repo`);

  try {
    const response = await axios.post<RepoView>(url.toString(), repo, getAxiosConfig());
    return successResult(response.data);
  } catch (error: unknown) {
    return errorResult(error, 'Failed to add repository');
  }
};

Note that repo is of RepoView type, which is just an extended version of the database Repo:

export interface RepoView extends Repo {
  proxyURL: string;
  lastModified?: string;
  dateCreated?: string;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed "noImplicitAdditionalProperties" to "throw-on-extras", and fixed tests to accommodate this change.

Comment thread src/service/index.ts
import { serverConfig } from '../config/env';
import { Proxy } from '../proxy';
import routes from './routes';
import { RegisterRoutes } from './generatedRoutes';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this file checked in @Andreybest ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is generated during build

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not commit it, you suggest it to be included in repo?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A perennial question! I've tended to go with committing it as reviewing the generated code can often help you spot issues in what its generated from, and it helps someone trying to navigate through the code to understand something. Tooling such as SAST scanners an code coverage calculators may need it to be there to work as they should.

If committing generated code, then its worth either adding a commit hook (best to check for modifications in this) or PR check box to confirm its been done ;-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the concern!

Added generatedRoutes.ts to branch, and added pre-commit hook to lint-staged that will automatically stage changes to generatedRoutes.ts.

@Andreybest
Copy link
Copy Markdown
Contributor Author

Checked all commits on main branch for new changes to logic for endpoints. Only change with addition of https server, which required to change test files for https, would appreciate check on this.

Checked up to commit: 4c6e8d47d9189ee016d6f6a59adbd2f013c0666f

@Andreybest Andreybest requested a review from kriswest May 18, 2026 02:08
Copy link
Copy Markdown
Contributor

@jescalada jescalada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Andreybest Looks good so far, just wondering if you've dealt with Kris' comments above for the missing RegisterRoutes(app)

As for the "noImplicitAdditionalProperties": "ignore" setting, we might want to fix our typing so that it's possible to set that flag to "throw"! 👍🏼

@jescalada
Copy link
Copy Markdown
Contributor

jescalada commented May 18, 2026

Also, don't forget to run npm run format at the end to fix the CI 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve API types and documentation

5 participants