Skip to content

Commit d718a1f

Browse files
authored
chore: improve and extend README content (#157)
1 parent 50bfdfd commit d718a1f

File tree

1 file changed

+287
-43
lines changed

1 file changed

+287
-43
lines changed

README.md

Lines changed: 287 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,36 @@
1+
<h1 align="center">
2+
<img
3+
src="https://github.com/user-attachments/assets/4d3bf8ba-8cbf-4673-9e6b-2cd30c9685d0"
4+
alt="API doc parser"
5+
width="250"
6+
height="250">
7+
</h1>
8+
19
# API Doc Parser
210

3-
[![GitHub Actions](https://github.com/api-platform/api-doc-parser/workflows/CI/badge.svg?branch=main)](https://github.com/api-platform/api-doc-parser/actions?query=workflow%3ACI+branch%3Amain)
11+
**Effortlessly turn Hydra, Swagger/OpenAPI, and GraphQL specs into actionable data for your tools and apps.**
12+
13+
[![CI](https://github.com/api-platform/api-doc-parser/actions/workflows/ci.yml/badge.svg)](https://github.com/api-platform/api-doc-parser/actions/workflows/ci.yml)
14+
[![GitHub License](https://img.shields.io/github/license/api-platform/api-doc-parser)](https://github.com/api-platform/api-doc-parser/blob/main/LICENSE)
15+
[![npm bundle size](https://img.shields.io/bundlephobia/minzip/@api-platform/api-doc-parser)](https://bundlephobia.com/package/@api-platform/api-doc-parser)
416
[![npm version](https://badge.fury.io/js/%40api-platform%2Fapi-doc-parser.svg)](https://badge.fury.io/js/%40api-platform%2Fapi-doc-parser)
17+
[![NPM Downloads](https://img.shields.io/npm/dw/%40api-platform%2Fapi-doc-parser)](https://img.shields.io/npm/dw/%40api-platform%2Fapi-doc-parser)
518

6-
`api-doc-parser` is a standalone TypeScript library to parse [Hydra](http://hydra-cg.com), [Swagger](https://swagger.io/specification/v2/), [OpenAPI](https://github.com/OAI/OpenAPI-Specification#the-openapi-specification) and [GraphQL](https://graphql.org/) documentations
7-
and transform them in an intermediate representation.
8-
This data structure can then be used for various tasks such as creating smart API clients,
9-
scaffolding code or building administration interfaces.
19+
---
1020

11-
It plays well with the [API Platform](https://api-platform.com) framework.
21+
**`api-doc-parser` is a standalone TypeScript library that parses [Hydra](https://www.hydra-cg.com/), [Swagger](https://swagger.io/specification/v2/), [OpenAPI](https://github.com/OAI/OpenAPI-Specification#the-openapi-specification), and [GraphQL](https://graphql.org/) documentation into a unified, intermediate representation.**
22+
This normalized structure enables smart API clients, code generators, admin interfaces, and more.
23+
It integrates seamlessly with the [API Platform](https://api-platform.com/) framework.
1224

13-
## Install
25+
## ✨ Key Features
1426

15-
With [Yarn](https://yarnpkg.com/):
27+
- **Unified output** – one normalized `Api` object covering resources, fields, operations, parameters, and relations
28+
- **TypeScript-first** – strict typings for every parsed element
29+
- **Embedded & referenced resources** resolved automatically
30+
- **Framework integration** – easily integrates with the API Platform ecosystem
31+
- **Supports all major API formats** – Hydra, Swagger/OpenAPI v2, OpenAPI v3, and GraphQL
1632

17-
yarn add @api-platform/api-doc-parser
33+
## 📦 Installation
1834

1935
Using [NPM](https://www.npmjs.com/):
2036

@@ -24,19 +40,23 @@ Using [Pnpm](https://pnpm.io/):
2440

2541
pnpm add @api-platform/api-doc-parser
2642

27-
If you plan to use the library with Node, you also need a polyfill for the `fetch` function:
43+
With [Yarn](https://yarnpkg.com/):
44+
45+
yarn add @api-platform/api-doc-parser
46+
47+
Using [Bun](https://bun.sh/):
2848

29-
yarn add isomorphic-fetch
49+
bun add @api-platform/api-doc-parser
3050

31-
## Usage
51+
## 🚀 Usage
3252

3353
**Hydra**
3454

3555
```javascript
3656
import { parseHydraDocumentation } from "@api-platform/api-doc-parser";
3757

38-
parseHydraDocumentation("https://demo.api-platform.com").then(({ api }) =>
39-
console.log(api),
58+
const { api, response, status } = await parseHydraDocumentation(
59+
"https://demo.api-platform.com",
4060
);
4161
```
4262

@@ -45,8 +65,8 @@ parseHydraDocumentation("https://demo.api-platform.com").then(({ api }) =>
4565
```javascript
4666
import { parseSwaggerDocumentation } from "@api-platform/api-doc-parser";
4767

48-
parseSwaggerDocumentation("https://demo.api-platform.com/docs.json").then(
49-
({ api }) => console.log(api),
68+
const { api, response, status } = await parseSwaggerDocumentation(
69+
"https://demo.api-platform.com/docs.json",
5070
);
5171
```
5272

@@ -55,52 +75,276 @@ parseSwaggerDocumentation("https://demo.api-platform.com/docs.json").then(
5575
```javascript
5676
import { parseOpenApi3Documentation } from "@api-platform/api-doc-parser";
5777

58-
parseOpenApi3Documentation(
59-
"https://demo.api-platform.com/docs.json?spec_version=3",
60-
).then(({ api }) => console.log(api));
78+
const { api, response, status } = await parseOpenApi3Documentation(
79+
"https://demo.api-platform.com/docs.jsonopenapi?spec_version=3.0.0",
80+
);
6181
```
6282

6383
**GraphQL**
6484

6585
```javascript
6686
import { parseGraphQl } from "@api-platform/api-doc-parser";
6787

68-
parseGraphQl("https://demo.api-platform.com/graphql").then(({ api }) =>
69-
console.log(api),
88+
const { api, response } = await parseGraphQl(
89+
"https://demo.api-platform.com/graphql",
7090
);
7191
```
7292

73-
## OpenAPI Support
93+
## ![TypeScript](https://api.iconify.design/vscode-icons:file-type-typescript-official.svg?color=%23888888&width=26&height=26) Type definitions
94+
95+
Each parse function returns a Promise that resolves to an object containing the normalized API structure, the raw documentation, and the HTTP status code:
7496

75-
In order to support OpenAPI, the library makes some assumptions about how the documentation relates to a corresponding ressource:
97+
#### OpenAPI 3
98+
99+
```typescript
100+
function parseOpenApi3Documentation(
101+
entrypointUrl: string,
102+
options?: RequestInitExtended,
103+
): Promise<{
104+
api: Api;
105+
response: OpenAPIV3.Document;
106+
status: number;
107+
}>;
108+
```
76109

77-
- The path to get (`GET`) or edit (`PUT`) one resource looks like `/books/{id}` (regular expression used: `^[^{}]+/{[^{}]+}/?$`).
78-
Note that `books` may be a singular noun (`book`).
79-
If there is no path like this, the library skips the resource.
80-
- The corresponding path schema is retrieved for `get` either in the [`response` / `200` / `content` / `application/json`] path section or in the `components` section of the documentation.
81-
If retrieved from the `components` section, the component name needs to look like `Book` (singular noun).
82-
For `put`, the schema is only retrieved in the [`requestBody` / `content` / `application/json`] path section.
83-
If no schema is found, the resource is skipped.
84-
- If there are two schemas (one for `get` and one for `put`), resource fields are merged.
85-
- The library looks for a creation (`POST`) and list (`GET`) path. They need to look like `/books` (plural noun).
86-
- The deletion (`DELETE`) path needs to be inside the get / edit path.
87-
- In order to reference the resources between themselves (embeddeds or relations), the library guesses embeddeds or references from property names.
88-
For instance if a book schema has a `reviews` property, the library tries to find a `Review` resource.
89-
If there is, a relation or an embedded between `Book` and `Review` resources is made for the `reviews` field.
90-
The property name can also be like `review_id`, `reviewId`, `review_ids` or `reviewIds` for references.
91-
- Parameters are only retrieved in the list path.
110+
#### Swagger
92111

93-
## Support for other formats (JSON:API...)
112+
```typescript
113+
function parseSwaggerDocumentation(entrypointUrl: string): Promise<{
114+
api: Api;
115+
response: OpenAPIV2.Document;
116+
status: number;
117+
}>;
118+
```
119+
120+
#### Hydra
121+
122+
```typescript
123+
function parseHydraDocumentation(
124+
entrypointUrl: string,
125+
options?: RequestInitExtended,
126+
): Promise<{
127+
api: Api;
128+
response: Response;
129+
status: number;
130+
}>;
131+
```
132+
133+
#### GraphQL
134+
135+
```typescript
136+
function parseGraphQl(
137+
entrypointUrl: string,
138+
options?: RequestInit,
139+
): Promise<{
140+
api: Api;
141+
response: Response;
142+
}>;
143+
```
144+
145+
### Api
146+
147+
Represents the root of the parsed API, containing the entrypoint URL, an optional title, and a list of resources.
148+
149+
```typescript
150+
interface Api {
151+
entrypoint: string;
152+
title?: string;
153+
resources?: Resource[];
154+
}
155+
```
156+
157+
### Resource
158+
159+
Describes an API resource (such as an entity or collection), including its fields, operations, and metadata.
160+
161+
```typescript
162+
interface Resource {
163+
name: string | null;
164+
url: string | null;
165+
id?: string | null;
166+
title?: string | null;
167+
description?: string | null;
168+
deprecated?: boolean | null;
169+
fields?: Field[] | null;
170+
readableFields?: Field[] | null;
171+
writableFields?: Field[] | null;
172+
parameters?: Parameter[] | null;
173+
getParameters?: () => Promise<Parameter[]> | null;
174+
operations?: Operation[] | null;
175+
}
176+
```
177+
178+
### Field
179+
180+
Represents a property of a resource, including its type, constraints, and metadata.
181+
182+
```typescript
183+
interface Field {
184+
name: string | null;
185+
id?: string | null;
186+
range?: string | null;
187+
type?: FieldType | null;
188+
arrayType?: FieldType | null;
189+
enum?: { [key: string | number]: string | number } | null;
190+
reference?: string | Resource | null;
191+
embedded?: Resource | null;
192+
required?: boolean | null;
193+
nullable?: boolean | null;
194+
description?: string | null;
195+
maxCardinality?: number | null;
196+
deprecated?: boolean | null;
197+
}
198+
```
199+
200+
### Parameter
201+
202+
Represents a query parameter for a collection/list operation, such as a filter or pagination variable.
203+
204+
```typescript
205+
interface Parameter {
206+
variable: string;
207+
range: string | null;
208+
required: boolean;
209+
description: string;
210+
deprecated?: boolean;
211+
}
212+
```
213+
214+
### FieldType
215+
216+
Enumerates the possible types for a field, such as string, integer, date, etc.
217+
218+
```typescript
219+
type FieldType =
220+
| "string"
221+
| "integer"
222+
| "negativeInteger"
223+
| "nonNegativeInteger"
224+
| "positiveInteger"
225+
| "nonPositiveInteger"
226+
| "number"
227+
| "decimal"
228+
| "double"
229+
| "float"
230+
| "boolean"
231+
| "date"
232+
| "dateTime"
233+
| "duration"
234+
| "time"
235+
| "byte"
236+
| "binary"
237+
| "hexBinary"
238+
| "base64Binary"
239+
| "array"
240+
| "object"
241+
| "email"
242+
| "url"
243+
| "uuid"
244+
| "password"
245+
| string;
246+
```
247+
248+
### Operation
249+
250+
Represents an operation (such as GET, POST, PUT, PATCH, DELETE) that can be performed on a resource.
251+
252+
```typescript
253+
interface Operation {
254+
name: string | null;
255+
type: "show" | "edit" | "delete" | "list" | "create" | null;
256+
method?: string | null;
257+
expects?: any | null;
258+
returns?: string | null;
259+
types?: string[] | null;
260+
deprecated?: boolean | null;
261+
}
262+
```
263+
264+
## 📖 OpenAPI Support
265+
266+
`api-doc-parser` applies a predictable set of rules when interpreting an OpenAPI document.
267+
If a rule is not met, the resource concerned is silently skipped.
268+
| Rule | Details |
269+
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
270+
| **Single-item path pattern** | A `GET` (read) or **`PUT`/`PATCH`** (update) endpoint **must** match:<br/>`/books/{id}` (regex&nbsp;`^[^{}]+/{[^{}]+}/?$`).<br/>`books` may be singular (`/book/{id}`). |
271+
| **Schema discovery** | **GET** → first searches `responses → 200 → content → application/json`; if missing, falls back to `components` (component name must be singular, e.g. `Book`).<br/>**PUT/PATCH** → only `requestBody → content → application/json` is considered.<br/>If both GET & PUT/PATCH schemas exist, their fields are **merged**. |
272+
| **Collection paths** | A create (`POST`) or list (`GET`) endpoint **must** be plural:<br/>`/books`. |
273+
| **Deletion path** | `DELETE` must live under the single-item GET path (`/books/{id}`). |
274+
| **Relations & Embeddeds** | Links between resources are inferred from property names and their JSON schema:<br/>• **Plural object/array properties** (e.g. `reviews`, `authors`) become **embedded** resources when their item schema matches an existing resource (`Review`, `Author`).<br/>• **ID-like properties** (e.g. `review_id`, `reviewId`, `review_ids`, `reviewIds`, `authorId`) are treated as **references** to that resource.<br/>• As a result, fields such as **`reviews`** (object/array) and **`review_ids`** (scalar/array of IDs) each point to the **same** `Review` resource, one flagged _embedded_, the other _reference_. |
275+
| **Parameter extraction** | Parameters are read **only** from the list path (`/books`). |
276+
277+
## 🧩 Support for other formats (JSON:API, AsyncAPI...)
94278

95279
API Doc Parser is designed to parse any API documentation format and convert it in the same intermediate representation.
96280
If you develop a parser for another format, please [open a Pull Request](https://github.com/api-platform/api-doc-parser/pulls)
97281
to include it in the library.
98282

99-
## Run tests
283+
## 🤝 Contributing
284+
285+
Contributions are welcome! To contribute:
286+
287+
1. **Read our [Code of Conduct](https://github.com/api-platform/api-doc-parser?tab=coc-ov-file#contributor-code-of-conduct).**
288+
289+
2. **Fork the repository and create a feature branch.**
290+
291+
3. **Install dependencies**
100292

101-
pnpm test
102-
pnpm lint
293+
```bash
294+
pnpm install
295+
```
103296

104-
## Credits
297+
4. **Adhere to the code style**
298+
299+
```bash
300+
pnpm lint:fix
301+
```
302+
303+
```bash
304+
pnpm format
305+
```
306+
307+
5. **Run tests**
308+
309+
```bash
310+
pnpm test
311+
```
312+
313+
6. **Ensure type correctness**
314+
315+
```bash
316+
pnpm typecheck
317+
```
318+
319+
7. **Submit a pull request with a clear description of your changes.**
320+
321+
## 👥 Contributors
322+
323+
[![Contributors](https://contrib.rocks/image?repo=api-platform/api-doc-parser)](https://github.com/api-platform/api-doc-parser/graphs/contributors)
324+
325+
## 🌟 Star History
326+
327+
<a href="https://www.star-history.com/#api-platform/api-doc-parser&Date">
328+
<picture>
329+
<source
330+
media="(prefers-color-scheme: dark)"
331+
srcset="https://api.star-history.com/svg?repos=api-platform/api-doc-parser&type=Date&theme=dark"
332+
/>
333+
<source
334+
media="(prefers-color-scheme: light)"
335+
srcset="https://api.star-history.com/svg?repos=api-platform/api-doc-parser&type=Date"
336+
/>
337+
<img
338+
alt="Star History Chart"
339+
src="https://api.star-history.com/svg?repos=api-platform/api-doc-parser&type=Date"
340+
/>
341+
</picture>
342+
</a>
343+
344+
## 🙌 Credits
105345

106346
Created by [Kévin Dunglas](https://dunglas.fr). Sponsored by [Les-Tilleuls.coop](https://les-tilleuls.coop).
347+
348+
## 🔒 License
349+
350+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

0 commit comments

Comments
 (0)