With web applications a separation between client and server is commonplace nowadays: While the server (also often called back-end) deals with the underlying model, data storage and the predominant part of the business logic, the user interface and user-facing behaviour in general is realised with JavaScript, HTML and CSS on the client (also referred to as front-end), i.e. the user’s browser.

Frequently, frameworks such as Angular are used in order to facilitate development and make code easier to read and generally more accessible, for example by imposing a standard structure on projects and by placing specific code artefacts at specific locations so developers who’re unfamiliar with a project nevertheless will quickly find their way around.

The two sides of such a web application typically communicate via HTTP-based RESTful APIs provided by the server.

This clear separation between client and server side has numerous benefits, e.g.

flexibility: The business logic implementation isn’t tied to a specific view technology.

scalability: Server and client can be deployed independently. Moreover, the client runs on the user’s machine and therefore doesn’t necessarily or directly affect server resources.

offline capabilities: Even if the server isn’t reachable the application can continue to run (see Progressive Web Apps (PWAs)) and resynchronise when the server becomes available again.

However, as with almost any design pattern, this separation also comes with downsides, one of which is the need to keep your client-side model in sync with its server-side counterpart. If you don’t pay close attention to this the model on the server and that on the client over time will inevitably diverge, which in turn will make your software much harder to maintain.

Currently though, I’m involved in creating a workflow support tool that uses Spring Data REST for providing REST resources and Spring REST Docs for documenting the API (a task that’s otherwise often delegated to Swagger, too because while Swagger is a comprehensive API toolkit its most obvious and immediate benefit is an automatically generated human-readable API documentation). As for client development Angular and TypeScript are used for this workflow tool.

So, a Swagger or OpenAPI definition to generate a TypeScript client from would be expedient.

I thought: “Spring REST Docs also provides a machine-readable API definition because it can not just be used for documenting an API.” In fact, that’s almost just a byproduct of its main purpose: Writing accessible acceptance tests for APIs that serve as both API definition and documentation.

So, I did a bit of research and asked around but couldn’t quite find what I was looking for. Puzzled, because I couldn’t believe I really was the first one to encounter this problem, it dawned on me that I was thinking too complicated: Spring Data REST already supplies metadata about the API it provides, particularly about the data types used!

Usually, it does so in a format called Application-Level Profile Semantics (ALPS). While certainly useful this format doesn’t lend itself particularly well to being processed in JavaScript (or TypeScript as in the case of Angular) applications.

What I still needed though, was a way to not just read a JSON file – or a bunch of those – but to iterate over all the REST API endpoints provided by the server via HTTP and process the metadata supplied by each of those.

Therefore, I created an npm package called spring-data-rest-json-schema-to-typescript-definitions that solves this problem in a reusable fashion. This will hopefully allow others – including my future self – can build upon this in their Angular (or in fact any TypeScript-based) applications. Generating TypeScript declarations in this manner should help you keep your data model in sync between client and server and therefore increase overall software quality.